blob: 702efaffd0821f56d964b3860e8a2b5dfc77f453 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
// Intel specific conversion: Abstract Graph -> Machine specific segment
#include "encode.h"
#include "asm/assembler.h"
#include "minicc.h"
#include <boost/endian/conversion.hpp>
#include <exception>
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");
}
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());
}
}
}
|