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