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