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