• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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