BinaryOp.cpp revision f33f6de54db174aa679a4b6d1e040d37e95541c0
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