blob: b26bf9c04893ac10a790b57e567bfe0370641b13 (
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
// 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) {
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");
}
} else {
throw std::runtime_error("ICE: encode: flowgraph node is null");
}
}
}
|