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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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