//===- BinaryOp.cpp -------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "mcld/Script/BinaryOp.h" #include "mcld/LinkerScript.h" #include "mcld/Module.h" #include "mcld/ADT/SizeTraits.h" #include "mcld/Script/Operand.h" #include "mcld/Target/TargetLDBackend.h" #include #include namespace mcld { //===----------------------------------------------------------------------===// // BinaryOp //===----------------------------------------------------------------------===// template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() * m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() / m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() % m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() + m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() - m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() << m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() >> m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() < m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() <= m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() > m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() >= m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() == m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() != m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval( const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() & m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval( const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() ^ m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval( const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() | m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval( const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() && m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval( const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); res->setValue(m_pOperand[0]->value() || m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); uint64_t value = m_pOperand[0]->value(); uint64_t align = m_pOperand[1]->value(); alignAddress(value, align); res->setValue(value); return res; } template <> IntOperand* BinaryOp::eval( const Module& pModule, const TargetLDBackend& pBackend) { /* FIXME: Currently we handle relro in a different way, and now the result of this expression won't affect DATA_SEGMENT_ALIGN. */ IntOperand* res = result(); uint64_t value = m_pOperand[0]->value() + m_pOperand[1]->value(); alignAddress(value, pBackend.commonPageSize()); res->setValue(value); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); if (m_pOperand[0]->value() >= m_pOperand[1]->value()) res->setValue(m_pOperand[0]->value()); else res->setValue(m_pOperand[1]->value()); return res; } template <> IntOperand* BinaryOp::eval(const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); if (m_pOperand[0]->value() <= m_pOperand[1]->value()) res->setValue(m_pOperand[0]->value()); else res->setValue(m_pOperand[1]->value()); return res; } /* SEGMENT_START(segment, default) */ template <> IntOperand* BinaryOp::eval( const Module& pModule, const TargetLDBackend& pBackend) { IntOperand* res = result(); /* Currently we look up segment address from -T command line options. */ SectOperand* sect = llvm::cast(m_pOperand[0]); const LinkerScript::AddressMap& addressMap = pModule.getScript().addressMap(); LinkerScript::AddressMap::const_iterator addr; if (sect->name().compare("text-segment") == 0) addr = addressMap.find(".text"); else if (sect->name().compare("data-segment") == 0) addr = addressMap.find(".data"); else if (sect->name().compare("bss-segment") == 0) addr = addressMap.find(".bss"); else addr = addressMap.find(sect->name()); if (addr != addressMap.end()) res->setValue(addr.getEntry()->value()); else { assert(m_pOperand[1]->type() == Operand::INTEGER); res->setValue(m_pOperand[1]->value()); } return res; } } // namespace mcld