Implement writing of opcodes

This commit is contained in:
Konstantin Nazarov 2024-08-11 02:25:44 +01:00
parent 3cb4869ed5
commit 74bff1a4c4
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
4 changed files with 161 additions and 2 deletions

View file

@ -19,6 +19,7 @@ target_sources(vm_lib
src/writer.cpp src/writer.cpp
src/utf8.cpp src/utf8.cpp
src/compiler.cpp src/compiler.cpp
src/opcode.cpp
PUBLIC PUBLIC
FILE_SET HEADERS FILE_SET HEADERS

92
src/opcode.cpp Normal file
View file

@ -0,0 +1,92 @@
#include "opcode.hpp"
#include "die.hpp"
struct op_t {
const char* opname;
OpcodeType optype;
};
static const op_t opcode_tbl[] = {};
op_t get_op(Oc op) {
switch (op) {
case Oc::Unknown:
return op_t{0, OpcodeType::Reg0};
case Oc::Add:
return op_t{"add", OpcodeType::Reg3};
case Oc::Sub:
return op_t{"sub", OpcodeType::Reg3};
case Oc::Mul:
return op_t{"mul", OpcodeType::Reg3};
case Oc::Div:
return op_t{"div", OpcodeType::Reg3};
case Oc::Mod:
return op_t{"mod", OpcodeType::Reg3};
case Oc::Mov:
return op_t{"mov", OpcodeType::Reg2};
case Oc::LoadConst:
return op_t{"loadc", OpcodeType::Reg1I};
case Oc::LoadStack:
return op_t{"lfi", OpcodeType::Reg1I};
case Oc::Jump:
return op_t{"jmp", OpcodeType::Reg0I};
case Oc::JumpEqual:
return op_t{"jeq", OpcodeType::Reg2I};
case Oc::JumpLess:
return op_t{"jlt", OpcodeType::Reg2I};
case Oc::JumpLessEqual:
return op_t{"jle", OpcodeType::Reg2I};
case Oc::JumpNotEqual:
return op_t{"jne", OpcodeType::Reg2I};
case Oc::Call:
return op_t{"call", OpcodeType::Reg1I};
case Oc::TailCall:
return op_t{"tailcall", OpcodeType::Reg1I};
case Oc::Ret:
return op_t{"ret", OpcodeType::Reg1};
case Oc::RetNil:
return op_t{"retnil", OpcodeType::Reg0};
case Oc::ShiftRight:
return op_t{"sri", OpcodeType::Reg2I};
case Oc::ShiftLeft:
return op_t{"sli", OpcodeType::Reg2I};
case Oc::BitwiseAnd:
return op_t{"band", OpcodeType::Reg3};
case Oc::BitwiseOr:
return op_t{"bor", OpcodeType::Reg3};
case Oc::BitwiseXor:
return op_t{"bxor", OpcodeType::Reg3};
case Oc::BitwiseNeg:
return op_t{"bneg", OpcodeType::Reg2};
case Oc::MakeArray:
return op_t{"make-array", OpcodeType::Reg1I};
case Oc::ArrayLoad:
return op_t{"al", OpcodeType::Reg3};
case Oc::ArrayStore:
return op_t{"as", OpcodeType::Reg4};
case Oc::Push:
return op_t{"push", OpcodeType::Reg1};
case Oc::Pop:
return op_t{"pop", OpcodeType::Reg1};
case Oc::StackReserve:
return op_t{"sr", OpcodeType::Reg0I};
case Oc::AssertEqual:
return op_t{"assert-equal", OpcodeType::Reg2};
case Oc::MakeDict:
return op_t{"make-dict", OpcodeType::Reg1};
case Oc::SetJump:
return op_t{"setjump", OpcodeType::Reg1I};
case Oc::SetGlobal:
return op_t{"setglobal", OpcodeType::Reg2};
case Oc::GetGlobal:
return op_t{"getglobal", OpcodeType::Reg2};
default:
die("Unknown opcode\n");
}
}
const char* opcode_name(Oc op) { return get_op(op).opname; }
OpcodeType opcode_type(Oc op) { return get_op(op).optype; }

View file

@ -2,6 +2,18 @@
#include <cstdint> #include <cstdint>
enum class OpcodeType : uint8_t {
Unknown = 0,
Reg0,
Reg0I,
Reg1,
Reg1I,
Reg2,
Reg2I,
Reg3,
Reg4,
};
enum class Oc : uint8_t { enum class Oc : uint8_t {
Unknown = 0, Unknown = 0,
Add, Add,
@ -10,7 +22,6 @@ enum class Oc : uint8_t {
Div, Div,
Mod, Mod,
Mov, Mov,
LoadImmediate,
// constants // constants
LoadConst, LoadConst,
// Load/store // Load/store
@ -57,3 +68,6 @@ struct OpArg {
uint8_t is_const : 1 = 0; uint8_t is_const : 1 = 0;
int64_t arg : 63 = 0; int64_t arg : 63 = 0;
}; };
const char* opcode_name(Oc op);
OpcodeType opcode_type(Oc op);

View file

@ -1,5 +1,8 @@
#include "writer.hpp" #include "writer.hpp"
#include "error.hpp"
#include "opcode.hpp"
Result<String> Writer::write_one(Value& obj) { Result<String> Writer::write_one(Value& obj) {
switch (obj.tag()) { switch (obj.tag()) {
case Tag::Nil: case Tag::Nil:
@ -215,8 +218,57 @@ Result<String> Writer::write_dict(Dict& val) {
} }
Result<String> Writer::write_opcode(Opcode& val) { Result<String> Writer::write_opcode(Opcode& val) {
String res = TRY(String::create("#<opcode>")); String res = TRY(String::create("#<opcode "));
const char* name = opcode_name(val.opcode());
OpcodeType ot = opcode_type(val.opcode());
char buf[256];
switch (ot) {
case OpcodeType::Unknown:
return ERROR(TypeMismatch);
case OpcodeType::Reg0:
sprintf(buf, "%s", name);
break;
case OpcodeType::Reg0I:
sprintf(buf, "%s %ld", name, val.arg1().arg);
break;
case OpcodeType::Reg1:
sprintf(buf, "%s %s%ld", name, (val.arg1().is_const) ? "c" : "r",
val.arg1().arg);
break;
case OpcodeType::Reg1I:
sprintf(buf, "%s %s%ld %ld", name, (val.arg1().is_const) ? "c" : "r",
val.arg1().arg, val.arg2().arg);
break;
case OpcodeType::Reg2:
sprintf(buf, "%s %s%ld %s%ld", name, (val.arg1().is_const) ? "c" : "r",
val.arg1().arg, (val.arg2().is_const) ? "c" : "r",
val.arg2().arg);
break;
case OpcodeType::Reg2I:
sprintf(buf, "%s %s%ld %s%ld %ld", name,
(val.arg1().is_const) ? "c" : "r", val.arg1().arg,
(val.arg2().is_const) ? "c" : "r", val.arg2().arg,
val.arg3().arg);
break;
case OpcodeType::Reg3:
sprintf(buf, "%s %s%ld %s%ld %s%ld", name,
(val.arg1().is_const) ? "c" : "r", val.arg1().arg,
(val.arg2().is_const) ? "c" : "r", val.arg2().arg,
(val.arg3().is_const) ? "c" : "r", val.arg3().arg);
break;
case OpcodeType::Reg4:
sprintf(buf, "%s %s%ld %s%ld %s%ld %s%ld", name,
(val.arg1().is_const) ? "c" : "r", val.arg1().arg,
(val.arg2().is_const) ? "c" : "r", val.arg2().arg,
(val.arg3().is_const) ? "c" : "r", val.arg3().arg,
(val.arg4().is_const) ? "c" : "r", val.arg4().arg);
break;
}
res = TRY(res.concat(buf));
res = TRY(res.concat(">"));
return res; return res;
} }