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