diff options
39 files changed, 128 insertions, 74 deletions
@@ -97,9 +97,13 @@ TESTSRC=\ SRC=$(PROGSRC) mcc.cpp -all: test-$(PROJECTNAME) mcc - ./test-$(PROJECTNAME) # --gtest_filter='CppTest.compile_1' +all: mcc unittest systemtest +# Tests on C++ level +unittest: test-$(PROJECTNAME) + ./test-$(PROJECTNAME) --gtest_filter='CppTest.compile_2_times' + +# Testing mcc executable and compiled elf programs systemtest: ./mcc systemtest/mcc-execute.tests/test-return-1.cpp ./mcc systemtest/mcc-execute.tests/test-addition.cpp @@ -142,6 +146,6 @@ zip: clean zip -r ../$(PROJECTNAME).zip * ls -l ../$(PROJECTNAME).zip -.PHONY: clean all zip dep systemtest +.PHONY: clean all zip dep systemtest unittest -include $(wildcard $(SRC:.cpp=.d)) diff --git a/asm/assembler.cpp b/asm/assembler.cpp index 5d8a986..b555125 100644 --- a/asm/assembler.cpp +++ b/asm/assembler.cpp @@ -22,7 +22,7 @@ bool registerOp(const std::string& mnemonic, FactoryFunction f) return true; } -std::string mangleName(const std::string& s, Asm::Args& args) +std::string mangleName(const std::string& s, const Asm::Args& args) { std::string result {s}; @@ -33,7 +33,7 @@ std::string mangleName(const std::string& s, Asm::Args& args) return result; } -std::shared_ptr<Op> makeOp(const std::string& mnemonic, Asm::Args& args) +std::shared_ptr<Op> makeOp(const std::string& mnemonic, const Asm::Args& args) { std::string mangled{mangleName(mnemonic, args)}; diff --git a/asm/assembler.h b/asm/assembler.h index b459b85..aa886b5 100644 --- a/asm/assembler.h +++ b/asm/assembler.h @@ -107,14 +107,14 @@ public: } // namespace Asm -using FactoryFunction = std::function<std::shared_ptr<Op>(Asm::Args&)>; +using FactoryFunction = std::function<std::shared_ptr<Op>(const Asm::Args&)>; // mnemonic: mnemonic including argument types bool registerOp(const std::string& mnemonic, FactoryFunction f); // Create Op from a registered mnemonic // mnemonic: just the mnemonic name -std::shared_ptr<Op> makeOp(const std::string& mnemonic, Asm::Args& args); +std::shared_ptr<Op> makeOp(const std::string& mnemonic, const Asm::Args& args); // overload for empty list of arguments std::shared_ptr<Op> makeOp(const std::string& mnemonic); @@ -137,5 +137,5 @@ std::string mangleName(const std::string& s) return mangleName<Targs...>(s + "_" + typeid(T).name()); } -std::string mangleName(const std::string& s, Asm::Args& args); +std::string mangleName(const std::string& s, const Asm::Args& args); diff --git a/asm/intel64/add.cpp b/asm/intel64/add.cpp index 4438895..236436c 100644 --- a/asm/intel64/add.cpp +++ b/asm/intel64/add.cpp @@ -7,7 +7,7 @@ using namespace std::string_literals; -Op_add::Op_add(Asm::Args& args) +Op_add::Op_add(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register32) && std::any_cast<Asm::Args::Register32>(args[0]).name() == "eax" && @@ -31,10 +31,10 @@ Op_add::Op_add(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate32>("add"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate32>("add"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_add>(args); }) && - registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate32>("add"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate32>("add"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_add>(args); }) }; diff --git a/asm/intel64/add.h b/asm/intel64/add.h index 1d55317..0c1b8ce 100644 --- a/asm/intel64/add.h +++ b/asm/intel64/add.h @@ -7,7 +7,7 @@ class Op_add: public Op { public: - Op_add(Asm::Args& args); + Op_add(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/dec.cpp b/asm/intel64/dec.cpp index dab603a..5ae61c4 100644 --- a/asm/intel64/dec.cpp +++ b/asm/intel64/dec.cpp @@ -9,7 +9,7 @@ using namespace std::string_literals; -Op_dec::Op_dec(Asm::Args& args) +Op_dec::Op_dec(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register8)) { // dec reg8 machine_code = std::vector<uint8_t>{ 0xFE } + @@ -28,13 +28,13 @@ Op_dec::Op_dec(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register8>("dec"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register8>("dec"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_dec>(args); }) && - registerOp(mangleName<Asm::Args::Register32>("dec"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register32>("dec"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_dec>(args); }) && - registerOp(mangleName<Asm::Args::Register64>("dec"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64>("dec"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_dec>(args); }) }; diff --git a/asm/intel64/dec.h b/asm/intel64/dec.h index 293ba8d..1b0eaf7 100644 --- a/asm/intel64/dec.h +++ b/asm/intel64/dec.h @@ -7,7 +7,7 @@ class Op_dec: public Op { public: - Op_dec(Asm::Args& args); + Op_dec(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/div.cpp b/asm/intel64/div.cpp index 5ed9988..9ca24e9 100644 --- a/asm/intel64/div.cpp +++ b/asm/intel64/div.cpp @@ -9,7 +9,7 @@ using namespace std::string_literals; -Op_div::Op_div(Asm::Args& args) +Op_div::Op_div(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register8)) { // div reg8 (accu is al (remainder=ah) <- ah / reg8) machine_code = std::vector<uint8_t>{ 0xF6 } + @@ -28,13 +28,13 @@ Op_div::Op_div(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register8>("div"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register8>("div"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_div>(args); }) && - registerOp(mangleName<Asm::Args::Register32>("div"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register32>("div"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_div>(args); }) && - registerOp(mangleName<Asm::Args::Register64>("div"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64>("div"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_div>(args); }) }; diff --git a/asm/intel64/div.h b/asm/intel64/div.h index 9605f3e..89614fc 100644 --- a/asm/intel64/div.h +++ b/asm/intel64/div.h @@ -7,7 +7,7 @@ class Op_div: public Op { public: - Op_div(Asm::Args& args); + Op_div(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/encode.cpp b/asm/intel64/encode.cpp index b26bf9c..123dff2 100644 --- a/asm/intel64/encode.cpp +++ b/asm/intel64/encode.cpp @@ -96,8 +96,16 @@ void Asm::toMachineCode(const FlowGraph::Graph& graph, Segment& segment) else throw std::runtime_error("ICE: Asm: Unsupported binary operation type: "s + std::to_string(static_cast<int>(op.type()))); + } else if (typeid(node_deref) == typeid(FlowGraph::CreateScopeOp)) { + //FlowGraph::CreateScopeOp& op {dynamic_cast<FlowGraph::CreateScopeOp&>(*node)}; + segment.push_back(makeOp("push", Asm::Args{{Asm::Args::Register64("rbp")}})); + segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Register64("rbp"), Asm::Args::Register64("rsp")}})); + + } else if (typeid(node_deref) == typeid(FlowGraph::DestroyScopeOp)) { + //FlowGraph::DestroyScopeOp& op {dynamic_cast<FlowGraph::DestroyScopeOp&>(*node)}; + segment.push_back(makeOp("pop", Asm::Args{{Asm::Args::Register64("rbp")}})); } else { - throw std::runtime_error("ICE: Encoding: Unsupported node"); + throw std::runtime_error("ICE: Encoding: Unsupported node: "s + demangle(typeid(node_deref))); } } else { throw std::runtime_error("ICE: encode: flowgraph node is null"); diff --git a/asm/intel64/idiv.cpp b/asm/intel64/idiv.cpp index 3ee17a3..debeeb4 100644 --- a/asm/intel64/idiv.cpp +++ b/asm/intel64/idiv.cpp @@ -9,7 +9,7 @@ using namespace std::string_literals; -Op_idiv::Op_idiv(Asm::Args& args) +Op_idiv::Op_idiv(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register8)) { // idiv reg8 (accu is al (remainder=ah) <- ah / reg8) machine_code = std::vector<uint8_t>{ 0xF6 } + @@ -28,10 +28,10 @@ Op_idiv::Op_idiv(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register8>("idiv"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register8>("idiv"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_idiv>(args); }) && - registerOp(mangleName<Asm::Args::Register64>("idiv"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64>("idiv"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_idiv>(args); }) }; diff --git a/asm/intel64/idiv.h b/asm/intel64/idiv.h index a6ef411..8b93043 100644 --- a/asm/intel64/idiv.h +++ b/asm/intel64/idiv.h @@ -7,7 +7,7 @@ class Op_idiv: public Op { public: - Op_idiv(Asm::Args& args); + Op_idiv(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/imul.cpp b/asm/intel64/imul.cpp index 4df8577..0ffca30 100644 --- a/asm/intel64/imul.cpp +++ b/asm/intel64/imul.cpp @@ -9,7 +9,7 @@ using namespace std::string_literals; -Op_imul::Op_imul(Asm::Args& args) +Op_imul::Op_imul(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register8)) { // imul reg8 (accu is ax <- al) machine_code = std::vector<uint8_t>{ 0xF6 } + @@ -28,13 +28,13 @@ Op_imul::Op_imul(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register8>("imul"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register8>("imul"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_imul>(args); }) && - registerOp(mangleName<Asm::Args::Register32>("imul"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register32>("imul"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_imul>(args); }) && - registerOp(mangleName<Asm::Args::Register64>("imul"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64>("imul"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_imul>(args); }) }; diff --git a/asm/intel64/imul.h b/asm/intel64/imul.h index 387d87f..becf21d 100644 --- a/asm/intel64/imul.h +++ b/asm/intel64/imul.h @@ -7,7 +7,7 @@ class Op_imul: public Op { public: - Op_imul(Asm::Args& args); + Op_imul(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/inc.cpp b/asm/intel64/inc.cpp index 3df9104..cc7f1ff 100644 --- a/asm/intel64/inc.cpp +++ b/asm/intel64/inc.cpp @@ -9,7 +9,7 @@ using namespace std::string_literals; -Op_inc::Op_inc(Asm::Args& args) +Op_inc::Op_inc(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register8)) { // inc reg8 machine_code = std::vector<uint8_t>{ 0xFE } + @@ -28,13 +28,13 @@ Op_inc::Op_inc(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register8>("inc"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register8>("inc"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_inc>(args); }) && - registerOp(mangleName<Asm::Args::Register32>("inc"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register32>("inc"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_inc>(args); }) && - registerOp(mangleName<Asm::Args::Register64>("inc"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64>("inc"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_inc>(args); }) }; diff --git a/asm/intel64/inc.h b/asm/intel64/inc.h index 0887392..6c96ae2 100644 --- a/asm/intel64/inc.h +++ b/asm/intel64/inc.h @@ -7,7 +7,7 @@ class Op_inc: public Op { public: - Op_inc(Asm::Args& args); + Op_inc(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/int.cpp b/asm/intel64/int.cpp index de6c73b..dbc6ae7 100644 --- a/asm/intel64/int.cpp +++ b/asm/intel64/int.cpp @@ -2,7 +2,7 @@ #include <asm/assembler.h> -Op_int::Op_int(Asm::Args& args) +Op_int::Op_int(const Asm::Args& args) { // At this point, the registration already ensured the number and types of args @@ -21,7 +21,7 @@ Op_int::Op_int(Asm::Args& args) namespace { -bool registered { registerOp(mangleName<Asm::Args::Immediate8>("int"), [](Asm::Args& args) -> std::shared_ptr<Op>{ +bool registered { registerOp(mangleName<Asm::Args::Immediate8>("int"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_int>(args); }) }; diff --git a/asm/intel64/int.h b/asm/intel64/int.h index aee4962..b27f4a3 100644 --- a/asm/intel64/int.h +++ b/asm/intel64/int.h @@ -7,7 +7,7 @@ class Op_int: public Op { public: - Op_int(Asm::Args& args); + Op_int(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/jmp.cpp b/asm/intel64/jmp.cpp index 8542127..2fc4a13 100644 --- a/asm/intel64/jmp.cpp +++ b/asm/intel64/jmp.cpp @@ -61,7 +61,7 @@ namespace { bool registerOps() { bool result{true}; for (const auto& jumpOp: jumpOps) { - result &= registerOp(mangleName<Asm::Args::Label>(jumpOp.name), [&](Asm::Args& args) -> std::shared_ptr<Op>{ + result &= registerOp(mangleName<Asm::Args::Label>(jumpOp.name), [&](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_jmp>(jumpOp.name, args, jumpOp.jmp8, jumpOp.jmp32); }); } @@ -73,7 +73,7 @@ namespace { }; } -Op_jmp::Op_jmp(const std::string& name, Asm::Args& args, const OP_T& jmp8, const OP_T& jmp32) +Op_jmp::Op_jmp(const std::string& name, const Asm::Args& args, const OP_T& jmp8, const OP_T& jmp32) { label = std::any_cast<Asm::Args::Label>(args[0]).name(); diff --git a/asm/intel64/jmp.h b/asm/intel64/jmp.h index a7c7511..c96f4e2 100644 --- a/asm/intel64/jmp.h +++ b/asm/intel64/jmp.h @@ -10,7 +10,7 @@ class Op_jmp: public Op, public AddressFeature { public: - Op_jmp(const std::string& name, Asm::Args& args, const OP_T& jmp8, const OP_T& jmp32); + Op_jmp(const std::string& name, const Asm::Args& args, const OP_T& jmp8, const OP_T& jmp32); std::vector<uint8_t> getCode() override { diff --git a/asm/intel64/mov.cpp b/asm/intel64/mov.cpp index 5741170..5b224c1 100644 --- a/asm/intel64/mov.cpp +++ b/asm/intel64/mov.cpp @@ -9,16 +9,29 @@ using namespace std::string_literals; -Op_mov::Op_mov(Asm::Args& args) +Op_mov::Op_mov(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register8) && args[1].type() == typeid(Asm::Args::Register8)) { // mov reg8, reg8 // r/m8, r8: ModRM:r/m (w), ModRM:reg (r) machine_code = std::vector<uint8_t>{ 0x88 } + ModRM(std::any_cast<Asm::Args::Register8>(args[1]).name(), std::any_cast<Asm::Args::Register8>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Register32)) { // mov reg32, reg32 + // r/m32, r32: ModRM:r/m (w), ModRM:reg (r) + machine_code = std::vector<uint8_t>{ 0x89 } + + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), std::any_cast<Asm::Args::Register32>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Register64)) { // mov reg64, reg64 + // r/m64, r64: ModRM:r/m (w), ModRM:reg (r) + machine_code = REX("W") + std::vector<uint8_t>{ 0x89 } + + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), std::any_cast<Asm::Args::Register64>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Immediate32)) { // mov reg32, imm32 machine_code = std::vector<uint8_t>{ static_cast<uint8_t>(0xB8 + RegNo(std::any_cast<Asm::Args::Register32>(args[0]).name())) } + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode(); + } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Immediate64)) { // mov reg64, imm64 machine_code = std::vector<uint8_t>{ REX("W") + static_cast<uint8_t>(0xB8 + RegNo(std::any_cast<Asm::Args::Register64>(args[0]).name())) } + std::any_cast<Asm::Args::Immediate64>(args[1]).getCode(); + } else { throw std::runtime_error("Unimplemented: mov "s + args[0].type().name() + " "s + args[1].type().name()); } @@ -27,13 +40,13 @@ Op_mov::Op_mov(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register8, Asm::Args::Register8>("mov"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register8, Asm::Args::Register8>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_mov>(args); }) && - registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate32>("mov"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_mov>(args); }) && - registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate64>("mov"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate64>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_mov>(args); }) }; diff --git a/asm/intel64/mov.h b/asm/intel64/mov.h index 53afed4..06c346e 100644 --- a/asm/intel64/mov.h +++ b/asm/intel64/mov.h @@ -7,7 +7,7 @@ class Op_mov: public Op { public: - Op_mov(Asm::Args& args); + Op_mov(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/mul.cpp b/asm/intel64/mul.cpp index e4c3489..502b1d9 100644 --- a/asm/intel64/mul.cpp +++ b/asm/intel64/mul.cpp @@ -9,7 +9,7 @@ using namespace std::string_literals; -Op_mul::Op_mul(Asm::Args& args) +Op_mul::Op_mul(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register8)) { // mul reg8 (accu is ax <- al) machine_code = std::vector<uint8_t>{ 0xF6 } + @@ -28,13 +28,13 @@ Op_mul::Op_mul(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register8>("mul"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register8>("mul"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_mul>(args); }) && - registerOp(mangleName<Asm::Args::Register32>("mul"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register32>("mul"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_mul>(args); }) && - registerOp(mangleName<Asm::Args::Register64>("mul"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64>("mul"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_mul>(args); }) }; diff --git a/asm/intel64/mul.h b/asm/intel64/mul.h index 9ff31d1..0c4ab50 100644 --- a/asm/intel64/mul.h +++ b/asm/intel64/mul.h @@ -7,7 +7,7 @@ class Op_mul: public Op { public: - Op_mul(Asm::Args& args); + Op_mul(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/pop.cpp b/asm/intel64/pop.cpp index 8528b15..6d8b734 100644 --- a/asm/intel64/pop.cpp +++ b/asm/intel64/pop.cpp @@ -9,7 +9,7 @@ using namespace std::string_literals; -Op_pop::Op_pop(Asm::Args& args) +Op_pop::Op_pop(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register64)) { // pop reg64 machine_code = std::vector<uint8_t>{ 0x58 } + RegNo(std::any_cast<Asm::Args::Register64>(args[0]).name()); @@ -21,7 +21,7 @@ Op_pop::Op_pop(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register64>("pop"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64>("pop"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_pop>(args); }) }; diff --git a/asm/intel64/pop.h b/asm/intel64/pop.h index 3bcd421..c020568 100644 --- a/asm/intel64/pop.h +++ b/asm/intel64/pop.h @@ -7,7 +7,7 @@ class Op_pop: public Op { public: - Op_pop(Asm::Args& args); + Op_pop(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/push.cpp b/asm/intel64/push.cpp index bad2c90..37acec9 100644 --- a/asm/intel64/push.cpp +++ b/asm/intel64/push.cpp @@ -9,7 +9,7 @@ using namespace std::string_literals; -Op_push::Op_push(Asm::Args& args) +Op_push::Op_push(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register64)) { // push reg64 machine_code = std::vector<uint8_t>{ 0x50 } + RegNo(std::any_cast<Asm::Args::Register64>(args[0]).name()); @@ -21,7 +21,7 @@ Op_push::Op_push(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register64>("push"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64>("push"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_push>(args); }) }; diff --git a/asm/intel64/push.h b/asm/intel64/push.h index 9525981..e322622 100644 --- a/asm/intel64/push.h +++ b/asm/intel64/push.h @@ -7,7 +7,7 @@ class Op_push: public Op { public: - Op_push(Asm::Args& args); + Op_push(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/sub.cpp b/asm/intel64/sub.cpp index e055ee9..2447c15 100644 --- a/asm/intel64/sub.cpp +++ b/asm/intel64/sub.cpp @@ -7,7 +7,7 @@ using namespace std::string_literals; -Op_sub::Op_sub(Asm::Args& args) +Op_sub::Op_sub(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register32) && std::any_cast<Asm::Args::Register32>(args[0]).name() == "eax" && @@ -31,10 +31,10 @@ Op_sub::Op_sub(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate32>("sub"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate32>("sub"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_sub>(args); }) && - registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate32>("sub"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate32>("sub"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_sub>(args); }) }; diff --git a/asm/intel64/sub.h b/asm/intel64/sub.h index cc0dd81..88dcbf4 100644 --- a/asm/intel64/sub.h +++ b/asm/intel64/sub.h @@ -7,7 +7,7 @@ class Op_sub: public Op { public: - Op_sub(Asm::Args& args); + Op_sub(const Asm::Args& args); public: std::vector<uint8_t> getCode() override diff --git a/asm/intel64/trivials.cpp b/asm/intel64/trivials.cpp index 094d27f..eb1bbb8 100644 --- a/asm/intel64/trivials.cpp +++ b/asm/intel64/trivials.cpp @@ -9,13 +9,13 @@ Op_syscall::Op_syscall(): OpSimple({ 0x0F, 0x05 }) {} namespace { bool registered { - registerOp("nop", [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp("nop", [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_nop>(); }) && - registerOp("ret", [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp("ret", [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_ret>(); }) && - registerOp("syscall", [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp("syscall", [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_syscall>(); }) }; diff --git a/asm/intel64/xor.cpp b/asm/intel64/xor.cpp index 2aa4272..aba6fb5 100644 --- a/asm/intel64/xor.cpp +++ b/asm/intel64/xor.cpp @@ -9,7 +9,7 @@ using namespace std::string_literals; -Op_xor::Op_xor(Asm::Args& args) +Op_xor::Op_xor(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register8) && args[1].type() == typeid(Asm::Args::Register8)) { // xor reg8, reg8 // r8, r/m8: ModRM:reg (w), ModRM:r/m (r) @@ -23,7 +23,7 @@ Op_xor::Op_xor(Asm::Args& args) namespace { bool registered { - registerOp(mangleName<Asm::Args::Register8, Asm::Args::Register8>("xor"), [](Asm::Args& args) -> std::shared_ptr<Op>{ + registerOp(mangleName<Asm::Args::Register8, Asm::Args::Register8>("xor"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_xor>(args); }) }; diff --git a/asm/intel64/xor.h b/asm/intel64/xor.h index 7e07006..8cae899 100644 --- a/asm/intel64/xor.h +++ b/asm/intel64/xor.h @@ -7,7 +7,7 @@ class Op_xor: public Op { public: - Op_xor(Asm::Args& args); + Op_xor(const Asm::Args& args); public: std::vector<uint8_t> getCode() override @@ -13,6 +13,8 @@ #include <gtest/gtest.h> #include <gmock/gmock.h> +#include <boost/core/demangle.hpp> + #include <functional> #include <optional> #include <unordered_set> @@ -398,6 +400,11 @@ std::unordered_map<std::string, std::function<std::any(index_t)>> CPP::getNodeEv { "multiplicative-expression", [&](index_t index) -> std::any { if (childTypesOfNodeMatch(index, {"multiplicative-expression", "*", "pm-expression"})) { + if (getValue(index, 0).type() != typeid(FlowGraph::Data)) + throw std::runtime_error("ICE: multiplicative-expression: Bad data type for argument 1: "s + demangle(getValue(index, 0).type())); + if (getValue(index, 2).type() != typeid(FlowGraph::Data)) + throw std::runtime_error("ICE: multiplicative-expression: Bad data type for argument 3: "s + demangle(getValue(index, 2).type())); + FlowGraph::LocalScope scope; // TODO: move to context! FlowGraph::Data destination{FlowGraph::MakeTemporaryInt(scope)}; FlowGraph::Data value0 {std::any_cast<FlowGraph::Data>(getValue(index, 0))}; @@ -414,6 +421,11 @@ std::unordered_map<std::string, std::function<std::any(index_t)>> CPP::getNodeEv { "additive-expression", [&](index_t index) -> std::any { if (childTypesOfNodeMatch(index, {"additive-expression", "+", "multiplicative-expression"})) { + if (getValue(index, 0).type() != typeid(FlowGraph::Data)) + throw std::runtime_error("ICE: additive-expression: Bad data type for argument 1: "s + demangle(getValue(index, 0).type())); + if (getValue(index, 2).type() != typeid(FlowGraph::Data)) + throw std::runtime_error("ICE: additive-expression: Bad data type for argument 3: "s + demangle(getValue(index, 2).type())); + FlowGraph::LocalScope scope; // TODO: move to context! FlowGraph::Data destination{FlowGraph::MakeTemporaryInt(scope)}; FlowGraph::Data value0 {std::any_cast<FlowGraph::Data>(getValue(index, 0))}; @@ -507,19 +519,27 @@ std::unordered_map<std::string, std::function<std::any(index_t)>> CPP::getNodeEv { "expression", [&](index_t index) -> std::any { if (childTypesOfNodeMatch(index, {"assignment-expression"})) { + std::shared_ptr<FlowGraph::CreateScopeOp> scope_node {std::make_shared<FlowGraph::CreateScopeOp>()}; + mCPPContext.graph.push_back(scope_node); + + FlowGraph::LocalScope& scope{scope_node->scope()}; + if (getValue(index, 0).type() == typeid(FlowGraph::Data)) { // got Data -> make trivial Node out of it and return it - FlowGraph::LocalScope scope; // TODO: move to context! + FlowGraph::Data destination{FlowGraph::MakeTemporaryInt(scope)}; FlowGraph::Data source {std::any_cast<FlowGraph::Data>(getValue(index, 0))}; std::shared_ptr<FlowGraph::Node> node {std::make_shared<FlowGraph::UnaryOperation>(FlowGraph::UnaryOperationType::Store, destination, source)}; mCPPContext.graph.push_back(node); return node; - } else { + } else if (getValue(index, 0).type() == typeid(std::shared_ptr<FlowGraph::Node>)) { std::shared_ptr<FlowGraph::Node> node {std::any_cast<std::shared_ptr<FlowGraph::Node>>(getValue(index, 0))}; mCPPContext.graph.push_back(node); return getValue(index, 0); + } else { + throw std::runtime_error("ICE: expression: Unsupported argument type: "s + demangle(getValue(index, 0).type())); } + mCPPContext.graph.push_back(std::make_shared<FlowGraph::DestroyScopeOp>(scope)); } throw std::runtime_error("ICE: Unsupported childs: "s + ruleString(index)); // TODO } @@ -66,7 +66,7 @@ private: std::unordered_map<std::string, std::function<std::any(index_t)>> getNodeEvalMap(); std::unordered_map<std::string, std::function<std::any(index_t)>> node_eval_map; - CPPContext mCPPContext; + CPPContext mCPPContext; // intermediate data of phase 7.c void getValueOfToken(index_t index); void getValueOfNode(index_t index); diff --git a/flowgraph/node.h b/flowgraph/node.h index 98c684d..77395f0 100644 --- a/flowgraph/node.h +++ b/flowgraph/node.h @@ -174,7 +174,7 @@ namespace FlowGraph { class DestroyScopeOp: public Node { public: - DestroyScopeOp() {} + DestroyScopeOp(LocalScope& scope) {} }; } // namespace FlowGraph @@ -60,3 +60,8 @@ std::string Token::toString() const return location.toString() + ": "s + value + " ("s + type + ")"s; } +std::string demangle(const std::type_info& type) +{ + return boost::core::demangle(type.name()); +} + @@ -2,6 +2,8 @@ #pragma once +#include <boost/core/demangle.hpp> + #include <cstdlib> #include <filesystem> #include <iostream> @@ -47,3 +49,5 @@ struct PairHashSS { return h0 ^ (h1 << 1); } }; + +std::string demangle(const std::type_info& type); diff --git a/tests/test-flowgraph.cpp b/tests/test-flowgraph.cpp index 021d6dd..469d816 100644 --- a/tests/test-flowgraph.cpp +++ b/tests/test-flowgraph.cpp @@ -51,7 +51,7 @@ TEST_F(FlowGraphTest, build_graph) { std::shared_ptr<Node> free1{ std::make_shared<DeallocateDynamic>(pointer) }; graph.push_back(free1); - std::shared_ptr<Node> destroyScope{std::make_shared<DestroyScopeOp>()}; + std::shared_ptr<Node> destroyScope{std::make_shared<DestroyScopeOp>(createScope->scope())}; graph.push_back(destroyScope); } |