diff options
| author | Roland Reichwein <mail@reichwein.it> | 2020-11-14 22:06:10 +0100 | 
|---|---|---|
| committer | Roland Reichwein <mail@reichwein.it> | 2020-11-14 22:06:10 +0100 | 
| commit | 9e7f4c9d43b310c280cd6432cd4150411f4b914e (patch) | |
| tree | c7be57a91602c228f05ff1cab2f186dcc6635733 /asm | |
| parent | 009e450626194299ee4b5ccb8463ac64e127fde6 (diff) | |
Added system tests
Diffstat (limited to 'asm')
| -rw-r--r-- | asm/intel64/encode.cpp | 141 | 
1 files changed, 87 insertions, 54 deletions
| diff --git a/asm/intel64/encode.cpp b/asm/intel64/encode.cpp index 702efaf..b26bf9c 100644 --- a/asm/intel64/encode.cpp +++ b/asm/intel64/encode.cpp @@ -13,61 +13,94 @@ void Asm::toMachineCode(const FlowGraph::Graph& graph, Segment& segment)   segment.clear();   for (const std::shared_ptr<FlowGraph::Node>& node: graph) { -  try { -   FlowGraph::BinaryOperation& op {dynamic_cast<FlowGraph::BinaryOperation&>(*node)}; - -   auto operands {op.operands()}; -   // TODO: ignore destination (0) for now - -   if (operands[1].type() != FlowGraph::DataType::Int) { -    std::runtime_error("Bad type for operand 1: "s + std::to_string(int(operands[1].type()))); -   } - -   if (operands[2].type() != FlowGraph::DataType::Int) { -    std::runtime_error("Bad type for operand 2: "s + std::to_string(int(operands[2].type()))); -   } - -   if (!operands[1].storage()) -    throw std::runtime_error("ICE: Operand 1 storage is 0"); -   if (!operands[2].storage()) -    throw std::runtime_error("ICE: Operand 2 storage is 0"); - -   uint32_t immediate1{}; -   try { -    FlowGraph::Constant& value1 {dynamic_cast<FlowGraph::Constant&>(*operands[1].storage())}; -    if (value1.value().size() < sizeof(uint32_t)) -     throw std::runtime_error("ICE: Int data from operand 1 needs at least 4 bytes, got "s + std::to_string(value1.value().size())); - -    immediate1 = boost::endian::little_to_native(*(reinterpret_cast<const uint32_t*>(value1.value().data()))); -   } catch (const std::bad_cast& ex) { -    std::runtime_error("Bad value for operand 1: Constant expected"); -   } -    -   uint32_t immediate2{}; -   try { -    FlowGraph::Constant& value2 {dynamic_cast<FlowGraph::Constant&>(*operands[2].storage())}; -    if (value2.value().size() < sizeof(uint32_t)) -     throw std::runtime_error("ICE: Int data from operand 2 needs at least 4 bytes, got "s + std::to_string(value2.value().size())); - -    immediate2 = boost::endian::little_to_native(*(reinterpret_cast<const uint32_t*>(value2.value().data()))); -   } catch (const std::bad_cast& ex) { -    std::runtime_error("Bad value for operand 2: Constant expected"); +  if (node.get()) { +   auto& node_deref = *node.get(); +   if (typeid(node_deref) == typeid(FlowGraph::UnaryOperation)) { +    FlowGraph::UnaryOperation& op {dynamic_cast<FlowGraph::UnaryOperation&>(*node)}; +    auto operands {op.operands()}; + +    if (operands[1].type() != FlowGraph::DataType::Int) { +     std::runtime_error("Bad type for operand 1: "s + std::to_string(int(operands[1].type()))); +    } +     +    if (!operands[1].storage()) +     throw std::runtime_error("ICE: Operand 1 storage is 0"); + +    uint32_t immediate1{}; +    try { +     FlowGraph::Constant& value1 {dynamic_cast<FlowGraph::Constant&>(*operands[1].storage())}; +     if (value1.value().size() < sizeof(uint32_t)) +      throw std::runtime_error("ICE: Int data from operand 1 needs at least 4 bytes, got "s + std::to_string(value1.value().size())); + +     immediate1 = boost::endian::little_to_native(*(reinterpret_cast<const uint32_t*>(value1.value().data()))); +    } catch (const std::bad_cast& ex) { +     std::runtime_error("Bad value for operand 1: Constant expected"); +    } +     +    if (op.type() == FlowGraph::UnaryOperationType::Store) { +     Asm::Args args1{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(immediate1)}}; +     segment.push_back(makeOp("mov", args1)); +    } else +     throw std::runtime_error("ICE: Asm: Unsupported unary operation type: "s + std::to_string(static_cast<int>(op.type()))); +     +   } else if (typeid(node_deref) == typeid(FlowGraph::BinaryOperation)) { +    FlowGraph::BinaryOperation& op {dynamic_cast<FlowGraph::BinaryOperation&>(*node)}; + +    auto operands {op.operands()}; +    // TODO: ignore destination (0) for now + +    if (operands[1].type() != FlowGraph::DataType::Int) { +     std::runtime_error("Bad type for operand 1: "s + std::to_string(int(operands[1].type()))); +    } + +    if (operands[2].type() != FlowGraph::DataType::Int) { +     std::runtime_error("Bad type for operand 2: "s + std::to_string(int(operands[2].type()))); +    } + +    if (!operands[1].storage()) +     throw std::runtime_error("ICE: Operand 1 storage is 0"); +    if (!operands[2].storage()) +     throw std::runtime_error("ICE: Operand 2 storage is 0"); + +    uint32_t immediate1{}; +    try { +     FlowGraph::Constant& value1 {dynamic_cast<FlowGraph::Constant&>(*operands[1].storage())}; +     if (value1.value().size() < sizeof(uint32_t)) +      throw std::runtime_error("ICE: Int data from operand 1 needs at least 4 bytes, got "s + std::to_string(value1.value().size())); + +     immediate1 = boost::endian::little_to_native(*(reinterpret_cast<const uint32_t*>(value1.value().data()))); +    } catch (const std::bad_cast& ex) { +     std::runtime_error("Bad value for operand 1: Constant expected"); +    } +     +    uint32_t immediate2{}; +    try { +     FlowGraph::Constant& value2 {dynamic_cast<FlowGraph::Constant&>(*operands[2].storage())}; +     if (value2.value().size() < sizeof(uint32_t)) +      throw std::runtime_error("ICE: Int data from operand 2 needs at least 4 bytes, got "s + std::to_string(value2.value().size())); + +     immediate2 = boost::endian::little_to_native(*(reinterpret_cast<const uint32_t*>(value2.value().data()))); +    } catch (const std::bad_cast& ex) { +     std::runtime_error("Bad value for operand 2: Constant expected"); +    } + +    Asm::Args args1{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(immediate1)}}; +    segment.push_back(makeOp("mov", args1)); +     +    Asm::Args args2{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(immediate2)}}; + +    if (op.type() == FlowGraph::BinaryOperationType::Add) +     segment.push_back(makeOp("add", args2)); +    else if (op.type() == FlowGraph::BinaryOperationType::Multiply) +     segment.push_back(makeOp("mul", args2)); +    else +     throw std::runtime_error("ICE: Asm: Unsupported binary operation type: "s + std::to_string(static_cast<int>(op.type()))); + +   } else { +    throw std::runtime_error("ICE: Encoding: Unsupported node");     } - -   Asm::Args args1{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(immediate1)}}; -   segment.push_back(makeOp("mov", args1)); -    -   Asm::Args args2{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(immediate2)}}; - -   if (op.type() == FlowGraph::BinaryOperationType::Add) -    segment.push_back(makeOp("add", args2)); -   else if (op.type() == FlowGraph::BinaryOperationType::Multiply) -    segment.push_back(makeOp("mul", args2)); -   else -    throw std::runtime_error("ICE: Asm: Unsupported binary operation type: "s + std::to_string(static_cast<int>(FlowGraph::BinaryOperationType::Multiply))); - -  } catch (const std::bad_cast& ex) { -   std::runtime_error("ICE: Encoding: Unsupported node: "s + ex.what()); +  } else { +   throw std::runtime_error("ICE: encode: flowgraph node is null");    }   }  } | 
