refactor(furas): use new instructions from furvm
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
func println $s32 = native println
|
||||||
|
|
||||||
|
public func main = #main
|
||||||
|
main:
|
||||||
|
push $s32 69
|
||||||
|
call $s32 println
|
||||||
|
ret
|
||||||
|
|||||||
+59
-67
@@ -21,48 +21,36 @@ using namespace std::string_literals;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct instruction {
|
|
||||||
furvm::instruction_t fur{};
|
|
||||||
enum arg_type {
|
|
||||||
None = 0,
|
|
||||||
Type,
|
|
||||||
Constant,
|
|
||||||
Variable,
|
|
||||||
Function,
|
|
||||||
Label,
|
|
||||||
} arg = None;
|
|
||||||
};
|
|
||||||
|
|
||||||
// NOLINTBEGIN
|
// NOLINTBEGIN
|
||||||
std::unordered_map<enum token::type, instruction> instructions = {
|
std::unordered_map<enum token::type, furvm::instruction_t> instructions = {
|
||||||
{ token::Array, { furvm::instruction_t::Array, instruction::Type } },
|
{ token::Array, furvm::instruction_t::Array },
|
||||||
{ token::Get, { furvm::instruction_t::Get } },
|
{ token::Get, furvm::instruction_t::Get },
|
||||||
{ token::Set, { furvm::instruction_t::Set } },
|
{ token::Set, furvm::instruction_t::Set },
|
||||||
{ token::Drop, { furvm::instruction_t::Drop } },
|
{ token::Drop, furvm::instruction_t::Drop },
|
||||||
{ token::Dup, { furvm::instruction_t::Duplicate } },
|
{ token::Dup, furvm::instruction_t::Duplicate },
|
||||||
{ token::Swap, { furvm::instruction_t::Swap } },
|
{ token::Swap, furvm::instruction_t::Swap },
|
||||||
{ token::Clone, { furvm::instruction_t::Clone } },
|
{ token::Clone, furvm::instruction_t::Clone },
|
||||||
{ token::Ref, { furvm::instruction_t::Reference } },
|
{ token::Ref, furvm::instruction_t::Reference },
|
||||||
{ token::Add, { furvm::instruction_t::Add } },
|
{ token::Add, furvm::instruction_t::Add },
|
||||||
{ token::Sub, { furvm::instruction_t::Sub } },
|
{ token::Sub, furvm::instruction_t::Sub },
|
||||||
{ token::Mul, { furvm::instruction_t::Mul } },
|
{ token::Mul, furvm::instruction_t::Mul },
|
||||||
{ token::Div, { furvm::instruction_t::Div } },
|
{ token::Div, furvm::instruction_t::Div },
|
||||||
{ token::Mod, { furvm::instruction_t::Mod } },
|
{ token::Mod, furvm::instruction_t::Mod },
|
||||||
{ token::Eq, { furvm::instruction_t::Equals } },
|
{ token::Eq, furvm::instruction_t::Equals },
|
||||||
{ token::Neq, { furvm::instruction_t::NotEquals } },
|
{ token::Neq, furvm::instruction_t::NotEquals },
|
||||||
{ token::Lt, { furvm::instruction_t::LessThan } },
|
{ token::Lt, furvm::instruction_t::LessThan },
|
||||||
{ token::Gt, { furvm::instruction_t::GreaterThan } },
|
{ token::Gt, furvm::instruction_t::GreaterThan },
|
||||||
{ token::Le, { furvm::instruction_t::LessEqual } },
|
{ token::Le, furvm::instruction_t::LessEqual },
|
||||||
{ token::Ge, { furvm::instruction_t::GreaterEqual } },
|
{ token::Ge, furvm::instruction_t::GreaterEqual },
|
||||||
{ token::Ptrof, { furvm::instruction_t::Pointerof } },
|
{ token::Ptrof, furvm::instruction_t::Pointerof },
|
||||||
{ token::Sizeof, { furvm::instruction_t::Sizeof } },
|
{ token::Sizeof, furvm::instruction_t::Sizeof },
|
||||||
{ token::Lenof, { furvm::instruction_t::Lengthof } },
|
{ token::Lenof, furvm::instruction_t::Lengthof },
|
||||||
{ token::Load, { furvm::instruction_t::Load, instruction::Variable } },
|
{ token::Load, furvm::instruction_t::Load },
|
||||||
{ token::Store, { furvm::instruction_t::Store, instruction::Variable } },
|
{ token::Store, furvm::instruction_t::Store },
|
||||||
{ token::Call, { furvm::instruction_t::Call, instruction::Function } },
|
{ token::Call, furvm::instruction_t::Call },
|
||||||
{ token::Jmp, { furvm::instruction_t::Jump, instruction::Label } },
|
{ token::Jmp, furvm::instruction_t::Jump },
|
||||||
{ token::Jnz, { furvm::instruction_t::JumpNotZero, instruction::Label } },
|
{ token::Jnz, furvm::instruction_t::JumpNotZero },
|
||||||
{ token::Ret, { furvm::instruction_t::Return } },
|
{ token::Ret, furvm::instruction_t::Return },
|
||||||
};
|
};
|
||||||
// NOLINTEND
|
// NOLINTEND
|
||||||
|
|
||||||
@@ -214,12 +202,12 @@ struct mod_context {
|
|||||||
handle.dispatch();
|
handle.dispatch();
|
||||||
}
|
}
|
||||||
for (auto unknown : label.unknowns) {
|
for (auto unknown : label.unknowns) {
|
||||||
std::ptrdiff_t jmpOff = static_cast<std::ptrdiff_t>(label.offset - unknown);
|
const auto jmpOff = static_cast<std::ptrdiff_t>(label.offset) - static_cast<std::ptrdiff_t>(unknown);
|
||||||
if (jmpOff < std::numeric_limits<std::int8_t>::min() ||
|
if (jmpOff < std::numeric_limits<std::int8_t>::min() ||
|
||||||
jmpOff > std::numeric_limits<std::int8_t>::max()) {
|
jmpOff > std::numeric_limits<std::int8_t>::max()) {
|
||||||
assert(false); // TODO: Further jumps are not implemented
|
assert(false); // TODO: Further jumps are not implemented
|
||||||
}
|
}
|
||||||
mod.bytecode()[unknown - 1] = jmpOff;
|
mod.bytecode()[unknown - 1] = static_cast<std::int8_t>(jmpOff);
|
||||||
}
|
}
|
||||||
label.functions = {};
|
label.functions = {};
|
||||||
label.unknowns = {};
|
label.unknowns = {};
|
||||||
@@ -453,10 +441,11 @@ struct mod_context {
|
|||||||
case token::Ret: {
|
case token::Ret: {
|
||||||
auto it = instructions.find(result->type);
|
auto it = instructions.find(result->type);
|
||||||
assert(it != instructions.end());
|
assert(it != instructions.end());
|
||||||
mod.bytecode().push_back(static_cast<furvm::byte>(it->second.fur));
|
furvm::instruction instr{ it->second };
|
||||||
switch (it->second.arg) {
|
instr.arg.type = furvm::instruction::s_arguments[instr.type];
|
||||||
case instruction::None: break;
|
switch (instr.arg.type) {
|
||||||
case instruction::Type: {
|
case furvm::instruction_argument::None: break;
|
||||||
|
case furvm::instruction_argument::Type: {
|
||||||
result = eat_token(lexer, token::Dolar);
|
result = eat_token(lexer, token::Dolar);
|
||||||
if (!result) return result.error;
|
if (!result) return result.error;
|
||||||
result = eat_token(lexer, token::Identifier);
|
result = eat_token(lexer, token::Identifier);
|
||||||
@@ -464,25 +453,19 @@ struct mod_context {
|
|||||||
auto type = types.find(std::string(result->value.string));
|
auto type = types.find(std::string(result->value.string));
|
||||||
if (type == types.end())
|
if (type == types.end())
|
||||||
return { generator_error::UnknownType, "Unknown type "s + std::string(result->value.string) };
|
return { generator_error::UnknownType, "Unknown type "s + std::string(result->value.string) };
|
||||||
auto id = type->second.id();
|
instr.arg.u32 = type->second.id();
|
||||||
mod.bytecode().push_back((id >> 0) & 0xFF);
|
|
||||||
mod.bytecode().push_back((id >> 8) & 0xFF);
|
|
||||||
mod.bytecode().push_back((id >> 16) & 0xFF);
|
|
||||||
mod.bytecode().push_back((id >> 24) & 0xFF);
|
|
||||||
} break;
|
} break;
|
||||||
case instruction::Constant: {
|
case furvm::instruction_argument::Constant: {
|
||||||
assert(false); // TODO: Unimplemented
|
assert(false); // TODO: Unimplemented
|
||||||
} break;
|
} break;
|
||||||
case instruction::Variable: {
|
case furvm::instruction_argument::Variable: {
|
||||||
result = eat_token(lexer, token::Percent);
|
result = eat_token(lexer, token::Percent);
|
||||||
if (!result) return result.error;
|
if (!result) return result.error;
|
||||||
result = eat_token(lexer, token::Unsigned);
|
result = eat_token(lexer, token::Unsigned);
|
||||||
if (!result) return result.error;
|
if (!result) return result.error;
|
||||||
std::uint16_t var = result->value.uint;
|
instr.arg.u16 = result->value.uint;
|
||||||
mod.bytecode().push_back((var >> 0) & 0xFF);
|
|
||||||
mod.bytecode().push_back((var >> 8) & 0xFF);
|
|
||||||
} break;
|
} break;
|
||||||
case instruction::Function: {
|
case furvm::instruction_argument::Function: {
|
||||||
furvm::function_sig signature;
|
furvm::function_sig signature;
|
||||||
while ((result = next_token(lexer)).error.type == generator_error::Success &&
|
while ((result = next_token(lexer)).error.type == generator_error::Success &&
|
||||||
result->type == token::Dolar) {
|
result->type == token::Dolar) {
|
||||||
@@ -499,11 +482,10 @@ struct mod_context {
|
|||||||
auto func = functions.find(std::make_pair(name, signature));
|
auto func = functions.find(std::make_pair(name, signature));
|
||||||
if (func == functions.end())
|
if (func == functions.end())
|
||||||
return { generator_error::UnknownType, "Unknown type "s + std::string(result->value.string) };
|
return { generator_error::UnknownType, "Unknown type "s + std::string(result->value.string) };
|
||||||
auto id = func->second.id();
|
auto id = func->second.id();
|
||||||
mod.bytecode().push_back((id >> 0) & 0xFF);
|
instr.arg.u16 = id;
|
||||||
mod.bytecode().push_back((id >> 8) & 0xFF);
|
|
||||||
} break;
|
} break;
|
||||||
case instruction::Label: {
|
case furvm::instruction_argument::Offset: {
|
||||||
result = eat_token(lexer, token::Sha256);
|
result = eat_token(lexer, token::Sha256);
|
||||||
if (!result) return result.error;
|
if (!result) return result.error;
|
||||||
result = eat_token(lexer, token::Identifier);
|
result = eat_token(lexer, token::Identifier);
|
||||||
@@ -511,18 +493,28 @@ struct mod_context {
|
|||||||
auto& label = labels[std::string(result->value.string)];
|
auto& label = labels[std::string(result->value.string)];
|
||||||
auto offset = label.offset;
|
auto offset = label.offset;
|
||||||
if (offset == label_context::INVALID) {
|
if (offset == label_context::INVALID) {
|
||||||
label.unknowns.push_back(mod.bytecode().size() + 1);
|
label.unknowns.push_back(mod.bytecode().size() + 2);
|
||||||
mod.bytecode().push_back(0);
|
instr.arg.s8 = 0;
|
||||||
return { generator_error::Success };
|
break;
|
||||||
}
|
}
|
||||||
std::ptrdiff_t jmpOff = static_cast<std::ptrdiff_t>(offset - mod.bytecode().size() - 1);
|
const auto jmpOff =
|
||||||
|
static_cast<std::ptrdiff_t>(offset) - static_cast<std::ptrdiff_t>(mod.bytecode().size()) - 2;
|
||||||
if (jmpOff < std::numeric_limits<std::int8_t>::min() ||
|
if (jmpOff < std::numeric_limits<std::int8_t>::min() ||
|
||||||
jmpOff > std::numeric_limits<std::int8_t>::max()) {
|
jmpOff > std::numeric_limits<std::int8_t>::max()) {
|
||||||
assert(false); // TODO: Further jumps are not implemented
|
assert(false); // TODO: Further jumps are not implemented
|
||||||
}
|
}
|
||||||
mod.bytecode().push_back(jmpOff);
|
instr.arg.s8 = static_cast<std::int8_t>(jmpOff);
|
||||||
} break;
|
} break;
|
||||||
|
case furvm::instruction_argument::S8:
|
||||||
|
case furvm::instruction_argument::U8:
|
||||||
|
case furvm::instruction_argument::S16:
|
||||||
|
case furvm::instruction_argument::U16:
|
||||||
|
case furvm::instruction_argument::S32:
|
||||||
|
case furvm::instruction_argument::U32:
|
||||||
|
case furvm::instruction_argument::Count:
|
||||||
|
default: throw std::runtime_error("unreachable");
|
||||||
}
|
}
|
||||||
|
instr.write(mod.bytecode());
|
||||||
return { generator_error::Success };
|
return { generator_error::Success };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user