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