Skip to content

Commit

Permalink
VM: add support for I64 type (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrunix00 committed Jul 7, 2024
1 parent 2db8caa commit 8451ede
Show file tree
Hide file tree
Showing 6 changed files with 359 additions and 228 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(SPL)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_compile_options(-O3)
add_compile_options(-O2)

file(GLOB_RECURSE TEST_SOURCES tests/*.cpp)
file(GLOB_RECURSE SOURCES src/*.cpp)
Expand Down
83 changes: 83 additions & 0 deletions include/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#pragma once

#include "vm.h"

#define GENERATE_EMIT_FUNCTION(OPERATION) \
static inline void emit##OPERATION(Program &program, Segment &segment, const std::string &identifier) { \
size_t id; \
bool isLocal; \
Instruction instruction; \
Variable::Type type; \
if (segment.find_local(identifier) != -1) { \
isLocal = true; \
id = segment.find_local(identifier); \
type = segment.locals[identifier].type; \
} else if (program.find_global(identifier) != -1) { \
isLocal = false; \
id = program.find_global(identifier); \
type = program.segments[0].locals[identifier].type; \
} else { \
throw std::runtime_error("[Node::compile] Identifier not found: " + identifier); \
} \
switch (type) { \
case Variable::Type::I32: \
instruction.type = isLocal ? Instruction::InstructionType::OPERATION##LocalI32 \
: Instruction::InstructionType::OPERATION##GlobalI32; \
instruction.params.index = id; \
break; \
case Variable::Type::I64: \
instruction.type = isLocal ? Instruction::InstructionType::OPERATION##LocalI64 \
: Instruction::InstructionType::OPERATION##GlobalI64; \
instruction.params.index = id; \
break; \
default: \
throw std::runtime_error("[Node::compile] Invalid variable type!"); \
} \
segment.instructions.push_back(instruction); \
}
GENERATE_EMIT_FUNCTION(Load)
GENERATE_EMIT_FUNCTION(Store)

static inline Variable::Type varTypeConvert(AbstractSyntaxTree *ast) {
if (ast->nodeType != AbstractSyntaxTree::Type::Node)
throw std::runtime_error("[Declaration::compile] Invalid type: " + ast->typeStr);
auto token = dynamic_cast<Node *>(ast)->token;
switch (token.type) {
case I32:
return Variable::Type::I32;
case I64:
return Variable::Type::I64;
default:
throw std::runtime_error("[Declaration::compile] Invalid type: " + token.value);
}
}

#define DECLARE_NUMBER_VAR(TYPE, PARAM) \
case TYPE: { \
segment.instructions.push_back({.type = Instruction::InstructionType::Load##TYPE, \
.params = {.PARAM = std::stoi(initNode->token.value)}}); \
segment.instructions.push_back({ \
.type = segment.id == 0 \
? Instruction::InstructionType::StoreGlobal##TYPE \
: Instruction::InstructionType::StoreLocal##TYPE, \
.params = {.index = segment.locals.size()}, \
}); \
segment.declare_variable(identifier.token.value, Variable::Type::TYPE); \
} break;

#define DECLARE_OTHER_VAR(TYPE) \
case TYPE: { \
initNode->compile(program, segment); \
segment.instructions.push_back({ \
.type = segment.id == 0 \
? Instruction::InstructionType::StoreGlobal##TYPE \
: Instruction::InstructionType::StoreLocal##TYPE, \
.params = {.index = segment.locals.size()}, \
}); \
segment.declare_variable(identifier.token.value, Variable::Type::TYPE); \
} break;

#define VAR_CASE(OP, TYPE) \
case Variable::Type::TYPE: \
segment.instructions.push_back(Instruction{.type = Instruction::InstructionType::OP##TYPE}); \
break;
42 changes: 26 additions & 16 deletions include/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,41 @@ struct Instruction {
enum InstructionType : uint8_t {
Invalid = 0,
AddI32,
AddI32_RI,
AddI32_GI,
AddI64,
SubI32,
SubI32_RI,
SubI32_GI,
SubI64,
MulI32,
MulI32_RI,
MulI32_GI,
MulI64,
DivI32,
DivI32_RI,
DivI32_GI,
DivI64,
ModI32,
ModI32_RI,
ModI32_GI,
LoadI32,
ModI64,
GreaterI32,
GreaterI32_RI,
GreaterI32_GI,
GreaterI64,
LessI32,
LessI32_RI,
LessI32_GI,
LessI64,
GreaterEqualI32,
GreaterEqualI64,
LessEqualI32,
LessEqualI64,
EqualI32,
EqualI64,
NotEqualI32,
NotEqualI64,
IncrementI32,
IncrementI64,
DecrementI32,
DecrementI64,
StoreGlobalI32,
StoreGlobalI64,
StoreLocalI32,
StoreLocalI64,
LoadI32,
LoadI64,
LoadGlobalI32,
LoadGlobalI64,
LoadLocalI32,
LoadLocalI64,
Return,
Call,
JumpIfFalse,
Expand All @@ -50,10 +54,15 @@ struct Instruction {
void *ptr;
size_t index;
int32_t i32;
int64_t i64;
struct {
size_t index;
int32_t i32;
} ri;
} ri32;
struct {
size_t index;
int64_t i64;
} ri64;
} params{};
};

Expand All @@ -62,6 +71,7 @@ struct Variable {
enum class Type {
Invalid = 0,
I32,
I64,
Function
} type;
size_t index;
Expand Down
Loading

0 comments on commit 8451ede

Please sign in to comment.