Home | History | Annotate | Download | only in Script
      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