aritmetics
This commit is contained in:
parent
5575c491a1
commit
2bc99cc901
@ -388,7 +388,8 @@ public final class PbsFrontendCompiler {
|
|||||||
callableSignatureByCallableId,
|
callableSignatureByCallableId,
|
||||||
returnSlotsByCallableId,
|
returnSlotsByCallableId,
|
||||||
intrinsicIdTable,
|
intrinsicIdTable,
|
||||||
localSlotByNameId);
|
localSlotByNameId,
|
||||||
|
fn.parameters().size());
|
||||||
final var terminated = lowerBlock(fn.body(), loweringContext);
|
final var terminated = lowerBlock(fn.body(), loweringContext);
|
||||||
final var instructions = loweringContext.instructions();
|
final var instructions = loweringContext.instructions();
|
||||||
if (!terminated) {
|
if (!terminated) {
|
||||||
@ -417,6 +418,7 @@ public final class PbsFrontendCompiler {
|
|||||||
}
|
}
|
||||||
final var start = safeToInt(fn.span().getStart());
|
final var start = safeToInt(fn.span().getStart());
|
||||||
final var end = safeToInt(fn.span().getEnd());
|
final var end = safeToInt(fn.span().getEnd());
|
||||||
|
final var localSlots = Math.max(0, loweringContext.nextLocalSlot() - fn.parameters().size());
|
||||||
executableFunctions.add(new IRBackendExecutableFunction(
|
executableFunctions.add(new IRBackendExecutableFunction(
|
||||||
fileId,
|
fileId,
|
||||||
normalizedModuleId,
|
normalizedModuleId,
|
||||||
@ -425,7 +427,7 @@ public final class PbsFrontendCompiler {
|
|||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
fn.parameters().size(),
|
fn.parameters().size(),
|
||||||
0,
|
localSlots,
|
||||||
returnSlots,
|
returnSlots,
|
||||||
maxStackSlots,
|
maxStackSlots,
|
||||||
ReadOnlyList.wrap(instructions),
|
ReadOnlyList.wrap(instructions),
|
||||||
@ -629,8 +631,39 @@ public final class PbsFrontendCompiler {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (statement) {
|
switch (statement) {
|
||||||
case PbsAst.LetStatement letStatement -> lowerExpression(letStatement.initializer(), context);
|
case PbsAst.LetStatement letStatement -> {
|
||||||
case PbsAst.AssignStatement assignStatement -> lowerExpression(assignStatement.value(), context);
|
lowerExpression(letStatement.initializer(), context);
|
||||||
|
final var localSlot = context.declareLocalSlot(letStatement.name());
|
||||||
|
emitSetLocal(localSlot, letStatement.span(), context);
|
||||||
|
}
|
||||||
|
case PbsAst.AssignStatement assignStatement -> {
|
||||||
|
final var target = assignStatement.target();
|
||||||
|
if (target == null || target.rootName() == null || target.rootName().isBlank()) {
|
||||||
|
reportUnsupportedLowering("assignment target requires a local root name", assignStatement.span(), context);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (target.pathSegments() != null && !target.pathSegments().isEmpty()) {
|
||||||
|
reportUnsupportedLowering("path assignment lowering is not supported in executable lowering v1", assignStatement.span(), context);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final var targetSlot = context.resolveLocalSlot(target.rootName());
|
||||||
|
if (targetSlot == null) {
|
||||||
|
reportUnsupportedLowering("assignment target is not a known local: " + target.rootName(), assignStatement.span(), context);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (assignStatement.operator()) {
|
||||||
|
case ASSIGN -> {
|
||||||
|
lowerExpression(assignStatement.value(), context);
|
||||||
|
emitSetLocal(targetSlot, assignStatement.span(), context);
|
||||||
|
}
|
||||||
|
case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, DIV_ASSIGN, MOD_ASSIGN -> {
|
||||||
|
emitGetLocal(targetSlot, assignStatement.span(), context);
|
||||||
|
lowerExpression(assignStatement.value(), context);
|
||||||
|
emitBinaryOperatorInstruction(compoundAssignBinaryOperator(assignStatement.operator()), assignStatement.span(), context);
|
||||||
|
emitSetLocal(targetSlot, assignStatement.span(), context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
case PbsAst.ReturnStatement returnStatement -> {
|
case PbsAst.ReturnStatement returnStatement -> {
|
||||||
if (returnStatement.value() != null) {
|
if (returnStatement.value() != null) {
|
||||||
lowerExpression(returnStatement.value(), context);
|
lowerExpression(returnStatement.value(), context);
|
||||||
@ -741,8 +774,12 @@ public final class PbsFrontendCompiler {
|
|||||||
case PbsAst.BinaryExpr binaryExpr -> {
|
case PbsAst.BinaryExpr binaryExpr -> {
|
||||||
lowerExpression(binaryExpr.left(), context);
|
lowerExpression(binaryExpr.left(), context);
|
||||||
lowerExpression(binaryExpr.right(), context);
|
lowerExpression(binaryExpr.right(), context);
|
||||||
|
emitBinaryOperatorInstruction(binaryExpr.operator(), binaryExpr.span(), context);
|
||||||
|
}
|
||||||
|
case PbsAst.UnaryExpr unaryExpr -> {
|
||||||
|
lowerExpression(unaryExpr.expression(), context);
|
||||||
|
emitUnaryOperatorInstruction(unaryExpr.operator(), unaryExpr.span(), context);
|
||||||
}
|
}
|
||||||
case PbsAst.UnaryExpr unaryExpr -> lowerExpression(unaryExpr.expression(), context);
|
|
||||||
case PbsAst.ElseExpr elseExpr -> {
|
case PbsAst.ElseExpr elseExpr -> {
|
||||||
lowerExpression(elseExpr.optionalExpression(), context);
|
lowerExpression(elseExpr.optionalExpression(), context);
|
||||||
lowerExpression(elseExpr.fallbackExpression(), context);
|
lowerExpression(elseExpr.fallbackExpression(), context);
|
||||||
@ -809,8 +846,7 @@ public final class PbsFrontendCompiler {
|
|||||||
case PbsAst.BoundedLiteralExpr ignored -> {
|
case PbsAst.BoundedLiteralExpr ignored -> {
|
||||||
}
|
}
|
||||||
case PbsAst.StringLiteralExpr stringLiteralExpr -> emitPushConst(stringLiteralExpr.value(), stringLiteralExpr.span(), context);
|
case PbsAst.StringLiteralExpr stringLiteralExpr -> emitPushConst(stringLiteralExpr.value(), stringLiteralExpr.span(), context);
|
||||||
case PbsAst.BoolLiteralExpr ignored -> {
|
case PbsAst.BoolLiteralExpr boolLiteralExpr -> emitPushBool(boolLiteralExpr.value(), boolLiteralExpr.span(), context);
|
||||||
}
|
|
||||||
case PbsAst.ThisExpr ignored -> {
|
case PbsAst.ThisExpr ignored -> {
|
||||||
}
|
}
|
||||||
case PbsAst.NoneExpr ignored -> {
|
case PbsAst.NoneExpr ignored -> {
|
||||||
@ -890,6 +926,7 @@ public final class PbsFrontendCompiler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final var host = hostCandidates.getFirst();
|
final var host = hostCandidates.getFirst();
|
||||||
|
final var effectiveArgSlots = callExpr.arguments().size() + implicitReceiverArgSlots(callExpr.callee());
|
||||||
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
||||||
IRBackendExecutableFunction.InstructionKind.CALL_HOST,
|
IRBackendExecutableFunction.InstructionKind.CALL_HOST,
|
||||||
"",
|
"",
|
||||||
@ -897,7 +934,7 @@ public final class PbsFrontendCompiler {
|
|||||||
host.abiModule(),
|
host.abiModule(),
|
||||||
host.abiMethod(),
|
host.abiMethod(),
|
||||||
host.abiVersion(),
|
host.abiVersion(),
|
||||||
callExpr.arguments().size(),
|
effectiveArgSlots,
|
||||||
0),
|
0),
|
||||||
null,
|
null,
|
||||||
callExpr.span()));
|
callExpr.span()));
|
||||||
@ -939,6 +976,7 @@ public final class PbsFrontendCompiler {
|
|||||||
reportUnsupportedLowering("executable lowering resolved callable without signature metadata", callExpr.span(), context);
|
reportUnsupportedLowering("executable lowering resolved callable without signature metadata", callExpr.span(), context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final var effectiveArgSlots = callExpr.arguments().size() + implicitReceiverArgSlots(callExpr.callee());
|
||||||
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
||||||
IRBackendExecutableFunction.InstructionKind.CALL_FUNC,
|
IRBackendExecutableFunction.InstructionKind.CALL_FUNC,
|
||||||
calleeSignature.moduleId(),
|
calleeSignature.moduleId(),
|
||||||
@ -946,7 +984,7 @@ public final class PbsFrontendCompiler {
|
|||||||
calleeCallableId,
|
calleeCallableId,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
callExpr.arguments().size(),
|
effectiveArgSlots,
|
||||||
context.returnSlotsByCallableId().get(calleeCallableId),
|
context.returnSlotsByCallableId().get(calleeCallableId),
|
||||||
callExpr.span()));
|
callExpr.span()));
|
||||||
}
|
}
|
||||||
@ -1139,6 +1177,24 @@ public final class PbsFrontendCompiler {
|
|||||||
span));
|
span));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void emitPushBool(
|
||||||
|
final boolean value,
|
||||||
|
final p.studio.compiler.source.Span span,
|
||||||
|
final ExecutableLoweringContext context) {
|
||||||
|
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
||||||
|
IRBackendExecutableFunction.InstructionKind.PUSH_BOOL,
|
||||||
|
ModuleId.none(),
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
value ? "true" : "false",
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
span));
|
||||||
|
}
|
||||||
|
|
||||||
private void emitPushConst(
|
private void emitPushConst(
|
||||||
final String value,
|
final String value,
|
||||||
final p.studio.compiler.source.Span span,
|
final p.studio.compiler.source.Span span,
|
||||||
@ -1157,6 +1213,102 @@ public final class PbsFrontendCompiler {
|
|||||||
span));
|
span));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void emitSetLocal(
|
||||||
|
final int slot,
|
||||||
|
final p.studio.compiler.source.Span span,
|
||||||
|
final ExecutableLoweringContext context) {
|
||||||
|
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
||||||
|
IRBackendExecutableFunction.InstructionKind.SET_LOCAL,
|
||||||
|
ModuleId.none(),
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
slot,
|
||||||
|
null,
|
||||||
|
span));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String compoundAssignBinaryOperator(final PbsAst.AssignOperator operator) {
|
||||||
|
return switch (operator) {
|
||||||
|
case ADD_ASSIGN -> "+";
|
||||||
|
case SUB_ASSIGN -> "-";
|
||||||
|
case MUL_ASSIGN -> "*";
|
||||||
|
case DIV_ASSIGN -> "/";
|
||||||
|
case MOD_ASSIGN -> "%";
|
||||||
|
case ASSIGN -> "=";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void emitUnaryOperatorInstruction(
|
||||||
|
final String operator,
|
||||||
|
final p.studio.compiler.source.Span span,
|
||||||
|
final ExecutableLoweringContext context) {
|
||||||
|
final var normalized = operator == null ? "" : operator;
|
||||||
|
final IRBackendExecutableFunction.InstructionKind instructionKind = switch (normalized) {
|
||||||
|
case "-", "neg" -> IRBackendExecutableFunction.InstructionKind.NEG;
|
||||||
|
case "!", "not" -> IRBackendExecutableFunction.InstructionKind.NOT;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
if (instructionKind == null) {
|
||||||
|
reportUnsupportedLowering("unsupported unary operator in executable lowering: " + normalized, span, context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
||||||
|
instructionKind,
|
||||||
|
ModuleId.none(),
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
span));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void emitBinaryOperatorInstruction(
|
||||||
|
final String operator,
|
||||||
|
final p.studio.compiler.source.Span span,
|
||||||
|
final ExecutableLoweringContext context) {
|
||||||
|
final var normalized = operator == null ? "" : operator;
|
||||||
|
final IRBackendExecutableFunction.InstructionKind instructionKind = switch (normalized) {
|
||||||
|
case "+" -> IRBackendExecutableFunction.InstructionKind.ADD;
|
||||||
|
case "-" -> IRBackendExecutableFunction.InstructionKind.SUB;
|
||||||
|
case "*" -> IRBackendExecutableFunction.InstructionKind.MUL;
|
||||||
|
case "/" -> IRBackendExecutableFunction.InstructionKind.DIV;
|
||||||
|
case "%" -> IRBackendExecutableFunction.InstructionKind.MOD;
|
||||||
|
case "==" -> IRBackendExecutableFunction.InstructionKind.EQ;
|
||||||
|
case "!=" -> IRBackendExecutableFunction.InstructionKind.NEQ;
|
||||||
|
case "<" -> IRBackendExecutableFunction.InstructionKind.LT;
|
||||||
|
case "<=" -> IRBackendExecutableFunction.InstructionKind.LTE;
|
||||||
|
case ">" -> IRBackendExecutableFunction.InstructionKind.GT;
|
||||||
|
case ">=" -> IRBackendExecutableFunction.InstructionKind.GTE;
|
||||||
|
case "&&", "and" -> IRBackendExecutableFunction.InstructionKind.AND;
|
||||||
|
case "||", "or" -> IRBackendExecutableFunction.InstructionKind.OR;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
if (instructionKind == null) {
|
||||||
|
reportUnsupportedLowering("unsupported binary operator in executable lowering: " + normalized, span, context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
||||||
|
instructionKind,
|
||||||
|
ModuleId.none(),
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
span));
|
||||||
|
}
|
||||||
|
|
||||||
private void emitGetLocal(
|
private void emitGetLocal(
|
||||||
final int slot,
|
final int slot,
|
||||||
final p.studio.compiler.source.Span span,
|
final p.studio.compiler.source.Span span,
|
||||||
@ -1219,7 +1371,27 @@ public final class PbsFrontendCompiler {
|
|||||||
var outHeight = incomingHeightByInstruction.get(index);
|
var outHeight = incomingHeightByInstruction.get(index);
|
||||||
|
|
||||||
switch (instruction.kind()) {
|
switch (instruction.kind()) {
|
||||||
case PUSH_I32, PUSH_CONST, GET_LOCAL -> outHeight += 1;
|
case PUSH_I32, PUSH_BOOL, PUSH_CONST, GET_LOCAL -> outHeight += 1;
|
||||||
|
case POP, SET_LOCAL -> {
|
||||||
|
if (outHeight <= 0) {
|
||||||
|
throw new ExecutableLoweringAnalysisException(
|
||||||
|
"stack underflow at " + instruction.kind().name().toLowerCase() + ": need=1 have=" + outHeight);
|
||||||
|
}
|
||||||
|
outHeight -= 1;
|
||||||
|
}
|
||||||
|
case ADD, SUB, MUL, DIV, MOD, EQ, NEQ, LT, LTE, GT, GTE, AND, OR -> {
|
||||||
|
if (outHeight < 2) {
|
||||||
|
throw new ExecutableLoweringAnalysisException(
|
||||||
|
"stack underflow at " + instruction.kind().name().toLowerCase() + ": need=2 have=" + outHeight);
|
||||||
|
}
|
||||||
|
outHeight -= 1;
|
||||||
|
}
|
||||||
|
case NOT, NEG -> {
|
||||||
|
if (outHeight <= 0) {
|
||||||
|
throw new ExecutableLoweringAnalysisException(
|
||||||
|
"stack underflow at " + instruction.kind().name().toLowerCase() + ": need=1 have=" + outHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
case CALL_FUNC -> {
|
case CALL_FUNC -> {
|
||||||
final var argSlots = instruction.expectedArgSlots() == null ? 0 : instruction.expectedArgSlots();
|
final var argSlots = instruction.expectedArgSlots() == null ? 0 : instruction.expectedArgSlots();
|
||||||
final var retSlots = instruction.expectedRetSlots() == null ? 0 : instruction.expectedRetSlots();
|
final var retSlots = instruction.expectedRetSlots() == null ? 0 : instruction.expectedRetSlots();
|
||||||
@ -1327,6 +1499,7 @@ public final class PbsFrontendCompiler {
|
|||||||
private final ArrayList<IRBackendExecutableFunction.Instruction> instructions = new ArrayList<>();
|
private final ArrayList<IRBackendExecutableFunction.Instruction> instructions = new ArrayList<>();
|
||||||
private final ArrayDeque<LoopTargets> loopTargets = new ArrayDeque<>();
|
private final ArrayDeque<LoopTargets> loopTargets = new ArrayDeque<>();
|
||||||
private int nextLabelId = 0;
|
private int nextLabelId = 0;
|
||||||
|
private int nextLocalSlot;
|
||||||
|
|
||||||
private ExecutableLoweringContext(
|
private ExecutableLoweringContext(
|
||||||
final ModuleId moduleId,
|
final ModuleId moduleId,
|
||||||
@ -1340,7 +1513,8 @@ public final class PbsFrontendCompiler {
|
|||||||
final Map<CallableId, CallableSignatureRef> callableSignatureByCallableId,
|
final Map<CallableId, CallableSignatureRef> callableSignatureByCallableId,
|
||||||
final Map<CallableId, Integer> returnSlotsByCallableId,
|
final Map<CallableId, Integer> returnSlotsByCallableId,
|
||||||
final IntrinsicTable intrinsicIdTable,
|
final IntrinsicTable intrinsicIdTable,
|
||||||
final Map<NameId, Integer> localSlotByNameId) {
|
final Map<NameId, Integer> localSlotByNameId,
|
||||||
|
final int initialLocalSlot) {
|
||||||
this.moduleId = moduleId == null ? ModuleId.none() : moduleId;
|
this.moduleId = moduleId == null ? ModuleId.none() : moduleId;
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
this.nameTable = nameTable;
|
this.nameTable = nameTable;
|
||||||
@ -1352,7 +1526,8 @@ public final class PbsFrontendCompiler {
|
|||||||
this.callableSignatureByCallableId = callableSignatureByCallableId;
|
this.callableSignatureByCallableId = callableSignatureByCallableId;
|
||||||
this.returnSlotsByCallableId = returnSlotsByCallableId;
|
this.returnSlotsByCallableId = returnSlotsByCallableId;
|
||||||
this.intrinsicIdTable = intrinsicIdTable;
|
this.intrinsicIdTable = intrinsicIdTable;
|
||||||
this.localSlotByNameId = localSlotByNameId == null ? Map.of() : localSlotByNameId;
|
this.localSlotByNameId = localSlotByNameId == null ? new HashMap<>() : localSlotByNameId;
|
||||||
|
this.nextLocalSlot = Math.max(0, initialLocalSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ModuleId moduleId() {
|
private ModuleId moduleId() {
|
||||||
@ -1403,6 +1578,28 @@ public final class PbsFrontendCompiler {
|
|||||||
return localSlotByNameId;
|
return localSlotByNameId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Integer resolveLocalSlot(final String localName) {
|
||||||
|
if (localName == null || localName.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return localSlotByNameId.get(nameTable.register(localName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int declareLocalSlot(final String localName) {
|
||||||
|
final var nameId = nameTable.register(localName);
|
||||||
|
final var existing = localSlotByNameId.get(nameId);
|
||||||
|
if (existing != null) {
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
final var slot = nextLocalSlot++;
|
||||||
|
localSlotByNameId.put(nameId, slot);
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int nextLocalSlot() {
|
||||||
|
return nextLocalSlot;
|
||||||
|
}
|
||||||
|
|
||||||
private ArrayList<IRBackendExecutableFunction.Instruction> instructions() {
|
private ArrayList<IRBackendExecutableFunction.Instruction> instructions() {
|
||||||
return instructions;
|
return instructions;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,25 @@ public class BytecodeEmitter {
|
|||||||
private static final int OP_JMP_IF_FALSE = 0x03;
|
private static final int OP_JMP_IF_FALSE = 0x03;
|
||||||
private static final int OP_JMP_IF_TRUE = 0x04;
|
private static final int OP_JMP_IF_TRUE = 0x04;
|
||||||
private static final int OP_PUSH_CONST = 0x10;
|
private static final int OP_PUSH_CONST = 0x10;
|
||||||
|
private static final int OP_POP = 0x11;
|
||||||
|
private static final int OP_PUSH_BOOL = 0x16;
|
||||||
|
private static final int OP_ADD = 0x20;
|
||||||
|
private static final int OP_SUB = 0x21;
|
||||||
|
private static final int OP_MUL = 0x22;
|
||||||
|
private static final int OP_DIV = 0x23;
|
||||||
|
private static final int OP_MOD = 0x24;
|
||||||
|
private static final int OP_EQ = 0x30;
|
||||||
|
private static final int OP_NEQ = 0x31;
|
||||||
|
private static final int OP_LT = 0x32;
|
||||||
|
private static final int OP_GT = 0x33;
|
||||||
|
private static final int OP_AND = 0x34;
|
||||||
|
private static final int OP_OR = 0x35;
|
||||||
|
private static final int OP_NOT = 0x36;
|
||||||
|
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_LOCAL = 0x42;
|
private static final int OP_GET_LOCAL = 0x42;
|
||||||
|
private static final int OP_SET_LOCAL = 0x43;
|
||||||
private static final int OP_PUSH_I32 = 0x17;
|
private static final int OP_PUSH_I32 = 0x17;
|
||||||
private static final int OP_HOSTCALL = 0x71;
|
private static final int OP_HOSTCALL = 0x71;
|
||||||
private static final int OP_SYSCALL = 0x70;
|
private static final int OP_SYSCALL = 0x70;
|
||||||
@ -55,14 +73,86 @@ public class BytecodeEmitter {
|
|||||||
writeOpU32(code, OP_PUSH_CONST, op.immediate());
|
writeOpU32(code, OP_PUSH_CONST, op.immediate());
|
||||||
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
}
|
}
|
||||||
|
case POP -> {
|
||||||
|
writeOpNoImm(code, OP_POP);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
case GET_LOCAL -> {
|
case GET_LOCAL -> {
|
||||||
writeOpU32(code, OP_GET_LOCAL, op.immediate());
|
writeOpU32(code, OP_GET_LOCAL, op.immediate());
|
||||||
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
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 PUSH_BOOL -> {
|
||||||
|
writeOpU8(code, OP_PUSH_BOOL, op.immediate() == 0 ? 0 : 1);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
case PUSH_I32 -> {
|
case PUSH_I32 -> {
|
||||||
writeOpU32(code, OP_PUSH_I32, op.immediate());
|
writeOpU32(code, OP_PUSH_I32, op.immediate());
|
||||||
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
}
|
}
|
||||||
|
case ADD -> {
|
||||||
|
writeOpNoImm(code, OP_ADD);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case SUB -> {
|
||||||
|
writeOpNoImm(code, OP_SUB);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case MUL -> {
|
||||||
|
writeOpNoImm(code, OP_MUL);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case DIV -> {
|
||||||
|
writeOpNoImm(code, OP_DIV);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case MOD -> {
|
||||||
|
writeOpNoImm(code, OP_MOD);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case EQ -> {
|
||||||
|
writeOpNoImm(code, OP_EQ);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case NEQ -> {
|
||||||
|
writeOpNoImm(code, OP_NEQ);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case LT -> {
|
||||||
|
writeOpNoImm(code, OP_LT);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case LTE -> {
|
||||||
|
writeOpNoImm(code, OP_LTE);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case GT -> {
|
||||||
|
writeOpNoImm(code, OP_GT);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case GTE -> {
|
||||||
|
writeOpNoImm(code, OP_GTE);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case AND -> {
|
||||||
|
writeOpNoImm(code, OP_AND);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case OR -> {
|
||||||
|
writeOpNoImm(code, OP_OR);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case NOT -> {
|
||||||
|
writeOpNoImm(code, OP_NOT);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
|
case NEG -> {
|
||||||
|
writeOpNoImm(code, OP_NEG);
|
||||||
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
|
}
|
||||||
case JMP -> {
|
case JMP -> {
|
||||||
writeOpU32(code, OP_JMP, op.immediate());
|
writeOpU32(code, OP_JMP, op.immediate());
|
||||||
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
spans.add(new BytecodeFunctionLayoutBuilder.InstructionSpan(pc, spanOrUnknown(op.span())));
|
||||||
@ -136,6 +226,11 @@ public class BytecodeEmitter {
|
|||||||
out.writeBytes(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(immediate).array());
|
out.writeBytes(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(immediate).array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void writeOpU8(final ByteArrayOutputStream out, final int opcode, final int immediate) {
|
||||||
|
out.writeBytes(ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort((short) opcode).array());
|
||||||
|
out.write(immediate & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
private static BytecodeModule.SourceSpan spanOrUnknown(final BytecodeModule.SourceSpan span) {
|
private static BytecodeModule.SourceSpan spanOrUnknown(final BytecodeModule.SourceSpan span) {
|
||||||
if (span == null) {
|
if (span == null) {
|
||||||
return new BytecodeModule.SourceSpan(-1, 0, 0);
|
return new BytecodeModule.SourceSpan(-1, 0, 0);
|
||||||
@ -210,8 +305,26 @@ public class BytecodeEmitter {
|
|||||||
HALT,
|
HALT,
|
||||||
RET,
|
RET,
|
||||||
PUSH_CONST,
|
PUSH_CONST,
|
||||||
|
POP,
|
||||||
GET_LOCAL,
|
GET_LOCAL,
|
||||||
|
SET_LOCAL,
|
||||||
|
PUSH_BOOL,
|
||||||
PUSH_I32,
|
PUSH_I32,
|
||||||
|
ADD,
|
||||||
|
SUB,
|
||||||
|
MUL,
|
||||||
|
DIV,
|
||||||
|
MOD,
|
||||||
|
EQ,
|
||||||
|
NEQ,
|
||||||
|
LT,
|
||||||
|
LTE,
|
||||||
|
GT,
|
||||||
|
GTE,
|
||||||
|
AND,
|
||||||
|
OR,
|
||||||
|
NOT,
|
||||||
|
NEG,
|
||||||
CALL_FUNC,
|
CALL_FUNC,
|
||||||
JMP,
|
JMP,
|
||||||
JMP_IF_TRUE,
|
JMP_IF_TRUE,
|
||||||
@ -276,14 +389,86 @@ public class BytecodeEmitter {
|
|||||||
return new Operation(OperationKind.PUSH_CONST, constPoolIndex, null, null, null, span);
|
return new Operation(OperationKind.PUSH_CONST, constPoolIndex, null, null, null, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Operation pop(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.POP, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
public static Operation getLocal(final int slot, final BytecodeModule.SourceSpan span) {
|
public static Operation getLocal(final int slot, final BytecodeModule.SourceSpan span) {
|
||||||
return new Operation(OperationKind.GET_LOCAL, slot, null, null, null, span);
|
return new Operation(OperationKind.GET_LOCAL, 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 pushBool(final boolean value, final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.PUSH_BOOL, value ? 1 : 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
public static Operation pushI32(final int value, final BytecodeModule.SourceSpan span) {
|
public static Operation pushI32(final int value, final BytecodeModule.SourceSpan span) {
|
||||||
return new Operation(OperationKind.PUSH_I32, value, null, null, null, span);
|
return new Operation(OperationKind.PUSH_I32, value, null, null, null, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Operation add(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.ADD, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation sub(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.SUB, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation mul(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.MUL, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation div(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.DIV, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation mod(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.MOD, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation eq(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.EQ, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation neq(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.NEQ, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation lt(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.LT, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation lte(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.LTE, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation gt(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.GT, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation gte(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.GTE, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation and(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.AND, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation or(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.OR, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation not(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.NOT, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation neg(final BytecodeModule.SourceSpan span) {
|
||||||
|
return new Operation(OperationKind.NEG, 0, null, null, null, span);
|
||||||
|
}
|
||||||
|
|
||||||
public static Operation hostcall(
|
public static Operation hostcall(
|
||||||
final BytecodeModule.SyscallDecl decl,
|
final BytecodeModule.SyscallDecl decl,
|
||||||
final Integer expectedArgSlots,
|
final Integer expectedArgSlots,
|
||||||
|
|||||||
@ -9,11 +9,27 @@ final class BytecodeOpcodeLayout {
|
|||||||
Map.entry(0x03, 6),
|
Map.entry(0x03, 6),
|
||||||
Map.entry(0x04, 6),
|
Map.entry(0x04, 6),
|
||||||
Map.entry(0x10, 6),
|
Map.entry(0x10, 6),
|
||||||
|
Map.entry(0x11, 2),
|
||||||
Map.entry(0x14, 10),
|
Map.entry(0x14, 10),
|
||||||
Map.entry(0x15, 10),
|
Map.entry(0x15, 10),
|
||||||
Map.entry(0x16, 3),
|
Map.entry(0x16, 3),
|
||||||
Map.entry(0x17, 6),
|
Map.entry(0x17, 6),
|
||||||
Map.entry(0x18, 6),
|
Map.entry(0x18, 6),
|
||||||
|
Map.entry(0x20, 2),
|
||||||
|
Map.entry(0x21, 2),
|
||||||
|
Map.entry(0x22, 2),
|
||||||
|
Map.entry(0x23, 2),
|
||||||
|
Map.entry(0x24, 2),
|
||||||
|
Map.entry(0x30, 2),
|
||||||
|
Map.entry(0x31, 2),
|
||||||
|
Map.entry(0x32, 2),
|
||||||
|
Map.entry(0x33, 2),
|
||||||
|
Map.entry(0x34, 2),
|
||||||
|
Map.entry(0x35, 2),
|
||||||
|
Map.entry(0x36, 2),
|
||||||
|
Map.entry(0x3C, 2),
|
||||||
|
Map.entry(0x3D, 2),
|
||||||
|
Map.entry(0x3E, 2),
|
||||||
Map.entry(0x40, 6),
|
Map.entry(0x40, 6),
|
||||||
Map.entry(0x41, 6),
|
Map.entry(0x41, 6),
|
||||||
Map.entry(0x42, 6),
|
Map.entry(0x42, 6),
|
||||||
|
|||||||
@ -13,13 +13,31 @@ public record IRVMOp(
|
|||||||
public static final IRVMOp HALT = new IRVMOp("HALT", 0x01, 0, 0, 0, false, true, false);
|
public static final IRVMOp HALT = new IRVMOp("HALT", 0x01, 0, 0, 0, false, true, false);
|
||||||
public static final IRVMOp RET = new IRVMOp("RET", 0x51, 0, 0, 0, false, true, false);
|
public static final IRVMOp RET = new IRVMOp("RET", 0x51, 0, 0, 0, false, true, false);
|
||||||
public static final IRVMOp PUSH_CONST = new IRVMOp("PUSH_CONST", 0x10, 4, 0, 1, false, false, false);
|
public static final IRVMOp PUSH_CONST = new IRVMOp("PUSH_CONST", 0x10, 4, 0, 1, false, false, false);
|
||||||
|
public static final IRVMOp POP = new IRVMOp("POP", 0x11, 0, 1, 0, false, false, false);
|
||||||
public static final IRVMOp CALL = new IRVMOp("CALL", 0x50, 4, 0, 0, false, false, false);
|
public static final IRVMOp CALL = new IRVMOp("CALL", 0x50, 4, 0, 0, false, false, false);
|
||||||
public static final IRVMOp JMP = new IRVMOp("JMP", 0x02, 4, 0, 0, true, true, false);
|
public static final IRVMOp JMP = new IRVMOp("JMP", 0x02, 4, 0, 0, true, true, false);
|
||||||
public static final IRVMOp JMP_IF_TRUE = new IRVMOp("JMP_IF_TRUE", 0x04, 4, 1, 0, true, false, false);
|
public static final IRVMOp JMP_IF_TRUE = new IRVMOp("JMP_IF_TRUE", 0x04, 4, 1, 0, true, false, false);
|
||||||
public static final IRVMOp JMP_IF_FALSE = new IRVMOp("JMP_IF_FALSE", 0x03, 4, 1, 0, true, false, false);
|
public static final IRVMOp JMP_IF_FALSE = new IRVMOp("JMP_IF_FALSE", 0x03, 4, 1, 0, true, false, false);
|
||||||
public static final IRVMOp HOSTCALL = new IRVMOp("HOSTCALL", 0x71, 4, 0, 0, false, false, false);
|
public static final IRVMOp HOSTCALL = new IRVMOp("HOSTCALL", 0x71, 4, 0, 0, false, false, false);
|
||||||
public static final IRVMOp INTRINSIC = new IRVMOp("INTRINSIC", 0x72, 4, 0, 0, false, false, false);
|
public static final IRVMOp INTRINSIC = new IRVMOp("INTRINSIC", 0x72, 4, 0, 0, false, false, false);
|
||||||
|
public static final IRVMOp PUSH_BOOL = new IRVMOp("PUSH_BOOL", 0x16, 1, 0, 1, false, false, false);
|
||||||
public static final IRVMOp PUSH_I32 = new IRVMOp("PUSH_I32", 0x17, 4, 0, 1, false, false, false);
|
public static final IRVMOp PUSH_I32 = new IRVMOp("PUSH_I32", 0x17, 4, 0, 1, false, false, false);
|
||||||
|
public static final IRVMOp ADD = new IRVMOp("ADD", 0x20, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp SUB = new IRVMOp("SUB", 0x21, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp MUL = new IRVMOp("MUL", 0x22, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp DIV = new IRVMOp("DIV", 0x23, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp MOD = new IRVMOp("MOD", 0x24, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp EQ = new IRVMOp("EQ", 0x30, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp NEQ = new IRVMOp("NEQ", 0x31, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp LT = new IRVMOp("LT", 0x32, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp GT = new IRVMOp("GT", 0x33, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp AND = new IRVMOp("AND", 0x34, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp OR = new IRVMOp("OR", 0x35, 0, 2, 1, false, false, false);
|
||||||
|
public static final IRVMOp NOT = new IRVMOp("NOT", 0x36, 0, 1, 1, false, false, false);
|
||||||
|
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_LOCAL = new IRVMOp("GET_LOCAL", 0x42, 4, 0, 1, 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);
|
public static final IRVMOp INTERNAL_EXT = new IRVMOp("IRVM_EXT_NOP", 0xFFFF, 0, 0, 0, false, false, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,25 +12,61 @@ public final class IRVMProfileFeatureGate {
|
|||||||
IRVMOp.HALT,
|
IRVMOp.HALT,
|
||||||
IRVMOp.RET,
|
IRVMOp.RET,
|
||||||
IRVMOp.PUSH_CONST,
|
IRVMOp.PUSH_CONST,
|
||||||
|
IRVMOp.POP,
|
||||||
IRVMOp.GET_LOCAL,
|
IRVMOp.GET_LOCAL,
|
||||||
|
IRVMOp.SET_LOCAL,
|
||||||
IRVMOp.CALL,
|
IRVMOp.CALL,
|
||||||
IRVMOp.JMP,
|
IRVMOp.JMP,
|
||||||
IRVMOp.JMP_IF_TRUE,
|
IRVMOp.JMP_IF_TRUE,
|
||||||
IRVMOp.JMP_IF_FALSE,
|
IRVMOp.JMP_IF_FALSE,
|
||||||
IRVMOp.HOSTCALL,
|
IRVMOp.HOSTCALL,
|
||||||
IRVMOp.INTRINSIC,
|
IRVMOp.INTRINSIC,
|
||||||
|
IRVMOp.PUSH_BOOL,
|
||||||
|
IRVMOp.ADD,
|
||||||
|
IRVMOp.SUB,
|
||||||
|
IRVMOp.MUL,
|
||||||
|
IRVMOp.DIV,
|
||||||
|
IRVMOp.MOD,
|
||||||
|
IRVMOp.EQ,
|
||||||
|
IRVMOp.NEQ,
|
||||||
|
IRVMOp.LT,
|
||||||
|
IRVMOp.LTE,
|
||||||
|
IRVMOp.GT,
|
||||||
|
IRVMOp.GTE,
|
||||||
|
IRVMOp.AND,
|
||||||
|
IRVMOp.OR,
|
||||||
|
IRVMOp.NOT,
|
||||||
|
IRVMOp.NEG,
|
||||||
IRVMOp.PUSH_I32),
|
IRVMOp.PUSH_I32),
|
||||||
"experimental-v1", Set.of(
|
"experimental-v1", Set.of(
|
||||||
IRVMOp.HALT,
|
IRVMOp.HALT,
|
||||||
IRVMOp.RET,
|
IRVMOp.RET,
|
||||||
IRVMOp.PUSH_CONST,
|
IRVMOp.PUSH_CONST,
|
||||||
|
IRVMOp.POP,
|
||||||
IRVMOp.GET_LOCAL,
|
IRVMOp.GET_LOCAL,
|
||||||
|
IRVMOp.SET_LOCAL,
|
||||||
IRVMOp.CALL,
|
IRVMOp.CALL,
|
||||||
IRVMOp.JMP,
|
IRVMOp.JMP,
|
||||||
IRVMOp.JMP_IF_TRUE,
|
IRVMOp.JMP_IF_TRUE,
|
||||||
IRVMOp.JMP_IF_FALSE,
|
IRVMOp.JMP_IF_FALSE,
|
||||||
IRVMOp.HOSTCALL,
|
IRVMOp.HOSTCALL,
|
||||||
IRVMOp.INTRINSIC,
|
IRVMOp.INTRINSIC,
|
||||||
|
IRVMOp.PUSH_BOOL,
|
||||||
|
IRVMOp.ADD,
|
||||||
|
IRVMOp.SUB,
|
||||||
|
IRVMOp.MUL,
|
||||||
|
IRVMOp.DIV,
|
||||||
|
IRVMOp.MOD,
|
||||||
|
IRVMOp.EQ,
|
||||||
|
IRVMOp.NEQ,
|
||||||
|
IRVMOp.LT,
|
||||||
|
IRVMOp.LTE,
|
||||||
|
IRVMOp.GT,
|
||||||
|
IRVMOp.GTE,
|
||||||
|
IRVMOp.AND,
|
||||||
|
IRVMOp.OR,
|
||||||
|
IRVMOp.NOT,
|
||||||
|
IRVMOp.NEG,
|
||||||
IRVMOp.PUSH_I32,
|
IRVMOp.PUSH_I32,
|
||||||
IRVMOp.INTERNAL_EXT)));
|
IRVMOp.INTERNAL_EXT)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,8 +93,26 @@ public record IRVMProgram(
|
|||||||
case 0x01 -> operation.kind() == BytecodeEmitter.OperationKind.HALT;
|
case 0x01 -> operation.kind() == BytecodeEmitter.OperationKind.HALT;
|
||||||
case 0x51 -> operation.kind() == BytecodeEmitter.OperationKind.RET;
|
case 0x51 -> operation.kind() == BytecodeEmitter.OperationKind.RET;
|
||||||
case 0x10 -> operation.kind() == BytecodeEmitter.OperationKind.PUSH_CONST && operation.immediate() == immediate;
|
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 0x42 -> operation.kind() == BytecodeEmitter.OperationKind.GET_LOCAL && operation.immediate() == immediate;
|
case 0x42 -> operation.kind() == BytecodeEmitter.OperationKind.GET_LOCAL && 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 0x17 -> operation.kind() == BytecodeEmitter.OperationKind.PUSH_I32 && operation.immediate() == immediate;
|
||||||
|
case 0x20 -> operation.kind() == BytecodeEmitter.OperationKind.ADD;
|
||||||
|
case 0x21 -> operation.kind() == BytecodeEmitter.OperationKind.SUB;
|
||||||
|
case 0x22 -> operation.kind() == BytecodeEmitter.OperationKind.MUL;
|
||||||
|
case 0x23 -> operation.kind() == BytecodeEmitter.OperationKind.DIV;
|
||||||
|
case 0x24 -> operation.kind() == BytecodeEmitter.OperationKind.MOD;
|
||||||
|
case 0x30 -> operation.kind() == BytecodeEmitter.OperationKind.EQ;
|
||||||
|
case 0x31 -> operation.kind() == BytecodeEmitter.OperationKind.NEQ;
|
||||||
|
case 0x32 -> operation.kind() == BytecodeEmitter.OperationKind.LT;
|
||||||
|
case 0x33 -> operation.kind() == BytecodeEmitter.OperationKind.GT;
|
||||||
|
case 0x34 -> operation.kind() == BytecodeEmitter.OperationKind.AND;
|
||||||
|
case 0x35 -> operation.kind() == BytecodeEmitter.OperationKind.OR;
|
||||||
|
case 0x36 -> operation.kind() == BytecodeEmitter.OperationKind.NOT;
|
||||||
|
case 0x3C -> operation.kind() == BytecodeEmitter.OperationKind.LTE;
|
||||||
|
case 0x3D -> operation.kind() == BytecodeEmitter.OperationKind.GTE;
|
||||||
|
case 0x3E -> operation.kind() == BytecodeEmitter.OperationKind.NEG;
|
||||||
case 0x50 -> operation.kind() == BytecodeEmitter.OperationKind.CALL_FUNC && operation.immediate() == immediate;
|
case 0x50 -> operation.kind() == BytecodeEmitter.OperationKind.CALL_FUNC && operation.immediate() == immediate;
|
||||||
case 0x02 -> operation.kind() == BytecodeEmitter.OperationKind.JMP && operation.immediate() == immediate;
|
case 0x02 -> operation.kind() == BytecodeEmitter.OperationKind.JMP && operation.immediate() == immediate;
|
||||||
case 0x04 -> operation.kind() == BytecodeEmitter.OperationKind.JMP_IF_TRUE && operation.immediate() == immediate;
|
case 0x04 -> operation.kind() == BytecodeEmitter.OperationKind.JMP_IF_TRUE && operation.immediate() == immediate;
|
||||||
@ -157,8 +175,26 @@ public record IRVMProgram(
|
|||||||
case 0x01 -> BytecodeEmitter.Operation.halt();
|
case 0x01 -> BytecodeEmitter.Operation.halt();
|
||||||
case 0x51 -> BytecodeEmitter.Operation.ret();
|
case 0x51 -> BytecodeEmitter.Operation.ret();
|
||||||
case 0x10 -> BytecodeEmitter.Operation.pushConst(immediate, null);
|
case 0x10 -> BytecodeEmitter.Operation.pushConst(immediate, null);
|
||||||
|
case 0x11 -> BytecodeEmitter.Operation.pop(null);
|
||||||
|
case 0x16 -> BytecodeEmitter.Operation.pushBool(immediate != 0, null);
|
||||||
case 0x42 -> BytecodeEmitter.Operation.getLocal(immediate, null);
|
case 0x42 -> BytecodeEmitter.Operation.getLocal(immediate, null);
|
||||||
|
case 0x43 -> BytecodeEmitter.Operation.setLocal(immediate, null);
|
||||||
case 0x17 -> BytecodeEmitter.Operation.pushI32(immediate, null);
|
case 0x17 -> BytecodeEmitter.Operation.pushI32(immediate, null);
|
||||||
|
case 0x20 -> BytecodeEmitter.Operation.add(null);
|
||||||
|
case 0x21 -> BytecodeEmitter.Operation.sub(null);
|
||||||
|
case 0x22 -> BytecodeEmitter.Operation.mul(null);
|
||||||
|
case 0x23 -> BytecodeEmitter.Operation.div(null);
|
||||||
|
case 0x24 -> BytecodeEmitter.Operation.mod(null);
|
||||||
|
case 0x30 -> BytecodeEmitter.Operation.eq(null);
|
||||||
|
case 0x31 -> BytecodeEmitter.Operation.neq(null);
|
||||||
|
case 0x32 -> BytecodeEmitter.Operation.lt(null);
|
||||||
|
case 0x33 -> BytecodeEmitter.Operation.gt(null);
|
||||||
|
case 0x34 -> BytecodeEmitter.Operation.and(null);
|
||||||
|
case 0x35 -> BytecodeEmitter.Operation.or(null);
|
||||||
|
case 0x36 -> BytecodeEmitter.Operation.not(null);
|
||||||
|
case 0x3C -> BytecodeEmitter.Operation.lte(null);
|
||||||
|
case 0x3D -> BytecodeEmitter.Operation.gte(null);
|
||||||
|
case 0x3E -> BytecodeEmitter.Operation.neg(null);
|
||||||
case 0x50 -> BytecodeEmitter.Operation.callFunc(immediate);
|
case 0x50 -> BytecodeEmitter.Operation.callFunc(immediate);
|
||||||
case 0x02 -> BytecodeEmitter.Operation.jmp(immediate, null);
|
case 0x02 -> BytecodeEmitter.Operation.jmp(immediate, null);
|
||||||
case 0x04 -> BytecodeEmitter.Operation.jmpIfTrue(immediate, null);
|
case 0x04 -> BytecodeEmitter.Operation.jmpIfTrue(immediate, null);
|
||||||
@ -211,8 +247,26 @@ public record IRVMProgram(
|
|||||||
case HALT -> new IRVMInstruction(IRVMOp.HALT, null);
|
case HALT -> new IRVMInstruction(IRVMOp.HALT, null);
|
||||||
case RET -> new IRVMInstruction(IRVMOp.RET, null);
|
case RET -> new IRVMInstruction(IRVMOp.RET, null);
|
||||||
case PUSH_CONST -> new IRVMInstruction(IRVMOp.PUSH_CONST, operation.immediate());
|
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_LOCAL -> new IRVMInstruction(IRVMOp.GET_LOCAL, operation.immediate());
|
case GET_LOCAL -> new IRVMInstruction(IRVMOp.GET_LOCAL, operation.immediate());
|
||||||
|
case SET_LOCAL -> new IRVMInstruction(IRVMOp.SET_LOCAL, operation.immediate());
|
||||||
case PUSH_I32 -> new IRVMInstruction(IRVMOp.PUSH_I32, operation.immediate());
|
case PUSH_I32 -> new IRVMInstruction(IRVMOp.PUSH_I32, operation.immediate());
|
||||||
|
case ADD -> new IRVMInstruction(IRVMOp.ADD, null);
|
||||||
|
case SUB -> new IRVMInstruction(IRVMOp.SUB, null);
|
||||||
|
case MUL -> new IRVMInstruction(IRVMOp.MUL, null);
|
||||||
|
case DIV -> new IRVMInstruction(IRVMOp.DIV, null);
|
||||||
|
case MOD -> new IRVMInstruction(IRVMOp.MOD, null);
|
||||||
|
case EQ -> new IRVMInstruction(IRVMOp.EQ, null);
|
||||||
|
case NEQ -> new IRVMInstruction(IRVMOp.NEQ, null);
|
||||||
|
case LT -> new IRVMInstruction(IRVMOp.LT, null);
|
||||||
|
case LTE -> new IRVMInstruction(IRVMOp.LTE, null);
|
||||||
|
case GT -> new IRVMInstruction(IRVMOp.GT, null);
|
||||||
|
case GTE -> new IRVMInstruction(IRVMOp.GTE, null);
|
||||||
|
case AND -> new IRVMInstruction(IRVMOp.AND, null);
|
||||||
|
case OR -> new IRVMInstruction(IRVMOp.OR, null);
|
||||||
|
case NOT -> new IRVMInstruction(IRVMOp.NOT, null);
|
||||||
|
case NEG -> new IRVMInstruction(IRVMOp.NEG, null);
|
||||||
case CALL_FUNC -> new IRVMInstruction(IRVMOp.CALL, operation.immediate());
|
case CALL_FUNC -> new IRVMInstruction(IRVMOp.CALL, operation.immediate());
|
||||||
case JMP -> new IRVMInstruction(IRVMOp.JMP, operation.immediate());
|
case JMP -> new IRVMInstruction(IRVMOp.JMP, operation.immediate());
|
||||||
case JMP_IF_TRUE -> new IRVMInstruction(IRVMOp.JMP_IF_TRUE, operation.immediate());
|
case JMP_IF_TRUE -> new IRVMInstruction(IRVMOp.JMP_IF_TRUE, operation.immediate());
|
||||||
|
|||||||
@ -90,6 +90,24 @@ public class LowerToIRVMService {
|
|||||||
operations.add(BytecodeEmitter.Operation.pushConst(constPoolIndex, sourceSpan));
|
operations.add(BytecodeEmitter.Operation.pushConst(constPoolIndex, sourceSpan));
|
||||||
functionPc += IRVMOp.PUSH_CONST.immediateSize() + 2;
|
functionPc += IRVMOp.PUSH_CONST.immediateSize() + 2;
|
||||||
}
|
}
|
||||||
|
case PUSH_BOOL -> {
|
||||||
|
final var raw = instr.label() == null ? "" : instr.label().trim().toLowerCase();
|
||||||
|
final Integer value = switch (raw) {
|
||||||
|
case "1", "true" -> 1;
|
||||||
|
case "0", "false" -> 0;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
if (value == null) {
|
||||||
|
throw loweringError(
|
||||||
|
fn,
|
||||||
|
instr,
|
||||||
|
IRVMLoweringErrorCode.LOWER_IRVM_INVALID_INTRINSIC_ID,
|
||||||
|
"invalid PUSH_BOOL literal payload: " + instr.label());
|
||||||
|
}
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.PUSH_BOOL, value));
|
||||||
|
operations.add(BytecodeEmitter.Operation.pushBool(value != 0, sourceSpan));
|
||||||
|
functionPc += IRVMOp.PUSH_BOOL.immediateSize() + 2;
|
||||||
|
}
|
||||||
case GET_LOCAL -> {
|
case GET_LOCAL -> {
|
||||||
final var slot = instr.expectedArgSlots();
|
final var slot = instr.expectedArgSlots();
|
||||||
if (slot == null) {
|
if (slot == null) {
|
||||||
@ -103,6 +121,99 @@ public class LowerToIRVMService {
|
|||||||
operations.add(BytecodeEmitter.Operation.getLocal(slot, sourceSpan));
|
operations.add(BytecodeEmitter.Operation.getLocal(slot, sourceSpan));
|
||||||
functionPc += IRVMOp.GET_LOCAL.immediateSize() + 2;
|
functionPc += IRVMOp.GET_LOCAL.immediateSize() + 2;
|
||||||
}
|
}
|
||||||
|
case SET_LOCAL -> {
|
||||||
|
final var slot = instr.expectedArgSlots();
|
||||||
|
if (slot == null) {
|
||||||
|
throw loweringError(
|
||||||
|
fn,
|
||||||
|
instr,
|
||||||
|
IRVMLoweringErrorCode.LOWER_IRVM_MISSING_CALLEE,
|
||||||
|
"missing local slot for SET_LOCAL");
|
||||||
|
}
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.SET_LOCAL, slot));
|
||||||
|
operations.add(BytecodeEmitter.Operation.setLocal(slot, sourceSpan));
|
||||||
|
functionPc += IRVMOp.SET_LOCAL.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case POP -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.POP, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.pop(sourceSpan));
|
||||||
|
functionPc += IRVMOp.POP.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case ADD -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.ADD, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.add(sourceSpan));
|
||||||
|
functionPc += IRVMOp.ADD.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case SUB -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.SUB, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.sub(sourceSpan));
|
||||||
|
functionPc += IRVMOp.SUB.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case MUL -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.MUL, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.mul(sourceSpan));
|
||||||
|
functionPc += IRVMOp.MUL.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case DIV -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.DIV, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.div(sourceSpan));
|
||||||
|
functionPc += IRVMOp.DIV.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case MOD -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.MOD, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.mod(sourceSpan));
|
||||||
|
functionPc += IRVMOp.MOD.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case EQ -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.EQ, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.eq(sourceSpan));
|
||||||
|
functionPc += IRVMOp.EQ.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case NEQ -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.NEQ, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.neq(sourceSpan));
|
||||||
|
functionPc += IRVMOp.NEQ.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case LT -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.LT, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.lt(sourceSpan));
|
||||||
|
functionPc += IRVMOp.LT.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case LTE -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.LTE, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.lte(sourceSpan));
|
||||||
|
functionPc += IRVMOp.LTE.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case GT -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.GT, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.gt(sourceSpan));
|
||||||
|
functionPc += IRVMOp.GT.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case GTE -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.GTE, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.gte(sourceSpan));
|
||||||
|
functionPc += IRVMOp.GTE.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case AND -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.AND, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.and(sourceSpan));
|
||||||
|
functionPc += IRVMOp.AND.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case OR -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.OR, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.or(sourceSpan));
|
||||||
|
functionPc += IRVMOp.OR.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case NOT -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.NOT, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.not(sourceSpan));
|
||||||
|
functionPc += IRVMOp.NOT.immediateSize() + 2;
|
||||||
|
}
|
||||||
|
case NEG -> {
|
||||||
|
instructions.add(new IRVMInstruction(IRVMOp.NEG, null));
|
||||||
|
operations.add(BytecodeEmitter.Operation.neg(sourceSpan));
|
||||||
|
functionPc += IRVMOp.NEG.immediateSize() + 2;
|
||||||
|
}
|
||||||
case HALT -> {
|
case HALT -> {
|
||||||
instructions.add(new IRVMInstruction(IRVMOp.HALT, null));
|
instructions.add(new IRVMInstruction(IRVMOp.HALT, null));
|
||||||
operations.add(BytecodeEmitter.Operation.halt(sourceSpan));
|
operations.add(BytecodeEmitter.Operation.halt(sourceSpan));
|
||||||
|
|||||||
@ -232,6 +232,20 @@ public record IRBackendExecutableFunction(
|
|||||||
throw new IllegalArgumentException("PUSH_I32 must not carry call metadata");
|
throw new IllegalArgumentException("PUSH_I32 must not carry call metadata");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case PUSH_BOOL -> {
|
||||||
|
if (label.isBlank()) {
|
||||||
|
throw new IllegalArgumentException("PUSH_BOOL requires immediate label payload");
|
||||||
|
}
|
||||||
|
if (!targetLabel.isBlank()
|
||||||
|
|| !calleeCallableName.isBlank()
|
||||||
|
|| calleeCallableId != null
|
||||||
|
|| hostCall != null
|
||||||
|
|| intrinsicCall != null
|
||||||
|
|| expectedArgSlots != null
|
||||||
|
|| expectedRetSlots != null) {
|
||||||
|
throw new IllegalArgumentException("PUSH_BOOL must not carry call metadata");
|
||||||
|
}
|
||||||
|
}
|
||||||
case PUSH_CONST -> {
|
case PUSH_CONST -> {
|
||||||
if (!targetLabel.isBlank()
|
if (!targetLabel.isBlank()
|
||||||
|| !calleeCallableName.isBlank()
|
|| !calleeCallableName.isBlank()
|
||||||
@ -257,6 +271,20 @@ public record IRBackendExecutableFunction(
|
|||||||
throw new IllegalArgumentException("GET_LOCAL must not carry call metadata");
|
throw new IllegalArgumentException("GET_LOCAL must not carry call metadata");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case SET_LOCAL -> {
|
||||||
|
if (expectedArgSlots == null) {
|
||||||
|
throw new IllegalArgumentException("SET_LOCAL requires local slot in expectedArgSlots");
|
||||||
|
}
|
||||||
|
if (!label.isBlank()
|
||||||
|
|| !targetLabel.isBlank()
|
||||||
|
|| !calleeCallableName.isBlank()
|
||||||
|
|| calleeCallableId != null
|
||||||
|
|| hostCall != null
|
||||||
|
|| intrinsicCall != null
|
||||||
|
|| expectedRetSlots != null) {
|
||||||
|
throw new IllegalArgumentException("SET_LOCAL must not carry call metadata");
|
||||||
|
}
|
||||||
|
}
|
||||||
case CALL_FUNC -> {
|
case CALL_FUNC -> {
|
||||||
if (calleeCallableId == null) {
|
if (calleeCallableId == null) {
|
||||||
throw new IllegalArgumentException("CALL_FUNC requires calleeCallableId");
|
throw new IllegalArgumentException("CALL_FUNC requires calleeCallableId");
|
||||||
@ -287,10 +315,13 @@ public record IRBackendExecutableFunction(
|
|||||||
throw new IllegalArgumentException("CALL_INTRINSIC must not carry host metadata");
|
throw new IllegalArgumentException("CALL_INTRINSIC must not carry host metadata");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case HALT, RET -> {
|
case HALT, RET, POP, ADD, SUB, MUL, DIV, MOD, EQ, NEQ, LT, LTE, GT, GTE, AND, OR, NOT, NEG -> {
|
||||||
if (!calleeCallableName.isBlank() || calleeCallableId != null || hostCall != null || intrinsicCall != null) {
|
if (!calleeCallableName.isBlank() || calleeCallableId != null || hostCall != null || intrinsicCall != null) {
|
||||||
throw new IllegalArgumentException(kind + " must not carry callsite metadata");
|
throw new IllegalArgumentException(kind + " must not carry callsite metadata");
|
||||||
}
|
}
|
||||||
|
if (!label.isBlank() || !targetLabel.isBlank()) {
|
||||||
|
throw new IllegalArgumentException(kind + " must not carry label metadata");
|
||||||
|
}
|
||||||
if (expectedArgSlots != null || expectedRetSlots != null) {
|
if (expectedArgSlots != null || expectedRetSlots != null) {
|
||||||
throw new IllegalArgumentException(kind + " must not carry expected slot metadata");
|
throw new IllegalArgumentException(kind + " must not carry expected slot metadata");
|
||||||
}
|
}
|
||||||
@ -329,8 +360,26 @@ public record IRBackendExecutableFunction(
|
|||||||
|
|
||||||
public enum InstructionKind {
|
public enum InstructionKind {
|
||||||
PUSH_I32,
|
PUSH_I32,
|
||||||
|
PUSH_BOOL,
|
||||||
PUSH_CONST,
|
PUSH_CONST,
|
||||||
GET_LOCAL,
|
GET_LOCAL,
|
||||||
|
SET_LOCAL,
|
||||||
|
POP,
|
||||||
|
ADD,
|
||||||
|
SUB,
|
||||||
|
MUL,
|
||||||
|
DIV,
|
||||||
|
MOD,
|
||||||
|
EQ,
|
||||||
|
NEQ,
|
||||||
|
LT,
|
||||||
|
LTE,
|
||||||
|
GT,
|
||||||
|
GTE,
|
||||||
|
AND,
|
||||||
|
OR,
|
||||||
|
NOT,
|
||||||
|
NEG,
|
||||||
HALT,
|
HALT,
|
||||||
RET,
|
RET,
|
||||||
CALL_FUNC,
|
CALL_FUNC,
|
||||||
|
|||||||
Binary file not shown.
@ -15,6 +15,10 @@ fn frame() -> void
|
|||||||
{
|
{
|
||||||
total += 5;
|
total += 5;
|
||||||
}
|
}
|
||||||
|
else if (Input.pad().x().pressed())
|
||||||
|
{
|
||||||
|
total -= 10;
|
||||||
|
}
|
||||||
|
|
||||||
if (total == 30)
|
if (total == 30)
|
||||||
{
|
{
|
||||||
@ -24,7 +28,7 @@ fn frame() -> void
|
|||||||
{
|
{
|
||||||
Log.error("50 is the magic number!");
|
Log.error("50 is the magic number!");
|
||||||
}
|
}
|
||||||
else
|
else if (total == 15)
|
||||||
{
|
{
|
||||||
Log.warn("The magic number is neither 30 nor 50!");
|
Log.warn("The magic number is neither 30 nor 50!");
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user