Assembler #6

Merged
andre merged 12 commits from assembler into master 2026-05-01 10:12:41 -05:00
8 changed files with 119 additions and 13 deletions
Showing only changes of commit 25c6f6e6dd - Show all commits

View File

@@ -85,6 +85,7 @@ add_library(lib${PROJECT_NAME} SHARED
src/assembler/assembler.cc src/assembler/assembler.cc
src/assembler/assembler.hh src/assembler/assembler.hh
src/assembler/as_exceptions.hh src/assembler/as_exceptions.hh
src/bytecode/bc_exceptions.hh
) )
target_compile_options(lib${PROJECT_NAME} PRIVATE ${warnings}) target_compile_options(lib${PROJECT_NAME} PRIVATE ${warnings})

View File

@@ -1,7 +1,10 @@
#include "assembler.hh" #include "assembler.hh"
#include <unordered_map>
#include "as_exceptions.hh" #include "as_exceptions.hh"
#include "../bytecode/bytecode.hh" #include "../bytecode/bytecode.hh"
#include "../vm/instruction.hh"
using namespace std::string_literals; using namespace std::string_literals;
@@ -49,13 +52,25 @@ ByteArray Assembler::assemble()
} else if (section == Section::Function && t.type == TokenType::Instruction) { } else if (section == Section::Function && t.type == TokenType::Instruction) {
std::string instruction = std::get<std::string>(t.token); std::string instruction = std::get<std::string>(t.token);
int oper = 0; std::optional<int> oper = {};
Token tt = lexer_.ingest(); Token tt = lexer_.ingest();
if (tt.type == TokenType::Integer) { if (tt.type == TokenType::Integer) {
oper = std::get<int>(tt.token); oper = std::get<int>(tt.token);
tt = lexer_.ingest(); tt = lexer_.ingest();
} }
emit_instruction(function_id, instruction, oper);
auto oinst = vm::translate_instruction(instruction, oper);
if (!oinst)
throw AssemblyError("Invalid or misused instruction '" + instruction + "'", tt.line, tt.column);
bp.functions.at(function_id).code.append_byte((uint8_t) *oinst);
switch (vm::instruction_operand_type(*oinst)) {
case vm::OperandType::Int8: bp.functions.at(function_id).code.append_int8((int8_t) *oper); break;
case vm::OperandType::Int16: bp.functions.at(function_id).code.append_int16((int16_t) *oper); break;
case vm::OperandType::Int32: bp.functions.at(function_id).code.append_int32(*oper); break;
case vm::OperandType::NoOperand: default:
}
if (tt.type != TokenType::Enter) if (tt.type != TokenType::Enter)
throw AssemblyError("Expected enter", tt.line, tt.column); throw AssemblyError("Expected enter", tt.line, tt.column);
@@ -70,11 +85,6 @@ ByteArray Assembler::assemble()
return bc::Bytecode::generate(bp); return bc::Bytecode::generate(bp);
} }
void Assembler::emit_instruction(uint32_t function_id, std::string const& inst, int oper)
{
}
TokenValue Assembler::expect_token(TokenType type) TokenValue Assembler::expect_token(TokenType type)
{ {
Token t = lexer_.ingest(); Token t = lexer_.ingest();

View File

@@ -1,6 +1,7 @@
#ifndef TYCHE_ASSEMBLER_HH #ifndef TYCHE_ASSEMBLER_HH
#define TYCHE_ASSEMBLER_HH #define TYCHE_ASSEMBLER_HH
#include <optional>
#include <string> #include <string>
#include "lexer.hh" #include "lexer.hh"
@@ -19,7 +20,6 @@ private:
Lexer lexer_; Lexer lexer_;
TokenValue expect_token(TokenType type); TokenValue expect_token(TokenType type);
void emit_instruction(uint32_t function_id, std::string const& inst, int oper);
}; };
} // tyche } // tyche

View File

@@ -0,0 +1,15 @@
#ifndef TYCHE_BC_EXCEPTIONS_HH
#define TYCHE_BC_EXCEPTIONS_HH
#include <stdexcept>
namespace tyche::bc {
class BytecodeParsingError : public std::runtime_error {
public:
explicit BytecodeParsingError(std::string const& str) : std::runtime_error(str.c_str()) {}
};
}
#endif //TYCHE_BC_EXCEPTIONS_HH

View File

@@ -1,4 +1,6 @@
#include "bytecode.hh" #include "bytecode.hh"
#include "bc_exceptions.hh"
#include "../common/overloaded.hh" #include "../common/overloaded.hh"
namespace tyche::bc { namespace tyche::bc {

View File

@@ -53,11 +53,6 @@ private:
std::vector<uint8_t> data_ {}; std::vector<uint8_t> data_ {};
}; };
class BytecodeParsingError : public std::runtime_error {
public:
explicit BytecodeParsingError(std::string const& str) : std::runtime_error(str.c_str()) {}
};
} }
#endif //TYCHE_BYTEARRAY_HH #endif //TYCHE_BYTEARRAY_HH

View File

