1 //===- BinaryOp.cpp -------------------------------------------------------===//
2 //
3 // The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "mcld/Script/BinaryOp.h"
10
11 #include "mcld/LinkerScript.h"
12 #include "mcld/Module.h"
13 #include "mcld/ADT/SizeTraits.h"
14 #include "mcld/Script/Operand.h"
15 #include "mcld/Target/TargetLDBackend.h"
16
17 #include <llvm/Support/Casting.h>
18
19 #include <cassert>
20
21 namespace mcld {
22
23 //===----------------------------------------------------------------------===//
24 // BinaryOp
25 //===----------------------------------------------------------------------===//
26 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)27 IntOperand* BinaryOp<Operator::MUL>::eval(const Module& pModule,
28 const TargetLDBackend& pBackend) {
29 IntOperand* res = result();
30 res->setValue(m_pOperand[0]->value() * m_pOperand[1]->value());
31 return res;
32 }
33
34 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)35 IntOperand* BinaryOp<Operator::DIV>::eval(const Module& pModule,
36 const TargetLDBackend& pBackend) {
37 IntOperand* res = result();
38 res->setValue(m_pOperand[0]->value() / m_pOperand[1]->value());
39 return res;
40 }
41
42 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)43 IntOperand* BinaryOp<Operator::MOD>::eval(const Module& pModule,
44 const TargetLDBackend& pBackend) {
45 IntOperand* res = result();
46 res->setValue(m_pOperand[0]->value() % m_pOperand[1]->value());
47 return res;
48 }
49
50 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)51 IntOperand* BinaryOp<Operator::ADD>::eval(const Module& pModule,
52 const TargetLDBackend& pBackend) {
53 IntOperand* res = result();
54 res->setValue(m_pOperand[0]->value() + m_pOperand[1]->value());
55 return res;
56 }
57
58 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)59 IntOperand* BinaryOp<Operator::SUB>::eval(const Module& pModule,
60 const TargetLDBackend& pBackend) {
61 IntOperand* res = result();
62 res->setValue(m_pOperand[0]->value() - m_pOperand[1]->value());
63 return res;
64 }
65
66 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)67 IntOperand* BinaryOp<Operator::LSHIFT>::eval(const Module& pModule,
68 const TargetLDBackend& pBackend) {
69 IntOperand* res = result();
70 res->setValue(m_pOperand[0]->value() << m_pOperand[1]->value());
71 return res;
72 }
73
74 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)75 IntOperand* BinaryOp<Operator::RSHIFT>::eval(const Module& pModule,
76 const TargetLDBackend& pBackend) {
77 IntOperand* res = result();
78 res->setValue(m_pOperand[0]->value() >> m_pOperand[1]->value());
79 return res;
80 }
81
82 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)83 IntOperand* BinaryOp<Operator::LT>::eval(const Module& pModule,
84 const TargetLDBackend& pBackend) {
85 IntOperand* res = result();
86 res->setValue(m_pOperand[0]->value() < m_pOperand[1]->value());
87 return res;
88 }
89
90 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)91 IntOperand* BinaryOp<Operator::LE>::eval(const Module& pModule,
92 const TargetLDBackend& pBackend) {
93 IntOperand* res = result();
94 res->setValue(m_pOperand[0]->value() <= m_pOperand[1]->value());
95 return res;
96 }
97
98 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)99 IntOperand* BinaryOp<Operator::GT>::eval(const Module& pModule,
100 const TargetLDBackend& pBackend) {
101 IntOperand* res = result();
102 res->setValue(m_pOperand[0]->value() > m_pOperand[1]->value());
103 return res;
104 }
105
106 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)107 IntOperand* BinaryOp<Operator::GE>::eval(const Module& pModule,
108 const TargetLDBackend& pBackend) {
109 IntOperand* res = result();
110 res->setValue(m_pOperand[0]->value() >= m_pOperand[1]->value());
111 return res;
112 }
113
114 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)115 IntOperand* BinaryOp<Operator::EQ>::eval(const Module& pModule,
116 const TargetLDBackend& pBackend) {
117 IntOperand* res = result();
118 res->setValue(m_pOperand[0]->value() == m_pOperand[1]->value());
119 return res;
120 }
121
122 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)123 IntOperand* BinaryOp<Operator::NE>::eval(const Module& pModule,
124 const TargetLDBackend& pBackend) {
125 IntOperand* res = result();
126 res->setValue(m_pOperand[0]->value() != m_pOperand[1]->value());
127 return res;
128 }
129
130 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)131 IntOperand* BinaryOp<Operator::BITWISE_AND>::eval(
132 const Module& pModule,
133 const TargetLDBackend& pBackend) {
134 IntOperand* res = result();
135 res->setValue(m_pOperand[0]->value() & m_pOperand[1]->value());
136 return res;
137 }
138
139 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)140 IntOperand* BinaryOp<Operator::BITWISE_XOR>::eval(
141 const Module& pModule,
142 const TargetLDBackend& pBackend) {
143 IntOperand* res = result();
144 res->setValue(m_pOperand[0]->value() ^ m_pOperand[1]->value());
145 return res;
146 }
147
148 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)149 IntOperand* BinaryOp<Operator::BITWISE_OR>::eval(
150 const Module& pModule,
151 const TargetLDBackend& pBackend) {
152 IntOperand* res = result();
153 res->setValue(m_pOperand[0]->value() | m_pOperand[1]->value());
154 return res;
155 }
156
157 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)158 IntOperand* BinaryOp<Operator::LOGICAL_AND>::eval(
159 const Module& pModule,
160 const TargetLDBackend& pBackend) {
161 IntOperand* res = result();
162 res->setValue(m_pOperand[0]->value() && m_pOperand[1]->value());
163 return res;
164 }
165
166 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)167 IntOperand* BinaryOp<Operator::LOGICAL_OR>::eval(
168 const Module& pModule,
169 const TargetLDBackend& pBackend) {
170 IntOperand* res = result();
171 res->setValue(m_pOperand[0]->value() || m_pOperand[1]->value());
172 return res;
173 }
174
175 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)176 IntOperand* BinaryOp<Operator::ALIGN>::eval(const Module& pModule,
177 const TargetLDBackend& pBackend) {
178 IntOperand* res = result();
179 uint64_t value = m_pOperand[0]->value();
180 uint64_t align = m_pOperand[1]->value();
181 alignAddress(value, align);
182 res->setValue(value);
183 return res;
184 }
185
186 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)187 IntOperand* BinaryOp<Operator::DATA_SEGMENT_RELRO_END>::eval(
188 const Module& pModule,
189 const TargetLDBackend& pBackend) {
190 /* FIXME: Currently we handle relro in a different way, and now the result
191 of this expression won't affect DATA_SEGMENT_ALIGN. */
192 IntOperand* res = result();
193 uint64_t value = m_pOperand[0]->value() + m_pOperand[1]->value();
194 alignAddress(value, pBackend.commonPageSize());
195 res->setValue(value);
196 return res;
197 }
198
199 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)200 IntOperand* BinaryOp<Operator::MAX>::eval(const Module& pModule,
201 const TargetLDBackend& pBackend) {
202 IntOperand* res = result();
203 if (m_pOperand[0]->value() >= m_pOperand[1]->value())
204 res->setValue(m_pOperand[0]->value());
205 else
206 res->setValue(m_pOperand[1]->value());
207 return res;
208 }
209
210 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)211 IntOperand* BinaryOp<Operator::MIN>::eval(const Module& pModule,
212 const TargetLDBackend& pBackend) {
213 IntOperand* res = result();
214 if (m_pOperand[0]->value() <= m_pOperand[1]->value())
215 res->setValue(m_pOperand[0]->value());
216 else
217 res->setValue(m_pOperand[1]->value());
218 return res;
219 }
220
221 /* SEGMENT_START(segment, default) */
222 template <>
eval(const Module & pModule,const TargetLDBackend & pBackend)223 IntOperand* BinaryOp<Operator::SEGMENT_START>::eval(
224 const Module& pModule,
225 const TargetLDBackend& pBackend) {
226 IntOperand* res = result();
227 /* Currently we look up segment address from -T command line options. */
228 SectOperand* sect = llvm::cast<SectOperand>(m_pOperand[0]);
229 const LinkerScript::AddressMap& addressMap = pModule.getScript().addressMap();
230 LinkerScript::AddressMap::const_iterator addr;
231 if (sect->name().compare("text-segment") == 0)
232 addr = addressMap.find(".text");
233 else if (sect->name().compare("data-segment") == 0)
234 addr = addressMap.find(".data");
235 else if (sect->name().compare("bss-segment") == 0)
236 addr = addressMap.find(".bss");
237 else
238 addr = addressMap.find(sect->name());
239
240 if (addr != addressMap.end())
241 res->setValue(addr.getEntry()->value());
242 else {
243 assert(m_pOperand[1]->type() == Operand::INTEGER);
244 res->setValue(m_pOperand[1]->value());
245 }
246 return res;
247 }
248
249 } // namespace mcld
250