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);  } | 
