1f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===- Assignment.cpp -----------------------------------------------------===// 2f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// 3f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// The MCLinker Project 4f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// 5f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// This file is distributed under the University of Illinois Open Source 6f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// License. See LICENSE.TXT for details. 7f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// 8f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===// 937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/Assignment.h" 1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerScript.h" 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Module.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/SectionData.h" 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/Operand.h" 1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/Operator.h" 1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/RpnEvaluator.h" 1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/RpnExpr.h" 1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/raw_ostream.h" 2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines 21f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/Casting.h> 2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines 23f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <cassert> 24f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 2537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 26f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 27f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===// 28f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// Assignment 29f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===// 30f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesAssignment::Assignment(Level pLevel, 31f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines Type pType, 32f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines SymOperand& pSymbol, 33f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines RpnExpr& pRpnExpr) 3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines : ScriptCommand(ScriptCommand::ASSIGNMENT), 3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_Level(pLevel), 3637b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_Type(pType), 3737b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_Symbol(pSymbol), 3837b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_RpnExpr(pRpnExpr) { 39f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines} 40f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 4137b74a387bb3993387029859c2d9d051c41c724eStephen HinesAssignment::~Assignment() { 42f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines} 43f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 4437b74a387bb3993387029859c2d9d051c41c724eStephen HinesAssignment& Assignment::operator=(const Assignment& pAssignment) { 45f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines return *this; 46f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines} 47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 4837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Assignment::dump() const { 49f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines switch (type()) { 5037b74a387bb3993387029859c2d9d051c41c724eStephen Hines case DEFAULT: 5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines case HIDDEN: 5337b74a387bb3993387029859c2d9d051c41c724eStephen Hines mcld::outs() << "HIDDEN ( "; 5437b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines case PROVIDE: 5637b74a387bb3993387029859c2d9d051c41c724eStephen Hines mcld::outs() << "PROVIDE ( "; 5737b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines case PROVIDE_HIDDEN: 5937b74a387bb3993387029859c2d9d051c41c724eStephen Hines mcld::outs() << "PROVIDE_HIDDEN ( "; 6037b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 6137b74a387bb3993387029859c2d9d051c41c724eStephen Hines default: 6237b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines } 64f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines m_Symbol.dump(); 66f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 67f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines mcld::outs() << " = "; 68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines m_RpnExpr.dump(); 70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines if (type() != DEFAULT) 72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines mcld::outs() << " )"; 73f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines mcld::outs() << ";\n"; 75f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines} 76f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 7737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Assignment::activate(Module& pModule) { 78f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines bool isLhsDot = m_Symbol.isDot(); 79f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines LinkerScript& script = pModule.getScript(); 80f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines switch (m_Level) { 8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines case OUTSIDE_SECTIONS: 8237b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(!isLhsDot); 8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines script.assignments().push_back( 8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines std::make_pair(reinterpret_cast<LDSymbol*>(NULL), *this)); 8537b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 8637b74a387bb3993387029859c2d9d051c41c724eStephen Hines 8737b74a387bb3993387029859c2d9d051c41c724eStephen Hines case OUTPUT_SECTION: { 8837b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool hasDotInRhs = m_RpnExpr.hasDot(); 8937b74a387bb3993387029859c2d9d051c41c724eStephen Hines SectionMap::reference out = script.sectionMap().back(); 9037b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (hasDotInRhs) { 9137b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!isLhsDot && out->dotAssignments().empty()) { 9237b74a387bb3993387029859c2d9d051c41c724eStephen Hines // . = ADDR ( `prev_output_sect' ) + SIZEOF ( `prev_output_sect' ) 9337b74a387bb3993387029859c2d9d051c41c724eStephen Hines SectionMap::iterator prev = 9437b74a387bb3993387029859c2d9d051c41c724eStephen Hines script.sectionMap().begin() + script.sectionMap().size() - 2; 9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines Assignment assign(OUTPUT_SECTION, 9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines HIDDEN, 9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines *SymOperand::create("."), 9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines *RpnExpr::buildHelperExpr(prev)); 9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines out->dotAssignments().push_back(assign); 10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 101f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 10237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!out->dotAssignments().empty()) { 10337b74a387bb3993387029859c2d9d051c41c724eStephen Hines Assignment& prevDotAssign = out->dotAssignments().back(); 10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If this is the 1st explicit assignment that includes both lhs dot 10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines // and 10637b74a387bb3993387029859c2d9d051c41c724eStephen Hines // rhs dot, then because of possible orphan sections, we are unable to 10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines // substitute the rhs dot now. 10837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!isLhsDot || prevDotAssign.type() == DEFAULT) { 10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end(); 11037b74a387bb3993387029859c2d9d051c41c724eStephen Hines it != ie; 11137b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++it) { 11237b74a387bb3993387029859c2d9d051c41c724eStephen Hines // substitute the rhs dot with the appropriate helper expr 11337b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((*it)->kind() == ExprToken::OPERAND && 11437b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::cast<Operand>(*it)->isDot()) { 11537b74a387bb3993387029859c2d9d051c41c724eStephen Hines *it = &(prevDotAssign.symbol()); 11637b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 11737b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // for each expression token 11837b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 119f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines } 120f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines } 121f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 12237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (isLhsDot) { 12337b74a387bb3993387029859c2d9d051c41c724eStephen Hines out->dotAssignments().push_back(*this); 12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 12537b74a387bb3993387029859c2d9d051c41c724eStephen Hines script.assignments().push_back( 12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines std::make_pair(reinterpret_cast<LDSymbol*>(NULL), *this)); 12737b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 12837b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 129f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines } 130f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines case INPUT_SECTION: { 13237b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool hasDotInRhs = m_RpnExpr.hasDot(); 13337b74a387bb3993387029859c2d9d051c41c724eStephen Hines SectionMap::Output::reference in = script.sectionMap().back()->back(); 13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (hasDotInRhs) { 13537b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (in->dotAssignments().empty()) { 13637b74a387bb3993387029859c2d9d051c41c724eStephen Hines // . = `frag' 13737b74a387bb3993387029859c2d9d051c41c724eStephen Hines RpnExpr* expr = RpnExpr::buildHelperExpr( 13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines in->getSection()->getSectionData()->front()); 13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines Assignment assign( 14037b74a387bb3993387029859c2d9d051c41c724eStephen Hines INPUT_SECTION, HIDDEN, *SymOperand::create("."), *expr); 14137b74a387bb3993387029859c2d9d051c41c724eStephen Hines in->dotAssignments().push_back( 14237b74a387bb3993387029859c2d9d051c41c724eStephen Hines std::make_pair(reinterpret_cast<Fragment*>(NULL), assign)); 14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 144f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines Assignment& prevDotAssign = in->dotAssignments().back().second; 14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end(); 14737b74a387bb3993387029859c2d9d051c41c724eStephen Hines it != ie; 14837b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++it) { 14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines // substitute the rhs dot with the appropriate helper expr 15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((*it)->kind() == ExprToken::OPERAND && 15137b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::cast<Operand>(*it)->isDot()) { 15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines *it = &(prevDotAssign.symbol()); 15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 15437b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end of for 155f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines } 156f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 15737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (isLhsDot) { 15837b74a387bb3993387029859c2d9d051c41c724eStephen Hines in->dotAssignments().push_back(std::make_pair( 15937b74a387bb3993387029859c2d9d051c41c724eStephen Hines in->getSection()->getSectionData()->front().getNextNode(), *this)); 16037b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 16137b74a387bb3993387029859c2d9d051c41c724eStephen Hines script.assignments().push_back( 16237b74a387bb3993387029859c2d9d051c41c724eStephen Hines std::make_pair(reinterpret_cast<LDSymbol*>(NULL), *this)); 16337b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 16437b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 165f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines } 16637b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end of switch 167f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines} 168f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 16937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool Assignment::assign(RpnEvaluator& pEvaluator) { 170f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines uint64_t result = 0; 171f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines bool success = pEvaluator.eval(m_RpnExpr, result); 172f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines if (success) 173f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines m_Symbol.setValue(result); 174f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines return success; 175f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines} 17637b74a387bb3993387029859c2d9d051c41c724eStephen Hines 17737b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 178