implements one-shot PBS boot guard in published wrapper lowering
This commit is contained in:
parent
64762ca227
commit
ce55cf6405
@ -240,9 +240,19 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
&& entryPointCallableName != null
|
||||
&& !entryPointCallableName.isBlank()
|
||||
&& !entryPointModuleId.isNone()) {
|
||||
final var existingBootGuard = globals.stream()
|
||||
.filter(global -> moduleIdsMatch(entryPointModuleId, global.moduleId()))
|
||||
.filter(global -> global.hiddenKind() == IRHiddenGlobalKind.BOOT_GUARD)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
final var bootGuardSlot = existingBootGuard != null
|
||||
? existingBootGuard.slot()
|
||||
: nextGlobalSlot(globals, entryPointModuleId);
|
||||
final var wrapperCallableId = new CallableId(callableSignatures.size());
|
||||
callableSignatures.add(new CallableSignatureRef(entryPointModuleId, entryPointCallableName, 0, "() -> unit"));
|
||||
final var instructions = new ArrayList<IRBackendExecutableFunction.Instruction>();
|
||||
instructions.add(getGlobalInstruction(bootGuardSlot, frameExecutable.span()));
|
||||
instructions.add(jumpIfTrueInstruction("bootstrap_done", frameExecutable.span()));
|
||||
for (final var moduleId : sortedModuleIds) {
|
||||
final var moduleInitCallableId = moduleInitCallableIds.get(moduleId);
|
||||
if (moduleInitCallableId == null) {
|
||||
@ -271,6 +281,9 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
0,
|
||||
frameExecutable.span()));
|
||||
}
|
||||
instructions.add(pushBoolInstruction(true, frameExecutable.span()));
|
||||
instructions.add(setGlobalInstruction(bootGuardSlot, frameExecutable.span()));
|
||||
instructions.add(labelInstruction("bootstrap_done", frameExecutable.span()));
|
||||
instructions.add(callInstruction(frameExecutable, frameExecutable.span()));
|
||||
instructions.add(retInstruction(frameExecutable.span()));
|
||||
executableFunctions.add(new IRBackendExecutableFunction(
|
||||
@ -287,15 +300,13 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
ReadOnlyList.wrap(instructions),
|
||||
frameExecutable.span()));
|
||||
|
||||
if (globals.stream().noneMatch(global ->
|
||||
moduleIdsMatch(entryPointModuleId, global.moduleId())
|
||||
&& global.hiddenKind() == IRHiddenGlobalKind.BOOT_GUARD)) {
|
||||
if (existingBootGuard == null) {
|
||||
globals.add(new IRGlobal(
|
||||
frameExecutable.fileId(),
|
||||
entryPointModuleId,
|
||||
PbsFrontendCompiler.bootGuardGlobalName(entryPointModuleId),
|
||||
"bool",
|
||||
0,
|
||||
bootGuardSlot,
|
||||
IRGlobalVisibility.MODULE,
|
||||
true,
|
||||
IRHiddenGlobalKind.BOOT_GUARD,
|
||||
@ -325,6 +336,19 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
.build();
|
||||
}
|
||||
|
||||
private int nextGlobalSlot(
|
||||
final ArrayList<IRGlobal> globals,
|
||||
final ModuleId moduleId) {
|
||||
var nextSlot = 0;
|
||||
for (final var global : globals) {
|
||||
if (!moduleIdsMatch(moduleId, global.moduleId())) {
|
||||
continue;
|
||||
}
|
||||
nextSlot = Math.max(nextSlot, global.slot() + 1);
|
||||
}
|
||||
return nextSlot;
|
||||
}
|
||||
|
||||
private ArrayList<IRGlobal> normalizeGlobalSlots(final ArrayList<IRGlobal> globals) {
|
||||
final var nextSlotByModule = new LinkedHashMap<ModuleId, Integer>();
|
||||
final var normalized = new ArrayList<IRGlobal>(globals.size());
|
||||
@ -390,6 +414,82 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
span);
|
||||
}
|
||||
|
||||
private IRBackendExecutableFunction.Instruction getGlobalInstruction(
|
||||
final int slot,
|
||||
final Span span) {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.GET_GLOBAL,
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
slot,
|
||||
null,
|
||||
span);
|
||||
}
|
||||
|
||||
private IRBackendExecutableFunction.Instruction setGlobalInstruction(
|
||||
final int slot,
|
||||
final Span span) {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.SET_GLOBAL,
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
slot,
|
||||
null,
|
||||
span);
|
||||
}
|
||||
|
||||
private IRBackendExecutableFunction.Instruction pushBoolInstruction(
|
||||
final boolean value,
|
||||
final Span span) {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.PUSH_BOOL,
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
value ? "true" : "false",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
span);
|
||||
}
|
||||
|
||||
private IRBackendExecutableFunction.Instruction labelInstruction(
|
||||
final String label,
|
||||
final Span span) {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.LABEL,
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
label,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
span);
|
||||
}
|
||||
|
||||
private IRBackendExecutableFunction.Instruction jumpIfTrueInstruction(
|
||||
final String targetLabel,
|
||||
final Span span) {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.JMP_IF_TRUE,
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
targetLabel,
|
||||
null,
|
||||
null,
|
||||
span);
|
||||
}
|
||||
|
||||
private ModuleId normalizeModuleId(final ModuleId moduleId) {
|
||||
return moduleId == null ? ModuleId.none() : moduleId;
|
||||
}
|
||||
|
||||
@ -369,15 +369,21 @@ class PBSFrontendPhaseServiceTest {
|
||||
.orElseThrow();
|
||||
assertTrue(bootGuard.isHidden());
|
||||
assertTrue(bootGuard.name().startsWith("__pbs.boot_guard$m"));
|
||||
assertEquals(1, bootGuard.slot());
|
||||
final var wrapper = irBackend.getExecutableFunctions().stream()
|
||||
.filter(function -> irBackend.getEntryPointCallableName().equals(function.callableName()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
assertEquals(4, wrapper.instructions().size());
|
||||
assertTrue(wrapper.instructions().get(0).calleeCallableName().startsWith("__pbs.module_init$m"));
|
||||
assertTrue(wrapper.instructions().get(1).calleeCallableName().startsWith("__pbs.project_init$m"));
|
||||
assertEquals("frame", wrapper.instructions().get(2).calleeCallableName());
|
||||
assertEquals(p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.RET, wrapper.instructions().get(3).kind());
|
||||
assertEquals(9, wrapper.instructions().size());
|
||||
assertEquals(p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.GET_GLOBAL, wrapper.instructions().get(0).kind());
|
||||
assertEquals(p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.JMP_IF_TRUE, wrapper.instructions().get(1).kind());
|
||||
assertTrue(wrapper.instructions().get(2).calleeCallableName().startsWith("__pbs.module_init$m"));
|
||||
assertTrue(wrapper.instructions().get(3).calleeCallableName().startsWith("__pbs.project_init$m"));
|
||||
assertEquals(p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.PUSH_BOOL, wrapper.instructions().get(4).kind());
|
||||
assertEquals(p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.SET_GLOBAL, wrapper.instructions().get(5).kind());
|
||||
assertEquals(p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.LABEL, wrapper.instructions().get(6).kind());
|
||||
assertEquals("frame", wrapper.instructions().get(7).calleeCallableName());
|
||||
assertEquals(p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.RET, wrapper.instructions().get(8).kind());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -35,6 +35,8 @@ public class BytecodeEmitter {
|
||||
private static final int OP_LTE = 0x3C;
|
||||
private static final int OP_GTE = 0x3D;
|
||||
private static final int OP_NEG = 0x3E;
|
||||
private static final int OP_GET_GLOBAL = 0x40;
|
||||
private static final int OP_SET_GLOBAL = 0x41;
|
||||
private static final int OP_GET_LOCAL = 0x42;
|
||||
private static final int OP_SET_LOCAL = 0x43;
|
||||
private static final int OP_PUSH_I32 = 0x17;
|
||||
@ -81,10 +83,18 @@ public class BytecodeEmitter {
|
||||
writeOpU32(code, OP_GET_LOCAL, op.immediate());
|
||||
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||
}
|
||||
case GET_GLOBAL -> {
|
||||
writeOpU32(code, OP_GET_GLOBAL, op.immediate());
|
||||
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||
}
|
||||
case SET_LOCAL -> {
|
||||
writeOpU32(code, OP_SET_LOCAL, op.immediate());
|
||||
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||
}
|
||||
case SET_GLOBAL -> {
|
||||
writeOpU32(code, OP_SET_GLOBAL, op.immediate());
|
||||
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||
}
|
||||
case PUSH_BOOL -> {
|
||||
writeOpU8(code, OP_PUSH_BOOL, op.immediate() == 0 ? 0 : 1);
|
||||
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||
@ -307,7 +317,9 @@ public class BytecodeEmitter {
|
||||
PUSH_CONST,
|
||||
POP,
|
||||
GET_LOCAL,
|
||||
GET_GLOBAL,
|
||||
SET_LOCAL,
|
||||
SET_GLOBAL,
|
||||
PUSH_BOOL,
|
||||
PUSH_I32,
|
||||
ADD,
|
||||
@ -397,10 +409,18 @@ public class BytecodeEmitter {
|
||||
return new Operation(OperationKind.GET_LOCAL, slot, null, null, null, span);
|
||||
}
|
||||
|
||||
public static Operation getGlobal(final int slot, final BytecodeModule.SourceSpan span) {
|
||||
return new Operation(OperationKind.GET_GLOBAL, slot, null, null, null, span);
|
||||
}
|
||||
|
||||
public static Operation setLocal(final int slot, final BytecodeModule.SourceSpan span) {
|
||||
return new Operation(OperationKind.SET_LOCAL, slot, null, null, null, span);
|
||||
}
|
||||
|
||||
public static Operation setGlobal(final int slot, final BytecodeModule.SourceSpan span) {
|
||||
return new Operation(OperationKind.SET_GLOBAL, slot, null, null, null, span);
|
||||
}
|
||||
|
||||
public static Operation pushBool(final boolean value, final BytecodeModule.SourceSpan span) {
|
||||
return new Operation(OperationKind.PUSH_BOOL, value ? 1 : 0, null, null, null, span);
|
||||
}
|
||||
|
||||
@ -37,6 +37,8 @@ public record IRVMOp(
|
||||
public static final IRVMOp LTE = new IRVMOp("LTE", 0x3C, 0, 2, 1, false, false, false);
|
||||
public static final IRVMOp GTE = new IRVMOp("GTE", 0x3D, 0, 2, 1, false, false, false);
|
||||
public static final IRVMOp NEG = new IRVMOp("NEG", 0x3E, 0, 1, 1, false, false, false);
|
||||
public static final IRVMOp GET_GLOBAL = new IRVMOp("GET_GLOBAL", 0x40, 4, 0, 1, false, false, false);
|
||||
public static final IRVMOp SET_GLOBAL = new IRVMOp("SET_GLOBAL", 0x41, 4, 1, 0, false, false, false);
|
||||
public static final IRVMOp GET_LOCAL = new IRVMOp("GET_LOCAL", 0x42, 4, 0, 1, false, false, false);
|
||||
public static final IRVMOp SET_LOCAL = new IRVMOp("SET_LOCAL", 0x43, 4, 1, 0, false, false, false);
|
||||
public static final IRVMOp INTERNAL_EXT = new IRVMOp("IRVM_EXT_NOP", 0xFFFF, 0, 0, 0, false, false, true);
|
||||
|
||||
@ -13,7 +13,9 @@ public final class IRVMProfileFeatureGate {
|
||||
IRVMOp.RET,
|
||||
IRVMOp.PUSH_CONST,
|
||||
IRVMOp.POP,
|
||||
IRVMOp.GET_GLOBAL,
|
||||
IRVMOp.GET_LOCAL,
|
||||
IRVMOp.SET_GLOBAL,
|
||||
IRVMOp.SET_LOCAL,
|
||||
IRVMOp.CALL,
|
||||
IRVMOp.JMP,
|
||||
@ -43,7 +45,9 @@ public final class IRVMProfileFeatureGate {
|
||||
IRVMOp.RET,
|
||||
IRVMOp.PUSH_CONST,
|
||||
IRVMOp.POP,
|
||||
IRVMOp.GET_GLOBAL,
|
||||
IRVMOp.GET_LOCAL,
|
||||
IRVMOp.SET_GLOBAL,
|
||||
IRVMOp.SET_LOCAL,
|
||||
IRVMOp.CALL,
|
||||
IRVMOp.JMP,
|
||||
|
||||
@ -94,7 +94,9 @@ public record IRVMProgram(
|
||||
case 0x10 -> operation.kind() == BytecodeEmitter.OperationKind.PUSH_CONST && operation.immediate() == immediate;
|
||||
case 0x11 -> operation.kind() == BytecodeEmitter.OperationKind.POP;
|
||||
case 0x16 -> operation.kind() == BytecodeEmitter.OperationKind.PUSH_BOOL;
|
||||
case 0x40 -> operation.kind() == BytecodeEmitter.OperationKind.GET_GLOBAL && operation.immediate() == immediate;
|
||||
case 0x42 -> operation.kind() == BytecodeEmitter.OperationKind.GET_LOCAL && operation.immediate() == immediate;
|
||||
case 0x41 -> operation.kind() == BytecodeEmitter.OperationKind.SET_GLOBAL && operation.immediate() == immediate;
|
||||
case 0x43 -> operation.kind() == BytecodeEmitter.OperationKind.SET_LOCAL && operation.immediate() == immediate;
|
||||
case 0x17 -> operation.kind() == BytecodeEmitter.OperationKind.PUSH_I32 && operation.immediate() == immediate;
|
||||
case 0x20 -> operation.kind() == BytecodeEmitter.OperationKind.ADD;
|
||||
@ -176,7 +178,9 @@ public record IRVMProgram(
|
||||
case 0x10 -> BytecodeEmitter.Operation.pushConst(immediate, null);
|
||||
case 0x11 -> BytecodeEmitter.Operation.pop(null);
|
||||
case 0x16 -> BytecodeEmitter.Operation.pushBool(immediate != 0, null);
|
||||
case 0x40 -> BytecodeEmitter.Operation.getGlobal(immediate, null);
|
||||
case 0x42 -> BytecodeEmitter.Operation.getLocal(immediate, null);
|
||||
case 0x41 -> BytecodeEmitter.Operation.setGlobal(immediate, null);
|
||||
case 0x43 -> BytecodeEmitter.Operation.setLocal(immediate, null);
|
||||
case 0x17 -> BytecodeEmitter.Operation.pushI32(immediate, null);
|
||||
case 0x20 -> BytecodeEmitter.Operation.add(null);
|
||||
@ -248,7 +252,9 @@ public record IRVMProgram(
|
||||
case PUSH_CONST -> new IRVMInstruction(IRVMOp.PUSH_CONST, operation.immediate());
|
||||
case POP -> new IRVMInstruction(IRVMOp.POP, null);
|
||||
case PUSH_BOOL -> new IRVMInstruction(IRVMOp.PUSH_BOOL, operation.immediate());
|
||||
case GET_GLOBAL -> new IRVMInstruction(IRVMOp.GET_GLOBAL, operation.immediate());
|
||||
case GET_LOCAL -> new IRVMInstruction(IRVMOp.GET_LOCAL, operation.immediate());
|
||||
case SET_GLOBAL -> new IRVMInstruction(IRVMOp.SET_GLOBAL, operation.immediate());
|
||||
case SET_LOCAL -> new IRVMInstruction(IRVMOp.SET_LOCAL, operation.immediate());
|
||||
case PUSH_I32 -> new IRVMInstruction(IRVMOp.PUSH_I32, operation.immediate());
|
||||
case ADD -> new IRVMInstruction(IRVMOp.ADD, null);
|
||||
|
||||
@ -124,6 +124,19 @@ public class LowerToIRVMService {
|
||||
operations.add(BytecodeEmitter.Operation.getLocal(slot, sourceSpan));
|
||||
functionPc += IRVMOp.GET_LOCAL.immediateSize() + 2;
|
||||
}
|
||||
case GET_GLOBAL -> {
|
||||
final var slot = instr.expectedArgSlots();
|
||||
if (slot == null) {
|
||||
throw loweringError(
|
||||
fn,
|
||||
instr,
|
||||
IRVMLoweringErrorCode.LOWER_IRVM_MISSING_CALLEE,
|
||||
"missing global slot for GET_GLOBAL");
|
||||
}
|
||||
instructions.add(new IRVMInstruction(IRVMOp.GET_GLOBAL, slot));
|
||||
operations.add(BytecodeEmitter.Operation.getGlobal(slot, sourceSpan));
|
||||
functionPc += IRVMOp.GET_GLOBAL.immediateSize() + 2;
|
||||
}
|
||||
case SET_LOCAL -> {
|
||||
final var slot = instr.expectedArgSlots();
|
||||
if (slot == null) {
|
||||
@ -137,6 +150,19 @@ public class LowerToIRVMService {
|
||||
operations.add(BytecodeEmitter.Operation.setLocal(slot, sourceSpan));
|
||||
functionPc += IRVMOp.SET_LOCAL.immediateSize() + 2;
|
||||
}
|
||||
case SET_GLOBAL -> {
|
||||
final var slot = instr.expectedArgSlots();
|
||||
if (slot == null) {
|
||||
throw loweringError(
|
||||
fn,
|
||||
instr,
|
||||
IRVMLoweringErrorCode.LOWER_IRVM_MISSING_CALLEE,
|
||||
"missing global slot for SET_GLOBAL");
|
||||
}
|
||||
instructions.add(new IRVMInstruction(IRVMOp.SET_GLOBAL, slot));
|
||||
operations.add(BytecodeEmitter.Operation.setGlobal(slot, sourceSpan));
|
||||
functionPc += IRVMOp.SET_GLOBAL.immediateSize() + 2;
|
||||
}
|
||||
case POP -> {
|
||||
instructions.add(new IRVMInstruction(IRVMOp.POP, null));
|
||||
operations.add(BytecodeEmitter.Operation.pop(sourceSpan));
|
||||
|
||||
@ -86,8 +86,13 @@ class LowerToIRVMServiceTest {
|
||||
fn("boot", "app", 10, ReadOnlyList.from(ret())),
|
||||
fn("frame", "app", 20, ReadOnlyList.from(ret())),
|
||||
fn("__pbs.frame_wrapper$m0", "app", 40, ReadOnlyList.from(
|
||||
getGlobal(0),
|
||||
jmpIfTrue("bootstrap_done"),
|
||||
callFunc("app", "__pbs.module_init$m0", 31),
|
||||
callFunc("app", "__pbs.project_init$m0", 32),
|
||||
pushBool(true),
|
||||
setGlobal(0),
|
||||
label("bootstrap_done"),
|
||||
callFunc("app", "frame", 20),
|
||||
ret()))))
|
||||
.build();
|
||||
@ -95,10 +100,14 @@ class LowerToIRVMServiceTest {
|
||||
final var lowered = new LowerToIRVMService().lower(backend);
|
||||
|
||||
assertEquals("__pbs.frame_wrapper$m0", lowered.module().functions().get(0).name());
|
||||
assertEquals(IRVMOp.CALL, lowered.module().functions().get(0).instructions().get(0).op());
|
||||
assertEquals(IRVMOp.CALL, lowered.module().functions().get(0).instructions().get(1).op());
|
||||
assertEquals(IRVMOp.GET_GLOBAL, lowered.module().functions().get(0).instructions().get(0).op());
|
||||
assertEquals(IRVMOp.JMP_IF_TRUE, lowered.module().functions().get(0).instructions().get(1).op());
|
||||
assertEquals(IRVMOp.CALL, lowered.module().functions().get(0).instructions().get(2).op());
|
||||
assertEquals(IRVMOp.RET, lowered.module().functions().get(0).instructions().get(3).op());
|
||||
assertEquals(IRVMOp.CALL, lowered.module().functions().get(0).instructions().get(3).op());
|
||||
assertEquals(IRVMOp.PUSH_BOOL, lowered.module().functions().get(0).instructions().get(4).op());
|
||||
assertEquals(IRVMOp.SET_GLOBAL, lowered.module().functions().get(0).instructions().get(5).op());
|
||||
assertEquals(IRVMOp.CALL, lowered.module().functions().get(0).instructions().get(6).op());
|
||||
assertEquals(IRVMOp.RET, lowered.module().functions().get(0).instructions().get(7).op());
|
||||
assertEquals(IRVMOp.RET, lowered.module().functions().stream()
|
||||
.filter(function -> "frame".equals(function.name()))
|
||||
.findFirst()
|
||||
@ -583,4 +592,57 @@ class LowerToIRVMServiceTest {
|
||||
null,
|
||||
Span.none());
|
||||
}
|
||||
|
||||
private static IRBackendExecutableFunction.Instruction jmpIfTrue(final String target) {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.JMP_IF_TRUE,
|
||||
ModuleId.none(),
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
target,
|
||||
null,
|
||||
null,
|
||||
Span.none());
|
||||
}
|
||||
|
||||
private static IRBackendExecutableFunction.Instruction getGlobal(final int slot) {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.GET_GLOBAL,
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
slot,
|
||||
null,
|
||||
Span.none());
|
||||
}
|
||||
|
||||
private static IRBackendExecutableFunction.Instruction setGlobal(final int slot) {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.SET_GLOBAL,
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
slot,
|
||||
null,
|
||||
Span.none());
|
||||
}
|
||||
|
||||
private static IRBackendExecutableFunction.Instruction pushBool(final boolean value) {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.PUSH_BOOL,
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
value ? "true" : "false",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Span.none());
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,6 +271,20 @@ public record IRBackendExecutableFunction(
|
||||
throw new IllegalArgumentException("GET_LOCAL must not carry call metadata");
|
||||
}
|
||||
}
|
||||
case GET_GLOBAL -> {
|
||||
if (expectedArgSlots == null) {
|
||||
throw new IllegalArgumentException("GET_GLOBAL requires global slot in expectedArgSlots");
|
||||
}
|
||||
if (!label.isBlank()
|
||||
|| !targetLabel.isBlank()
|
||||
|| !calleeCallableName.isBlank()
|
||||
|| calleeCallableId != null
|
||||
|| hostCall != null
|
||||
|| intrinsicCall != null
|
||||
|| expectedRetSlots != null) {
|
||||
throw new IllegalArgumentException("GET_GLOBAL must not carry call metadata");
|
||||
}
|
||||
}
|
||||
case SET_LOCAL -> {
|
||||
if (expectedArgSlots == null) {
|
||||
throw new IllegalArgumentException("SET_LOCAL requires local slot in expectedArgSlots");
|
||||
@ -285,6 +299,20 @@ public record IRBackendExecutableFunction(
|
||||
throw new IllegalArgumentException("SET_LOCAL must not carry call metadata");
|
||||
}
|
||||
}
|
||||
case SET_GLOBAL -> {
|
||||
if (expectedArgSlots == null) {
|
||||
throw new IllegalArgumentException("SET_GLOBAL requires global slot in expectedArgSlots");
|
||||
}
|
||||
if (!label.isBlank()
|
||||
|| !targetLabel.isBlank()
|
||||
|| !calleeCallableName.isBlank()
|
||||
|| calleeCallableId != null
|
||||
|| hostCall != null
|
||||
|| intrinsicCall != null
|
||||
|| expectedRetSlots != null) {
|
||||
throw new IllegalArgumentException("SET_GLOBAL must not carry call metadata");
|
||||
}
|
||||
}
|
||||
case CALL_FUNC -> {
|
||||
if (calleeCallableId == null) {
|
||||
throw new IllegalArgumentException("CALL_FUNC requires calleeCallableId");
|
||||
@ -363,7 +391,9 @@ public record IRBackendExecutableFunction(
|
||||
PUSH_BOOL,
|
||||
PUSH_CONST,
|
||||
GET_LOCAL,
|
||||
GET_GLOBAL,
|
||||
SET_LOCAL,
|
||||
SET_GLOBAL,
|
||||
POP,
|
||||
ADD,
|
||||
SUB,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user