@@ -1,7 +1,62 @@
#include "instruction.hh" #include "instruction.hh"
#include <limits>
#include <unordered_map>
namespace tyche::vm { namespace tyche::vm {
const std::unordered_map<std::string, vm::Instruction> instruction_names = {
{ "pushi", vm::Instruction::PushInt8 },
{ "pushc", vm::Instruction::PushConstant8 },
{ "pushz", vm::Instruction::PushZero },
{ "pusht", vm::Instruction::PushTrue },
{ "newa", vm::Instruction::NewArray },
{ "newt", vm::Instruction::NewTable },
{ "pop", vm::Instruction::Pop },
{ "dup", vm::Instruction::Duplicate },
{ "setl", vm::Instruction::SetLocal8 },
{ "getl", vm::Instruction::GetLocal8 },
{ "setg", vm::Instruction::SetGlobal8 },
{ "getl", vm::Instruction::GetGlobal8 },
{ "call8", vm::Instruction::Call8 },
{ "ret", vm::Instruction::Return },
{ "retn", vm::Instruction::ReturnNil },
{ "getkv", vm::Instruction::GetKeyValue },
{ "setkv", vm::Instruction::SetKeyValue },
{ "geta", vm::Instruction::GetArrayItem },
{ "seta", vm::Instruction::SetArrayItem },
{ "appnd", vm::Instruction::Append },
{ "next", vm::Instruction::Next },
{ "smt", vm::Instruction::SetMetatable },
{ "mt", vm::Instruction::GetMetatable },
{ "sum", vm::Instruction::Sum },
{ "sub", vm::Instruction::Subtract },
{ "mul", vm::Instruction::Multiply },
{ "div", vm::Instruction::Divide },
{ "idiv", vm::Instruction::DivideInt },
{ "eq", vm::Instruction::Equals },
{ "neq", vm::Instruction::NotEquals },
{ "lt", vm::Instruction::LessThan },
{ "lte", vm::Instruction::LessThanEq },
{ "gt", vm::Instruction::GreaterThan },
{ "gte", vm::Instruction::GreaterThanEq },
{ "and", vm::Instruction::And },
{ "or", vm::Instruction::Or },
{ "xor", vm::Instruction::Xor },
{ "len", vm::Instruction::Len },
{ "type", vm::Instruction::Type },
{ "cast", vm::Instruction::Cast },
{ "ver", vm::Instruction::Version },
{ "bz", vm::Instruction::BranchIfZero8 },
{ "bnz", vm::Instruction::BranchIfNotZero8 },
{ "jmp", vm::Instruction::Jump8 },
{ "cmpl", vm::Instruction::Compile },
{ "asmbl", vm::Instruction::Assemble },
{ "load", vm::Instruction::Load },
};
std::pair<std::string, size_t> debug_instruction(Instruction inst, int oper) std::pair<std::string, size_t> debug_instruction(Instruction inst, int oper)
{ {
std::string out; std::string out;
@@ -142,4 +197,27 @@ OperandType instruction_operand_type(Instruction inst)
return OperandType::NoOperand; return OperandType::NoOperand;
} }
std::optional<Instruction> translate_instruction(std::string const& txt, std::optional<int> op)
{
auto it = instruction_names.find(txt);
if (it == instruction_names.end())
return {};
Instruction inst = it->second;
OperandType optype = instruction_operand_type(inst);
if (optype == OperandType::NoOperand && op)
return {};
if (optype != OperandType::NoOperand && !op)
return {};
if (optype == OperandType::NoOperand)
return inst;
if (op >= std::numeric_limits<int8_t>::min() && op <= std::numeric_limits<int8_t>::max())
return inst;
if (op >= std::numeric_limits<int16_t>::min() && op <= std::numeric_limits<int16_t>::max())
return (Instruction) ((uint8_t) inst + OPCODE_NEXT_SIZE);
return (Instruction) ((uint8_t) inst + (OPCODE_NEXT_SIZE * 2));
}
} }

View File

@@ -2,6 +2,7 @@
#define TYCHE_INSTRUCTION_HH #define TYCHE_INSTRUCTION_HH
#include <cstdint> #include <cstdint>
#include <optional>
#include <string> #include <string>
#include <utility> #include <utility>
@@ -9,6 +10,8 @@
namespace tyche::vm { namespace tyche::vm {
constexpr uint8_t OPCODE_NEXT_SIZE = 0x20;
enum class Instruction : uint8_t { enum class Instruction : uint8_t {
// stack operations // stack operations
@@ -101,6 +104,8 @@ std::pair<std::string, size_t> debug_instruction(bc::Bytecode const& bt, uint32_
enum class OperandType { NoOperand, Int8, Int16, Int32 }; enum class OperandType { NoOperand, Int8, Int16, Int32 };
OperandType instruction_operand_type(Instruction instruction); OperandType instruction_operand_type(Instruction instruction);
std::optional<Instruction> translate_instruction(std::string const& txt, std::optional<int> op);
} }
#endif //TYCHE_INSTRUCTION_HH #endif //TYCHE_INSTRUCTION_HH