Implement writing of opcodes
This commit is contained in:
parent
3cb4869ed5
commit
74bff1a4c4
4 changed files with 161 additions and 2 deletions
|
@ -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
92
src/opcode.cpp
Normal 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; }
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue