Home | History | Annotate | Download | only in Script
      1 //===- Assignment.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/Assignment.h>
     10 #include <mcld/Script/RpnExpr.h>
     11 #include <mcld/Script/Operand.h>
     12 #include <mcld/Script/Operator.h>
     13 #include <mcld/Script/RpnEvaluator.h>
     14 #include <mcld/Support/raw_ostream.h>
     15 #include <mcld/LinkerScript.h>
     16 #include <mcld/LD/LDSection.h>
     17 #include <mcld/LD/SectionData.h>
     18 #include <mcld/Module.h>
     19 #include <llvm/Support/Casting.h>
     20 #include <cassert>
     21 
     22 using namespace mcld;
     23 
     24 //===----------------------------------------------------------------------===//
     25 // Assignment
     26 //===----------------------------------------------------------------------===//
     27 Assignment::Assignment(Level pLevel,
     28                        Type pType,
     29                        SymOperand& pSymbol,
     30                        RpnExpr& pRpnExpr)
     31   : ScriptCommand(ScriptCommand::ASSIGNMENT),
     32     m_Level(pLevel),
     33     m_Type(pType),
     34     m_Symbol(pSymbol),
     35     m_RpnExpr(pRpnExpr)
     36 {
     37 }
     38 
     39 Assignment::~Assignment()
     40 {
     41 }
     42 
     43 Assignment& Assignment::operator=(const Assignment& pAssignment)
     44 {
     45   return *this;
     46 }
     47 
     48 void Assignment::dump() const
     49 {
     50   switch (type()) {
     51   case DEFAULT:
     52     break;
     53   case HIDDEN:
     54     mcld::outs() << "HIDDEN ( ";
     55     break;
     56   case PROVIDE:
     57     mcld::outs() << "PROVIDE ( ";
     58     break;
     59   case PROVIDE_HIDDEN:
     60     mcld::outs() << "PROVIDE_HIDDEN ( ";
     61     break;
     62   default:
     63     break;
     64   }
     65 
     66   m_Symbol.dump();
     67 
     68   mcld::outs() << " = ";
     69 
     70   m_RpnExpr.dump();
     71 
     72   if (type() != DEFAULT)
     73     mcld::outs() << " )";
     74 
     75   mcld::outs() << ";\n";
     76 }
     77 
     78 void Assignment::activate(Module& pModule)
     79 {
     80   bool isLhsDot = m_Symbol.isDot();
     81   LinkerScript& script = pModule.getScript();
     82   switch (m_Level) {
     83   case OUTSIDE_SECTIONS:
     84     assert(!isLhsDot);
     85     script.assignments().push_back(std::make_pair((LDSymbol*)NULL, *this));
     86     break;
     87 
     88   case OUTPUT_SECTION: {
     89     bool hasDotInRhs = m_RpnExpr.hasDot();
     90     SectionMap::reference out = script.sectionMap().back();
     91     if (hasDotInRhs) {
     92       if (!isLhsDot && out->dotAssignments().empty()) {
     93         // . = ADDR ( `prev_output_sect' ) + SIZEOF ( `prev_output_sect' )
     94         SectionMap::iterator prev = script.sectionMap().begin() +
     95                                     script.sectionMap().size() - 2;
     96         Assignment assign(OUTPUT_SECTION,
     97                           HIDDEN,
     98                           *SymOperand::create("."),
     99                           *RpnExpr::buildHelperExpr(prev));
    100         out->dotAssignments().push_back(assign);
    101       }
    102 
    103       if (!out->dotAssignments().empty()) {
    104         Assignment& prevDotAssign = out->dotAssignments().back();
    105         // If this is the 1st explicit assignment that includes both lhs dot and
    106         // rhs dot, then because of possible orphan sections, we are unable to
    107         // substitute the rhs dot now.
    108         if (!isLhsDot || prevDotAssign.type() == DEFAULT) {
    109           for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
    110             it != ie; ++it) {
    111             // substitute the rhs dot with the appropriate helper expr
    112             if ((*it)->kind() == ExprToken::OPERAND &&
    113                 llvm::cast<Operand>(*it)->isDot())
    114               *it = &(prevDotAssign.symbol());
    115           } // for each expression token
    116         }
    117       }
    118     }
    119 
    120     if (isLhsDot) {
    121       out->dotAssignments().push_back(*this);
    122     } else {
    123       script.assignments().push_back(std::make_pair((LDSymbol*)NULL, *this));
    124     }
    125 
    126     break;
    127   }
    128 
    129   case INPUT_SECTION: {
    130     bool hasDotInRhs = m_RpnExpr.hasDot();
    131     SectionMap::Output::reference in = script.sectionMap().back()->back();
    132     if (hasDotInRhs) {
    133       if (in->dotAssignments().empty()) {
    134         // . = `frag'
    135         RpnExpr* expr =
    136           RpnExpr::buildHelperExpr(in->getSection()->getSectionData()->front());
    137         Assignment assign(INPUT_SECTION,
    138                           HIDDEN,
    139                           *SymOperand::create("."),
    140                           *expr);
    141         in->dotAssignments().push_back(std::make_pair((Fragment*)NULL, assign));
    142       }
    143 
    144       Assignment& prevDotAssign = in->dotAssignments().back().second;
    145       for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
    146         it != ie; ++it) {
    147         // substitute the rhs dot with the appropriate helper expr
    148         if ((*it)->kind() == ExprToken::OPERAND &&
    149             llvm::cast<Operand>(*it)->isDot())
    150           *it = &(prevDotAssign.symbol());
    151       } // end of for
    152     }
    153 
    154     if (isLhsDot) {
    155       in->dotAssignments().push_back(
    156         std::make_pair(in->getSection()->getSectionData()->front().getNextNode(),
    157                        *this));
    158     } else {
    159       script.assignments().push_back(std::make_pair((LDSymbol*)NULL, *this));
    160     }
    161 
    162     break;
    163   }
    164 
    165   } // end of switch
    166 }
    167 
    168 bool Assignment::assign(RpnEvaluator& pEvaluator)
    169 {
    170   uint64_t result = 0;
    171   bool success = pEvaluator.eval(m_RpnExpr, result);
    172   if (success)
    173     m_Symbol.setValue(result);
    174   return success;
    175 }
    176