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
18using namespace mcld;
19//===----------------------------------------------------------------------===//
20// BinaryOp
21//===----------------------------------------------------------------------===//
22template<>
23IntOperand* 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
31template<>
32IntOperand* 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
40template<>
41IntOperand* 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
49template<>
50IntOperand* 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
58template<>
59IntOperand* 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
67template<>
68IntOperand* 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
76template<>
77IntOperand* 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
85template<>
86IntOperand* 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
94template<>
95IntOperand* 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
103template<>
104IntOperand* 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
112template<>
113IntOperand* 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
121template<>
122IntOperand* 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
130template<>
131IntOperand* 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
139template<>
140IntOperand*
141BinaryOp<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
149template<>
150IntOperand*
151BinaryOp<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
159template<>
160IntOperand*
161BinaryOp<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
169template<>
170IntOperand*
171BinaryOp<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
179template<>
180IntOperand*
181BinaryOp<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
189template<>
190IntOperand* 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
201template<>
202IntOperand*
203BinaryOp<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
215template<>
216IntOperand* 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
227template<>
228IntOperand* 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) */
241template<>
242IntOperand*
243BinaryOp<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