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
21namespace mcld {
22
23//===----------------------------------------------------------------------===//
24// BinaryOp
25//===----------------------------------------------------------------------===//
26template <>
27IntOperand* 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
34template <>
35IntOperand* 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
42template <>
43IntOperand* 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
50template <>
51IntOperand* 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
58template <>
59IntOperand* 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
66template <>
67IntOperand* 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
74template <>
75IntOperand* 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
82template <>
83IntOperand* 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
90template <>
91IntOperand* 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
98template <>
99IntOperand* 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
106template <>
107IntOperand* 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
114template <>
115IntOperand* 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
122template <>
123IntOperand* 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
130template <>
131IntOperand* 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
139template <>
140IntOperand* 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
148template <>
149IntOperand* 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
157template <>
158IntOperand* 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
166template <>
167IntOperand* 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
175template <>
176IntOperand* 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
186template <>
187IntOperand* 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
199template <>
200IntOperand* 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
210template <>
211IntOperand* 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) */
222template <>
223IntOperand* 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