Add "Opcode" type
This commit is contained in:
parent
935c629460
commit
db6ff8deba
12 changed files with 180 additions and 5 deletions
|
@ -35,6 +35,7 @@ target_sources(vm_lib
|
|||
src/writer.hpp
|
||||
src/utf8.hpp
|
||||
src/compiler.hpp
|
||||
src/opcode.hpp
|
||||
)
|
||||
|
||||
add_executable(vli src/vli.cpp)
|
||||
|
|
|
@ -79,6 +79,8 @@ Result<PodObject*> Arena::gc_pod(PodObject* obj) {
|
|||
return gc_bytearray((PodByteArray*)obj);
|
||||
case Tag::Dict:
|
||||
return gc_dict((PodDict*)obj);
|
||||
case Tag::Opcode:
|
||||
return gc_opcode((PodOpcode*)obj);
|
||||
}
|
||||
|
||||
return ERROR(TypeMismatch);
|
||||
|
@ -178,6 +180,18 @@ Result<PodObject*> Arena::gc_dict(PodDict* obj) {
|
|||
return nobj;
|
||||
}
|
||||
|
||||
Result<PodObject*> Arena::gc_opcode(PodOpcode* obj) {
|
||||
auto nobj = TRY(alloc<PodOpcode>());
|
||||
nobj->header.tag = Tag::Opcode;
|
||||
nobj->opcode = obj->opcode;
|
||||
nobj->arg1 = obj->arg1;
|
||||
nobj->arg2 = obj->arg2;
|
||||
nobj->arg3 = obj->arg3;
|
||||
nobj->arg4 = obj->arg4;
|
||||
|
||||
return nobj;
|
||||
}
|
||||
|
||||
Arena& get_arena() {
|
||||
if (current_arena == 0) die("Arena not set\n");
|
||||
return *current_arena;
|
||||
|
|
|
@ -154,6 +154,7 @@ class Arena {
|
|||
Result<PodObject*> gc_array(PodArray* obj);
|
||||
Result<PodObject*> gc_bytearray(PodByteArray* obj);
|
||||
Result<PodObject*> gc_dict(PodDict* obj);
|
||||
Result<PodObject*> gc_opcode(PodOpcode* obj);
|
||||
|
||||
void add_root(GcRootList* node) { _gcroot.insert(node); }
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ Result<Value> Value::create(PodObject* obj) {
|
|||
return Value(TRY(Syntax::create((PodSyntax*)obj)));
|
||||
case Tag::Pair:
|
||||
return Value(TRY(Pair::create((PodPair*)obj)));
|
||||
case Tag::Opcode:
|
||||
return Value(TRY(Opcode::create((PodOpcode*)obj)));
|
||||
};
|
||||
return Value();
|
||||
}
|
||||
|
@ -101,6 +103,8 @@ Result<Value> Pair::copy() const { return Value(Pair(TRY(_value.copy()))); }
|
|||
|
||||
Result<Value> Bool::copy() const { return Value(Bool(TRY(_value.copy()))); }
|
||||
|
||||
Result<Value> Opcode::copy() const { return Value(Opcode(TRY(_value.copy()))); }
|
||||
|
||||
Result<Pair> Pair::create(Value& first, Value& rest) {
|
||||
auto pod = TRY(arena_alloc<PodPair>());
|
||||
pod->header.tag = Tag::Pair;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "arena.hpp"
|
||||
#include "error.hpp"
|
||||
#include "opcode.hpp"
|
||||
#include "pod.hpp"
|
||||
#include "utf8.hpp"
|
||||
|
||||
|
@ -699,6 +700,48 @@ class Bool : public Object {
|
|||
GcRoot<PodBool> _value;
|
||||
};
|
||||
|
||||
class Opcode : public Object {
|
||||
public:
|
||||
Opcode() {}
|
||||
Opcode(Opcode&& rhs) : _value(std::move(rhs._value)) {}
|
||||
Opcode(GcRoot<PodOpcode>&& val) : _value(std::move(val)) {}
|
||||
|
||||
virtual Tag tag() final { return Tag::Opcode; }
|
||||
virtual PodObject* pod() final { return _value.get(); }
|
||||
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
|
||||
virtual Result<short> cmp(Opcode& rhs) final { return 0; }
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Opcode(std::move(_value)); }
|
||||
|
||||
static Result<Opcode> create(PodOpcode* obj) {
|
||||
return Opcode(TRY(MkGcRoot(obj)));
|
||||
}
|
||||
|
||||
static Result<Opcode> create(Oc opcode, OpArg arg1 = {0, 0},
|
||||
OpArg arg2 = {0, 0}, OpArg arg3 = {0, 0},
|
||||
OpArg arg4 = {0, 0}) {
|
||||
auto pod = TRY(arena_alloc<PodOpcode>());
|
||||
pod->header.tag = Tag::Opcode;
|
||||
pod->opcode = opcode;
|
||||
pod->arg1 = arg1;
|
||||
pod->arg2 = arg2;
|
||||
pod->arg3 = arg3;
|
||||
pod->arg4 = arg4;
|
||||
|
||||
return Opcode(TRY(MkGcRoot(pod)));
|
||||
}
|
||||
|
||||
Oc opcode() { return _value->opcode; }
|
||||
OpArg arg1() { return _value->arg1; }
|
||||
OpArg arg2() { return _value->arg2; }
|
||||
OpArg arg3() { return _value->arg3; }
|
||||
OpArg arg4() { return _value->arg4; }
|
||||
|
||||
virtual Result<Value> copy() const final;
|
||||
|
||||
private:
|
||||
GcRoot<PodOpcode> _value;
|
||||
};
|
||||
// note: this class doesn't perform proper destruction of objects in some cases
|
||||
class Value {
|
||||
public:
|
||||
|
|
|
@ -15,12 +15,25 @@ struct Context {
|
|||
return Context(std::move(env), std::move(constants));
|
||||
}
|
||||
|
||||
uint64_t alloc_reg() {
|
||||
uint64_t reg = maxreg;
|
||||
++maxreg;
|
||||
return reg;
|
||||
}
|
||||
|
||||
Value env;
|
||||
Array constants;
|
||||
uint64_t maxreg;
|
||||
uint64_t maxconst;
|
||||
};
|
||||
|
||||
Result<Array> add_opcode(Array& opcodes, Oc opcode, OpArg arg1 = {0, 0},
|
||||
OpArg arg2 = {0, 0}, OpArg arg3 = {0, 0},
|
||||
OpArg arg4 = {0, 0}) {
|
||||
Value oc = Value(TRY(Opcode::create(opcode, arg1, arg2, arg3, arg4)));
|
||||
return opcodes.append(oc);
|
||||
}
|
||||
|
||||
Result<bool> is_primitive_op(Symbol& sym) {
|
||||
return TRY(sym.cmp("+")) == 0 || TRY(sym.cmp("-")) == 0 ||
|
||||
TRY(sym.cmp("*")) == 0 || TRY(sym.cmp("/")) == 0;
|
||||
|
@ -37,9 +50,10 @@ Result<Expression> Compiler::compile_expr(Context& context, Value& expr) {
|
|||
switch (expr.tag()) {
|
||||
case Tag::Pair:
|
||||
return compile_list(context, *expr.to<Pair>());
|
||||
case Tag::Int64:
|
||||
return compile_int64(context, *expr.to<Int64>());
|
||||
case Tag::Nil:
|
||||
case Tag::Bool:
|
||||
case Tag::Int64:
|
||||
case Tag::Float:
|
||||
case Tag::String:
|
||||
case Tag::Symbol:
|
||||
|
@ -47,6 +61,7 @@ Result<Expression> Compiler::compile_expr(Context& context, Value& expr) {
|
|||
case Tag::Array:
|
||||
case Tag::ByteArray:
|
||||
case Tag::Dict:
|
||||
case Tag::Opcode:
|
||||
return ERROR(TypeMismatch);
|
||||
}
|
||||
return ERROR(TypeMismatch);
|
||||
|
@ -54,21 +69,30 @@ Result<Expression> Compiler::compile_expr(Context& context, Value& expr) {
|
|||
|
||||
Result<Expression> Compiler::compile_primop(Context& context, Symbol& op,
|
||||
Pair& expr) {
|
||||
std::cout << "primop\n";
|
||||
|
||||
Value cur = TRY(expr.rest());
|
||||
Array code = TRY(Array::create());
|
||||
|
||||
uint64_t reg = context.alloc_reg();
|
||||
std::cout << "load-immediate r" << reg << ", " << 0 << "\n";
|
||||
code = TRY(add_opcode(code, Oc::LoadImmediate, {0, (int64_t)reg}, {0, 0}));
|
||||
|
||||
while (!cur.is<Nil>()) {
|
||||
Pair& pair = *cur.to<Pair>();
|
||||
auto subexpr = TRY(pair.first());
|
||||
|
||||
auto comp = TRY(compile_expr(context, subexpr));
|
||||
|
||||
uint64_t res = context.alloc_reg();
|
||||
std::cout << "add r" << res << ", r" << reg << ", r" << comp.reg << "\n";
|
||||
|
||||
reg = res;
|
||||
cur = TRY(pair.rest());
|
||||
}
|
||||
return ERROR(TypeMismatch);
|
||||
|
||||
Expression ex = Expression(reg, TRY(Array::create()));
|
||||
return ex;
|
||||
}
|
||||
|
||||
Result<Expression> Compiler::compile_list(Context& context, Pair& expr) {
|
||||
auto first = TRY(expr.first());
|
||||
|
||||
|
@ -80,3 +104,11 @@ Result<Expression> Compiler::compile_list(Context& context, Pair& expr) {
|
|||
}
|
||||
return ERROR(TypeMismatch);
|
||||
}
|
||||
|
||||
Result<Expression> Compiler::compile_int64(Context& context, Int64& value) {
|
||||
uint64_t reg = context.alloc_reg();
|
||||
std::cout << "loadc r" << reg << ", " << value.value() << "\n";
|
||||
|
||||
Expression expr = Expression(reg, TRY(Array::create()));
|
||||
return expr;
|
||||
}
|
||||
|
|
|
@ -19,4 +19,5 @@ class Compiler {
|
|||
Result<Expression> compile_expr(Context& context, Value& expr);
|
||||
Result<Expression> compile_list(Context& context, Pair& expr);
|
||||
Result<Expression> compile_primop(Context& context, Symbol& op, Pair& expr);
|
||||
Result<Expression> compile_int64(Context& context, Int64& value);
|
||||
};
|
||||
|
|
59
src/opcode.hpp
Normal file
59
src/opcode.hpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class Oc : uint8_t {
|
||||
Unknown = 0,
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
Mov,
|
||||
LoadImmediate,
|
||||
// constants
|
||||
LoadConst,
|
||||
// Load/store
|
||||
LoadStack,
|
||||
// Jumps
|
||||
Jump,
|
||||
JumpEqual,
|
||||
JumpLess,
|
||||
JumpLessEqual,
|
||||
JumpNotEqual,
|
||||
// Function calls
|
||||
Call,
|
||||
TailCall,
|
||||
// Return from function call
|
||||
Ret,
|
||||
RetNil,
|
||||
// Shifts
|
||||
ShiftRight,
|
||||
ShiftLeft,
|
||||
// Bitwise
|
||||
BitwiseAnd,
|
||||
BitwiseOr,
|
||||
BitwiseXor,
|
||||
BitwiseNeg,
|
||||
// Arrays
|
||||
MakeArray,
|
||||
ArrayLoad,
|
||||
ArrayStore,
|
||||
// Stack
|
||||
Push,
|
||||
Pop,
|
||||
StackReserve,
|
||||
// Assert
|
||||
AssertEqual,
|
||||
// Dictionaries
|
||||
MakeDict,
|
||||
SetJump,
|
||||
// Globals
|
||||
SetGlobal,
|
||||
GetGlobal,
|
||||
};
|
||||
|
||||
struct OpArg {
|
||||
uint8_t is_const : 1 = 0;
|
||||
int64_t arg : 63 = 0;
|
||||
};
|
13
src/pod.hpp
13
src/pod.hpp
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
#include "opcode.hpp"
|
||||
#include "result.hpp"
|
||||
#include "sourcerange.hpp"
|
||||
|
||||
|
@ -17,6 +18,7 @@ enum class Tag : uint8_t {
|
|||
Array,
|
||||
ByteArray,
|
||||
Dict,
|
||||
Opcode,
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@ -142,6 +144,17 @@ class PodPair : public PodObject {
|
|||
OffPtr<PodObject> rest;
|
||||
};
|
||||
|
||||
class PodOpcode final : public PodObject {
|
||||
public:
|
||||
PodOpcode() : PodObject(Tag::Opcode){};
|
||||
|
||||
Oc opcode;
|
||||
OpArg arg1;
|
||||
OpArg arg2;
|
||||
OpArg arg3;
|
||||
OpArg arg4;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Ptr {
|
||||
public:
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
StaticArena<64 * 1024 * 1024> arena;
|
||||
|
||||
int main() {
|
||||
auto s = DIEX(String::create("(+ 1 2 3)"));
|
||||
auto s = DIEX(String::create("(+ (+ 1 2 3) 4)"));
|
||||
auto reader = Reader(s);
|
||||
|
||||
auto r = DIEX(reader.read_one());
|
||||
|
|
|
@ -24,6 +24,8 @@ Result<String> Writer::write_one(Value& obj) {
|
|||
return write_syntax(*obj.to<Syntax>());
|
||||
case Tag::Pair:
|
||||
return write_pair(*obj.to<Pair>());
|
||||
case Tag::Opcode:
|
||||
return write_opcode(*obj.to<Opcode>());
|
||||
};
|
||||
return String();
|
||||
}
|
||||
|
@ -212,6 +214,10 @@ Result<String> Writer::write_dict(Dict& val) {
|
|||
return res;
|
||||
}
|
||||
|
||||
Result<String> Writer::write_opcode(Opcode& val) {
|
||||
return ERROR(NotImplemented);
|
||||
}
|
||||
|
||||
Result<String> write_one(Value& value) {
|
||||
auto w = Writer();
|
||||
return w.write_one(value);
|
||||
|
|
|
@ -22,6 +22,7 @@ class Writer {
|
|||
Result<String> write_dict(Dict& val);
|
||||
Result<String> write_symbol(Symbol& val);
|
||||
Result<String> write_syntax(Syntax& val);
|
||||
Result<String> write_opcode(Opcode& val);
|
||||
};
|
||||
|
||||
Result<String> write_one(Value& value);
|
||||
|
|
Loading…
Reference in a new issue