package jdk.internal.foreign.abi;
import jdk.incubator.foreign.MemoryLayouts;
import jdk.incubator.foreign.MemorySegment;
import java.io.PrintStream;
import java.lang.invoke.VarHandle;
import java.util.HashMap;
import java.util.Map;
class BufferLayout {
static final VarHandle VH_LONG = MemoryLayouts.JAVA_LONG.varHandle(long.class);
final long size;
final long arguments_next_pc;
final long stack_args_bytes;
final long stack_args;
final long[] input_type_offsets;
final long[] output_type_offsets;
private final Map<jdk.internal.foreign.abi.VMStorage, Long> argOffsets;
private final Map<jdk.internal.foreign.abi.VMStorage, Long> retOffsets;
private BufferLayout(long size, long arguments_next_pc, long stack_args_bytes, long stack_args,
long[] input_type_offsets, long[] output_type_offsets,
Map<jdk.internal.foreign.abi.VMStorage, Long> argOffsets, Map<jdk.internal.foreign.abi.VMStorage, Long> retOffsets) {
this.size = size;
this.arguments_next_pc = arguments_next_pc;
this.stack_args_bytes = stack_args_bytes;
this.stack_args = stack_args;
this.input_type_offsets = input_type_offsets;
this.output_type_offsets = output_type_offsets;
this.argOffsets = argOffsets;
this.retOffsets = retOffsets;
}
static BufferLayout of(ABIDescriptor abi) {
long offset = 0;
offset = SharedUtils.alignUp(offset, 8);
long arguments_next_pc = offset;
offset += 8;
offset = SharedUtils.alignUp(offset, 8);
long stack_args_bytes = offset;
offset += 8;
offset = SharedUtils.alignUp(offset, 8);
long stack_args = offset;
offset += 8;
Map<jdk.internal.foreign.abi.VMStorage, Long> argOffsets = new HashMap<>();
long[] input_type_offsets = new long[abi.inputStorage.length];
for (int i = 0; i < abi.inputStorage.length; i++) {
long size = abi.arch.typeSize(i);
offset = SharedUtils.alignUp(offset, size);
input_type_offsets[i] = offset;
for (jdk.internal.foreign.abi.VMStorage store : abi.inputStorage[i]) {
argOffsets.put(store, offset);
offset += size;
}
}
Map<jdk.internal.foreign.abi.VMStorage, Long> retOffsets = new HashMap<>();
long[] output_type_offsets = new long[abi.outputStorage.length];
for (int i = 0; i < abi.outputStorage.length; i++) {
long size = abi.arch.typeSize(i);
offset = SharedUtils.alignUp(offset, size);
output_type_offsets[i] = offset;
for (jdk.internal.foreign.abi.VMStorage store : abi.outputStorage[i]) {
retOffsets.put(store, offset);
offset += size;
}
}
return new BufferLayout(offset, arguments_next_pc, stack_args_bytes, stack_args,
input_type_offsets, output_type_offsets, argOffsets, retOffsets);
}
long argOffset(jdk.internal.foreign.abi.VMStorage storage) {
return argOffsets.get(storage);
}
long retOffset(jdk.internal.foreign.abi.VMStorage storage) {
return retOffsets.get(storage);
}
private static String getLongString(MemorySegment buffer, long offset) {
return Long.toHexString((long) VH_LONG.get(buffer.asSlice(offset)));
}
private static void dumpValues(jdk.internal.foreign.abi.Architecture arch, MemorySegment buff, PrintStream stream,
Map<jdk.internal.foreign.abi.VMStorage, Long> offsets) {
for (var entry : offsets.entrySet()) {
VMStorage storage = entry.getKey();
stream.print(storage.name());
stream.print("={ ");
MemorySegment start = buff.asSlice(entry.getValue());
for (int i = 0; i < arch.typeSize(storage.type()) / 8; i += 8) {
stream.print(getLongString(start, i));
stream.print(" ");
}
stream.println("}");
}
}
void dump(Architecture arch, MemorySegment buff, PrintStream stream) {
stream.println("Next PC: " + getLongString(buff, arguments_next_pc));
stream.println("Stack args bytes: " + getLongString(buff, stack_args_bytes));
stream.println("Stack args ptr: " + getLongString(buff, stack_args));
stream.println("Arguments:");
dumpValues(arch, buff, stream, argOffsets);
stream.println("Returns:");
dumpValues(arch, buff, stream, retOffsets);
}
}