Add "Opcode" type

This commit is contained in:
Konstantin Nazarov 2024-08-10 18:24:16 +01:00
parent 935c629460
commit db6ff8deba
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
12 changed files with 180 additions and 5 deletions

View file

@ -35,6 +35,7 @@ target_sources(vm_lib
src/writer.hpp src/writer.hpp
src/utf8.hpp src/utf8.hpp
src/compiler.hpp src/compiler.hpp
src/opcode.hpp
) )
add_executable(vli src/vli.cpp) add_executable(vli src/vli.cpp)

View file

@ -79,6 +79,8 @@ Result<PodObject*> Arena::gc_pod(PodObject* obj) {
return gc_bytearray((PodByteArray*)obj); return gc_bytearray((PodByteArray*)obj);
case Tag::Dict: case Tag::Dict:
return gc_dict((PodDict*)obj); return gc_dict((PodDict*)obj);
case Tag::Opcode:
return gc_opcode((PodOpcode*)obj);
} }
return ERROR(TypeMismatch); return ERROR(TypeMismatch);
@ -178,6 +180,18 @@ Result<PodObject*> Arena::gc_dict(PodDict* obj) {
return nobj; 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() { Arena& get_arena() {
if (current_arena == 0) die("Arena not set\n"); if (current_arena == 0) die("Arena not set\n");
return *current_arena; return *current_arena;

View file

@ -154,6 +154,7 @@ class Arena {
Result<PodObject*> gc_array(PodArray* obj); Result<PodObject*> gc_array(PodArray* obj);
Result<PodObject*> gc_bytearray(PodByteArray* obj); Result<PodObject*> gc_bytearray(PodByteArray* obj);
Result<PodObject*> gc_dict(PodDict* obj); Result<PodObject*> gc_dict(PodDict* obj);
Result<PodObject*> gc_opcode(PodOpcode* obj);
void add_root(GcRootList* node) { _gcroot.insert(node); } void add_root(GcRootList* node) { _gcroot.insert(node); }

View file

@ -36,6 +36,8 @@ Result<Value> Value::create(PodObject* obj) {
return Value(TRY(Syntax::create((PodSyntax*)obj))); return Value(TRY(Syntax::create((PodSyntax*)obj)));
case Tag::Pair: case Tag::Pair:
return Value(TRY(Pair::create((PodPair*)obj))); return Value(TRY(Pair::create((PodPair*)obj)));
case Tag::Opcode:
return Value(TRY(Opcode::create((PodOpcode*)obj)));
}; };
return Value(); 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> 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) { Result<Pair> Pair::create(Value& first, Value& rest) {
auto pod = TRY(arena_alloc<PodPair>()); auto pod = TRY(arena_alloc<PodPair>());
pod->header.tag = Tag::Pair; pod->header.tag = Tag::Pair;

View file

@ -7,6 +7,7 @@
#include "arena.hpp" #include "arena.hpp"
#include "error.hpp" #include "error.hpp"
#include "opcode.hpp"
#include "pod.hpp" #include "pod.hpp"
#include "utf8.hpp" #include "utf8.hpp"
@ -699,6 +700,48 @@ class Bool : public Object {
GcRoot<PodBool> _value; 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 // note: this class doesn't perform proper destruction of objects in some cases
class Value { class Value {
public: public:

View file

@ -15,12 +15,25 @@ struct Context {
return Context(std::move(env), std::move(constants)); return Context(std::move(env), std::move(constants));
} }
uint64_t alloc_reg() {
uint64_t reg = maxreg;
++maxreg;
return reg;
}
Value env; Value env;
Array constants; Array constants;
uint64_t maxreg; uint64_t maxreg;
uint64_t maxconst; 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) { Result<bool> is_primitive_op(Symbol& sym) {
return TRY(sym.cmp("+")) == 0 || TRY(sym.cmp("-")) == 0 || return TRY(sym.cmp("+")) == 0 || TRY(sym.cmp("-")) == 0 ||
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()) { switch (expr.tag()) {
case Tag::Pair: case Tag::Pair:
return compile_list(context, *expr.to<Pair>()); return compile_list(context, *expr.to<Pair>());
case Tag::Int64:
return compile_int64(context, *expr.to<Int64>());
case Tag::Nil: case Tag::Nil:
case Tag::Bool: case Tag::Bool:
case Tag::Int64:
case Tag::Float: case Tag::Float:
case Tag::String: case Tag::String:
case Tag::Symbol: case Tag::Symbol:
@ -47,6 +61,7 @@ Result<Expression> Compiler::compile_expr(Context& context, Value& expr) {
case Tag::Array: case Tag::Array:
case Tag::ByteArray: case Tag::ByteArray:
case Tag::Dict: case Tag::Dict:
case Tag::Opcode:
return ERROR(TypeMismatch); return ERROR(TypeMismatch);
} }
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, Result<Expression> Compiler::compile_primop(Context& context, Symbol& op,
Pair& expr) { Pair& expr) {
std::cout << "primop\n";
Value cur = TRY(expr.rest()); Value cur = TRY(expr.rest());
Array code = TRY(Array::create()); 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>()) { while (!cur.is<Nil>()) {
Pair& pair = *cur.to<Pair>(); Pair& pair = *cur.to<Pair>();
auto subexpr = TRY(pair.first()); auto subexpr = TRY(pair.first());
auto comp = TRY(compile_expr(context, subexpr)); 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()); 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) { Result<Expression> Compiler::compile_list(Context& context, Pair& expr) {
auto first = TRY(expr.first()); auto first = TRY(expr.first());
@ -80,3 +104,11 @@ Result<Expression> Compiler::compile_list(Context& context, Pair& expr) {
} }
return ERROR(TypeMismatch); 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;
}

View file

@ -19,4 +19,5 @@ class Compiler {
Result<Expression> compile_expr(Context& context, Value& expr); Result<Expression> compile_expr(Context& context, Value& expr);
Result<Expression> compile_list(Context& context, Pair& expr); Result<Expression> compile_list(Context& context, Pair& expr);
Result<Expression> compile_primop(Context& context, Symbol& op, 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
View 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;
};

View file

@ -2,6 +2,7 @@
#include <cstdint> #include <cstdint>
#include "opcode.hpp"
#include "result.hpp" #include "result.hpp"
#include "sourcerange.hpp" #include "sourcerange.hpp"
@ -17,6 +18,7 @@ enum class Tag : uint8_t {
Array, Array,
ByteArray, ByteArray,
Dict, Dict,
Opcode,
}; };
template <class T> template <class T>
@ -142,6 +144,17 @@ class PodPair : public PodObject {
OffPtr<PodObject> rest; 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> template <class T>
class Ptr { class Ptr {
public: public:

View file

@ -9,7 +9,7 @@
StaticArena<64 * 1024 * 1024> arena; StaticArena<64 * 1024 * 1024> arena;
int main() { int main() {
auto s = DIEX(String::create("(+ 1 2 3)")); auto s = DIEX(String::create("(+ (+ 1 2 3) 4)"));
auto reader = Reader(s); auto reader = Reader(s);
auto r = DIEX(reader.read_one()); auto r = DIEX(reader.read_one());

View file

@ -24,6 +24,8 @@ Result<String> Writer::write_one(Value& obj) {
return write_syntax(*obj.to<Syntax>()); return write_syntax(*obj.to<Syntax>());
case Tag::Pair: case Tag::Pair:
return write_pair(*obj.to<Pair>()); return write_pair(*obj.to<Pair>());
case Tag::Opcode:
return write_opcode(*obj.to<Opcode>());
}; };
return String(); return String();
} }
@ -212,6 +214,10 @@ Result<String> Writer::write_dict(Dict& val) {
return res; return res;
} }
Result<String> Writer::write_opcode(Opcode& val) {
return ERROR(NotImplemented);
}
Result<String> write_one(Value& value) { Result<String> write_one(Value& value) {
auto w = Writer(); auto w = Writer();
return w.write_one(value); return w.write_one(value);

View file

@ -22,6 +22,7 @@ class Writer {
Result<String> write_dict(Dict& val); Result<String> write_dict(Dict& val);
Result<String> write_symbol(Symbol& val); Result<String> write_symbol(Symbol& val);
Result<String> write_syntax(Syntax& val); Result<String> write_syntax(Syntax& val);
Result<String> write_opcode(Opcode& val);
}; };
Result<String> write_one(Value& value); Result<String> write_one(Value& value);