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