diff --git a/include/utils.h b/include/utils.h index d0139e7..af2cc39 100644 --- a/include/utils.h +++ b/include/utils.h @@ -105,7 +105,6 @@ VariableType::Type deduceType(Program &program, Segment &segment, AbstractSyntax Instruction getInstructionWithType(GenericInstruction instruction, VariableType::Type type); Instruction emitLoad(VariableType::Type, const Token &token); void typeCast(std::vector &instructions, VariableType::Type from, VariableType::Type to); -size_t sizeOfType(VariableType::Type type); VariableType::Type biggestType(VariableType::Type first, VariableType::Type second); VariableType::Type getInstructionType(const Program &program, const Instruction &instruction); diff --git a/include/vm.h b/include/vm.h index 939cf86..215517c 100644 --- a/include/vm.h +++ b/include/vm.h @@ -122,10 +122,9 @@ struct Variable { std::string name; VariableType *type{}; size_t index{}; - size_t size{}; Variable() = default; - Variable(std::string name, VariableType *type, size_t index, size_t size) - : name(std::move(name)), type(type), index(index), size(size){}; + Variable(std::string name, VariableType *type, size_t index) + : name(std::move(name)), type(type), index(index){}; }; struct Segment { @@ -148,14 +147,14 @@ struct Program { }; struct StackFrame { - uint32_t *locals{}; + uint64_t *locals{}; size_t localsSize{}; size_t segmentIndex{}; size_t currentInstruction{}; }; class VM { - uint32_t *stack; + uint64_t *stack; size_t stackCapacity; std::vector callStack; @@ -164,20 +163,13 @@ class VM { ~VM(); void newStackFrame(const Segment &segment); void popStackFrame(); - [[nodiscard]] uint32_t getLocal(size_t index) const; - void setLocal(size_t index, uint32_t value); - [[nodiscard]] uint32_t getGlobal(size_t index) const; - void setGlobal(size_t index, uint32_t value); - [[nodiscard]] uint64_t getDoubleLocal(size_t index) const; - void setDoubleLocal(size_t index, uint64_t value); - [[nodiscard]] uint64_t getDoubleGlobal(size_t index) const; - void setDoubleGlobal(size_t index, uint64_t value); - void pushStack(uint32_t value); - void pushDoubleStack(uint64_t value); - uint32_t popStack(); - uint64_t popDoubleStack(); - [[nodiscard]] uint32_t topStack() const; - [[nodiscard]] uint64_t topDoubleStack() const; + [[nodiscard]] uint64_t getLocal(size_t index) const; + void setLocal(size_t index, uint64_t value); + [[nodiscard]] uint64_t getGlobal(size_t index) const; + void setGlobal(size_t index, uint64_t value); + void pushStack(uint64_t value); + uint64_t popStack(); + [[nodiscard]] uint64_t topStack() const; void run(const Program &program); size_t stackSize{}; diff --git a/main.cpp b/main.cpp index c8977db..f8fac6c 100644 --- a/main.cpp +++ b/main.cpp @@ -16,10 +16,10 @@ void printTopStack(const VM &vm, const Program &program) { std::cout << (int32_t) vm.topStack() << std::endl; break; case VariableType::I64: { - std::cout << vm.topDoubleStack() << std::endl; + std::cout << vm.topStack() << std::endl; } break; case VariableType::Object: { - auto obj = std::bit_cast(vm.topDoubleStack()); + auto obj = std::bit_cast(vm.topStack()); if (obj->objType == Object::Type::String) { std::cout << static_cast(obj)->chars << std::endl; } diff --git a/src/ast.cpp b/src/ast.cpp index bf9d7ba..9591ea8 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -168,16 +168,14 @@ void Declaration::compile(Program &program, Segment &segment) const { segment.declare_function(identifier.token.value, new FunctionType(returnType, arguments), program.segments.size()); - size_t index = 0; - for (auto argument: functionDeclaration->arguments) { + for (size_t index = 0; index < functionDeclaration->arguments.size(); index++) { + auto argument = functionDeclaration->arguments[index]; newSegment.locals[argument->identifier.token.value] = Variable( argument->identifier.token.value, new VariableType(deduceType(program, segment, argument)), - index, - sizeOfType(varTypeConvert(functionDeclaration->returnType))); - newSegment.locals_capacity += sizeOfType(deduceType(program, segment, argument)); - index += sizeOfType(varTypeConvert(argument->type.value())); + index); } + newSegment.locals_capacity = newSegment.locals.size(); value.value()->compile(program, newSegment); program.segments.push_back(newSegment); } break; diff --git a/src/utils.cpp b/src/utils.cpp index 4921bf9..5bc06ff 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -178,19 +178,6 @@ void typeCast(std::vector &instructions, VariableType::Type from, V } } -size_t sizeOfType(VariableType::Type type) { - switch (type) { - case VariableType::Bool: - case VariableType::I32: - return 1; - case VariableType::Object: - case VariableType::I64: - return 2; - default: - throw std::runtime_error("Invalid type"); - } -} - VariableType::Type getInstructionType(const Program &program, const Instruction &instruction) { switch (instruction.type) { case Instruction::InstructionType::EqualI32: diff --git a/src/vm.cpp b/src/vm.cpp index efdd0de..0bea2f3 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -1,5 +1,4 @@ #include "vm.h" -#include "utils.h" #include #include #include @@ -25,10 +24,9 @@ Variable Program::find_function(const Segment &segment, const std::string &ident } void Segment::declare_variable(const std::string &name, VariableType *varType) { - locals[name] = Variable(name, varType, locals_capacity, 0); + locals[name] = Variable(name, varType, locals_capacity); if (varType->type != VariableType::Type::Function) { - locals[name].size = sizeOfType(varType->type); - locals_capacity += sizeOfType(varType->type); + locals_capacity++; } } size_t Segment::find_local(const std::string &identifier) { @@ -38,14 +36,14 @@ size_t Segment::find_local(const std::string &identifier) { return it->second.index; } void Segment::declare_function(const std::string &name, VariableType *funcType, size_t index) { - auto function = Variable(name, funcType, index, 0); + auto function = Variable(name, funcType, index); functions[name] = function; locals[name] = function; } VM::VM() { stackCapacity = 1024; - stack = (uint32_t *) malloc(stackCapacity * sizeof(uint32_t)); + stack = (uint64_t *) malloc(stackCapacity * sizeof(uint64_t)); if (stack == nullptr) throw std::runtime_error("Memory allocation failure!"); callStack.push_back(StackFrame{}); @@ -56,7 +54,7 @@ VM::~VM() { free(stackFrame.locals); } inline void VM::newStackFrame(const Segment &segment) { - auto locals = (uint32_t *) malloc(segment.locals_capacity * sizeof(uint32_t)); + auto locals = (uint64_t *) malloc(segment.locals_capacity * sizeof(uint64_t)); if (locals == nullptr) { throw std::runtime_error("Memory allocation failure!"); } @@ -74,40 +72,22 @@ inline void VM::popStackFrame() { free(callStack.back().locals); callStack.pop_back(); } -inline uint32_t VM::getLocal(const size_t index) const { +inline uint64_t VM::getLocal(const size_t index) const { return callStack.back().locals[index]; } -inline void VM::setLocal(const size_t index, uint32_t value) { +inline void VM::setLocal(const size_t index, uint64_t value) { callStack.back().locals[index] = value; } -inline uint32_t VM::getGlobal(size_t index) const { +inline uint64_t VM::getGlobal(size_t index) const { return callStack[0].locals[index]; } -inline void VM::setGlobal(const size_t index, uint32_t value) { - callStack.front().locals[index] = value; +inline void VM::setGlobal(const size_t index, uint64_t value) { + callStack[0].locals[index] = value; } -inline uint64_t VM::getDoubleLocal(const size_t index) const { - auto low = getLocal(index + 1); - auto high = static_cast(getLocal(index)); - return (high << 32) | (low & 0xFFFFFFFF); -} -inline void VM::setDoubleLocal(const size_t index, uint64_t value) { - setLocal(index, value >> 32); - setLocal(index + 1, value & 0xFFFFFFFF); -} -inline uint64_t VM::getDoubleGlobal(size_t index) const { - auto low = getGlobal(index); - auto high = (uint64_t) getGlobal(index + 1); - return high << 32 | (low & 0xFFFFFFFF); -} -inline void VM::setDoubleGlobal(const size_t index, uint64_t value) { - setGlobal(index, value >> 32); - setGlobal(index + 1, value & 0xFFFFFFFF); -} -inline void VM::pushStack(uint32_t value) { +inline void VM::pushStack(uint64_t value) { if (stackSize + 1 > stackCapacity) { stackCapacity *= 2; - auto newStack = (uint32_t *) realloc(stack, stackCapacity * sizeof(uint32_t)); + auto newStack = (uint64_t *) realloc(stack, stackCapacity * sizeof(uint64_t)); if (newStack == nullptr) { throw std::runtime_error("Memory allocation failure!"); } @@ -115,39 +95,17 @@ inline void VM::pushStack(uint32_t value) { } stack[stackSize++] = value; } -inline void VM::pushDoubleStack(uint64_t value) { - if (stackSize + 2 > stackCapacity) { - stackCapacity *= 2; - auto newStack = realloc(stack, stackCapacity * sizeof(uint32_t)); - if (newStack == nullptr) { - throw std::runtime_error("Memory allocation failure!"); - } - stack = (uint32_t *) newStack; - } - pushStack(value >> 32); - pushStack(value & 0xFFFFFFFF); -} -inline uint32_t VM::popStack() { +inline uint64_t VM::popStack() { return stack[--stackSize]; } -inline uint64_t VM::popDoubleStack() { - auto low = popStack(); - auto high = static_cast(popStack()); - return (high << 32) | (low & 0xFFFFFFFF); -} -uint32_t VM::topStack() const { +uint64_t VM::topStack() const { return stack[stackSize - 1]; } -uint64_t VM::topDoubleStack() const { - auto low = stack[stackSize - 1]; - auto high = static_cast(stack[stackSize - 2]); - return (high << 32) | (low & 0xFFFFFFFF); -} void VM::run(const Program &program) { if (callStack.front().localsSize != program.segments.front().locals_capacity) { callStack.front().localsSize = program.segments.front().locals_capacity; - auto *newPtr = (uint32_t *) realloc(callStack.front().locals, callStack.front().localsSize * sizeof(uint32_t)); + auto *newPtr = (uint64_t *) realloc(callStack.front().locals, callStack.front().localsSize * sizeof(uint64_t)); if (newPtr == nullptr) { throw std::runtime_error("Memory allocation failure!"); } else { @@ -244,38 +202,38 @@ void VM::run(const Program &program) { callStack.back().currentInstruction = instruction.params.index; continue; case Instruction::AddI64: { - auto a = popDoubleStack(); - auto b = popDoubleStack(); - pushDoubleStack(a + b); + auto a = popStack(); + auto b = popStack(); + pushStack(a + b); } break; case Instruction::SubI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); - pushDoubleStack(a - b); + auto b = popStack(); + auto a = popStack(); + pushStack(a - b); } break; case Instruction::MulI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); - pushDoubleStack(a * b); + auto b = popStack(); + auto a = popStack(); + pushStack(a * b); } break; case Instruction::DivI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); - pushDoubleStack(a / b); + auto b = popStack(); + auto a = popStack(); + pushStack(a / b); } break; case Instruction::ModI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); - pushDoubleStack(a % b); + auto b = popStack(); + auto a = popStack(); + pushStack(a % b); } break; case Instruction::GreaterI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); + auto b = popStack(); + auto a = popStack(); pushStack(a > b); } break; case Instruction::LessI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); + auto b = popStack(); + auto a = popStack(); pushStack(a < b); } break; case Instruction::GreaterEqualI32: { @@ -284,8 +242,8 @@ void VM::run(const Program &program) { pushStack(a >= b); } break; case Instruction::GreaterEqualI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); + auto b = popStack(); + auto a = popStack(); pushStack(a >= b); } break; case Instruction::LessEqualI32: { @@ -294,8 +252,8 @@ void VM::run(const Program &program) { pushStack(a <= b); } break; case Instruction::LessEqualI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); + auto b = popStack(); + auto a = popStack(); pushStack(a <= b); } break; case Instruction::EqualI32: { @@ -304,8 +262,8 @@ void VM::run(const Program &program) { pushStack(a == b); } break; case Instruction::EqualI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); + auto b = popStack(); + auto a = popStack(); pushStack(a == b); } break; case Instruction::NotEqualI32: { @@ -314,47 +272,47 @@ void VM::run(const Program &program) { pushStack(a != b); } break; case Instruction::NotEqualI64: { - auto b = popDoubleStack(); - auto a = popDoubleStack(); + auto b = popStack(); + auto a = popStack(); pushStack(a != b); } break; case Instruction::IncrementI64: { - auto val = popDoubleStack(); - pushDoubleStack(val + 1); + auto val = popStack(); + pushStack(val + 1); } break; case Instruction::DecrementI64: { - auto val = popDoubleStack(); - pushDoubleStack(val - 1); + auto val = popStack(); + pushStack(val - 1); } break; case Instruction::StoreGlobalObject: case Instruction::StoreGlobalI64: { - auto val = popDoubleStack(); - setDoubleGlobal(instruction.params.index, val); + auto val = popStack(); + setGlobal(instruction.params.index, val); } break; case Instruction::StoreLocalObject: case Instruction::StoreLocalI64: { - auto val = popDoubleStack(); - setDoubleLocal(instruction.params.index, val); + auto val = popStack(); + setLocal(instruction.params.index, val); } break; case Instruction::LoadI64: { - pushDoubleStack(instruction.params.i64); + pushStack(instruction.params.i64); } break; case Instruction::LoadGlobalObject: case Instruction::LoadGlobalI64: { - auto val = getDoubleGlobal(instruction.params.index); - pushDoubleStack(val); + auto val = getGlobal(instruction.params.index); + pushStack(val); } break; case Instruction::LoadLocalObject: case Instruction::LoadLocalI64: { - auto val = getDoubleLocal(instruction.params.index); - pushDoubleStack(val); + auto val = getLocal(instruction.params.index); + pushStack(val); } break; case Instruction::ConvertI32toI64: { auto val = popStack(); - pushDoubleStack(val); + pushStack(val); } break; case Instruction::LoadObject: { - pushDoubleStack(std::bit_cast(instruction.params.ptr)); + pushStack(std::bit_cast(instruction.params.ptr)); } break; } callStack.back().currentInstruction++; diff --git a/tests/vm_tests.cpp b/tests/vm_tests.cpp index fe29a76..57efed5 100644 --- a/tests/vm_tests.cpp +++ b/tests/vm_tests.cpp @@ -92,7 +92,7 @@ TEST(VM, SimpleI64VariableDeclaration) { VM vm; auto program = compile(input); vm.run(program); - ASSERT_EQ(vm.topDoubleStack(), static_cast(42)); + ASSERT_EQ(vm.topStack(), static_cast(42)); } TEST(VM, BinaryExpressionWithMultipleTypes) { @@ -102,7 +102,7 @@ TEST(VM, BinaryExpressionWithMultipleTypes) { VM vm; auto program = compile(input); vm.run(program); - ASSERT_EQ(vm.topDoubleStack(), 84); + ASSERT_EQ(vm.topStack(), 84); } TEST(VM, SimpleVariableAssignment) { @@ -130,7 +130,7 @@ TEST(VM, RightIncrementUnaryOperatorI64) { VM vm; auto program = compile(input); vm.run(program); - ASSERT_EQ(vm.topDoubleStack(), 43); + ASSERT_EQ(vm.topStack(), 43); } TEST(VM, RightDecrementUnaryOperator) { @@ -150,7 +150,7 @@ TEST(VM, RightDecrementUnaryOperatorI64) { VM vm; auto program = compile(input); vm.run(program); - ASSERT_EQ(vm.topDoubleStack(), 41); + ASSERT_EQ(vm.topStack(), 41); } TEST(VM, LeftIncrementUnaryOperator) { @@ -208,7 +208,7 @@ TEST(VM, FunctionWithDifferentReturnType) { VM vm; auto program = compile(input); vm.run(program); - ASSERT_EQ(vm.topDoubleStack(), 30); + ASSERT_EQ(vm.topStack(), 30); } TEST(VM, RecursiveFunction) { @@ -248,6 +248,6 @@ TEST(VM, DeclareStrings) { VM vm; auto program = compile(input); vm.run(program); - auto obj = reinterpret_cast(vm.topDoubleStack()); + auto obj = reinterpret_cast(vm.topStack()); ASSERT_EQ(*obj, "Hello World"); }