diff options
Diffstat (limited to 'asm/intel64/encode.cpp')
-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"); } } } |