You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
5.3 KiB
178 lines
5.3 KiB
4 months ago
|
//===- Assignment.cpp -----------------------------------------------------===//
|
||
|
//
|
||
|
// The MCLinker Project
|
||
|
//
|
||
|
// This file is distributed under the University of Illinois Open Source
|
||
|
// License. See LICENSE.TXT for details.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
#include "mcld/Script/Assignment.h"
|
||
|
|
||
|
#include "mcld/LinkerScript.h"
|
||
|
#include "mcld/Module.h"
|
||
|
#include "mcld/LD/LDSection.h"
|
||
|
#include "mcld/LD/SectionData.h"
|
||
|
#include "mcld/Script/Operand.h"
|
||
|
#include "mcld/Script/Operator.h"
|
||
|
#include "mcld/Script/RpnEvaluator.h"
|
||
|
#include "mcld/Script/RpnExpr.h"
|
||
|
#include "mcld/Support/raw_ostream.h"
|
||
|
|
||
|
#include <llvm/Support/Casting.h>
|
||
|
|
||
|
#include <cassert>
|
||
|
|
||
|
namespace mcld {
|
||
|
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
// Assignment
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
Assignment::Assignment(Level pLevel,
|
||
|
Type pType,
|
||
|
SymOperand& pSymbol,
|
||
|
RpnExpr& pRpnExpr)
|
||
|
: ScriptCommand(ScriptCommand::ASSIGNMENT),
|
||
|
m_Level(pLevel),
|
||
|
m_Type(pType),
|
||
|
m_Symbol(pSymbol),
|
||
|
m_RpnExpr(pRpnExpr) {
|
||
|
}
|
||
|
|
||
|
Assignment::~Assignment() {
|
||
|
}
|
||
|
|
||
|
Assignment& Assignment::operator=(const Assignment& pAssignment) {
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
void Assignment::dump() const {
|
||
|
switch (type()) {
|
||
|
case DEFAULT:
|
||
|
break;
|
||
|
case HIDDEN:
|
||
|
mcld::outs() << "HIDDEN ( ";
|
||
|
break;
|
||
|
case PROVIDE:
|
||
|
mcld::outs() << "PROVIDE ( ";
|
||
|
break;
|
||
|
case PROVIDE_HIDDEN:
|
||
|
mcld::outs() << "PROVIDE_HIDDEN ( ";
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
m_Symbol.dump();
|
||
|
|
||
|
mcld::outs() << " = ";
|
||
|
|
||
|
m_RpnExpr.dump();
|
||
|
|
||
|
if (type() != DEFAULT)
|
||
|
mcld::outs() << " )";
|
||
|
|
||
|
mcld::outs() << ";\n";
|
||
|
}
|
||
|
|
||
|
void Assignment::activate(Module& pModule) {
|
||
|
bool isLhsDot = m_Symbol.isDot();
|
||
|
LinkerScript& script = pModule.getScript();
|
||
|
switch (m_Level) {
|
||
|
case OUTSIDE_SECTIONS:
|
||
|
assert(!isLhsDot);
|
||
|
script.assignments().push_back(
|
||
|
std::make_pair(reinterpret_cast<LDSymbol*>(NULL), *this));
|
||
|
break;
|
||
|
|
||
|
case OUTPUT_SECTION: {
|
||
|
bool hasDotInRhs = m_RpnExpr.hasDot();
|
||
|
SectionMap::reference out = script.sectionMap().back();
|
||
|
if (hasDotInRhs) {
|
||
|
if (!isLhsDot && out->dotAssignments().empty()) {
|
||
|
// . = ADDR ( `prev_output_sect' ) + SIZEOF ( `prev_output_sect' )
|
||
|
SectionMap::iterator prev =
|
||
|
script.sectionMap().begin() + script.sectionMap().size() - 2;
|
||
|
Assignment assign(OUTPUT_SECTION,
|
||
|
HIDDEN,
|
||
|
*SymOperand::create("."),
|
||
|
*RpnExpr::buildHelperExpr(prev));
|
||
|
out->dotAssignments().push_back(assign);
|
||
|
}
|
||
|
|
||
|
if (!out->dotAssignments().empty()) {
|
||
|
Assignment& prevDotAssign = out->dotAssignments().back();
|
||
|
// If this is the 1st explicit assignment that includes both lhs dot
|
||
|
// and
|
||
|
// rhs dot, then because of possible orphan sections, we are unable to
|
||
|
// substitute the rhs dot now.
|
||
|
if (!isLhsDot || prevDotAssign.type() == DEFAULT) {
|
||
|
for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
|
||
|
it != ie;
|
||
|
++it) {
|
||
|
// substitute the rhs dot with the appropriate helper expr
|
||
|
if ((*it)->kind() == ExprToken::OPERAND &&
|
||
|
llvm::cast<Operand>(*it)->isDot()) {
|
||
|
*it = &(prevDotAssign.symbol());
|
||
|
}
|
||
|
} // for each expression token
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (isLhsDot) {
|
||
|
out->dotAssignments().push_back(*this);
|
||
|
} else {
|
||
|
script.assignments().push_back(
|
||
|
std::make_pair(reinterpret_cast<LDSymbol*>(NULL), *this));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case INPUT_SECTION: {
|
||
|
bool hasDotInRhs = m_RpnExpr.hasDot();
|
||
|
SectionMap::Output::reference in = script.sectionMap().back()->back();
|
||
|
if (hasDotInRhs) {
|
||
|
if (in->dotAssignments().empty()) {
|
||
|
// . = `frag'
|
||
|
RpnExpr* expr = RpnExpr::buildHelperExpr(
|
||
|
in->getSection()->getSectionData()->front());
|
||
|
Assignment assign(
|
||
|
INPUT_SECTION, HIDDEN, *SymOperand::create("."), *expr);
|
||
|
in->dotAssignments().push_back(
|
||
|
std::make_pair(reinterpret_cast<Fragment*>(NULL), assign));
|
||
|
}
|
||
|
|
||
|
Assignment& prevDotAssign = in->dotAssignments().back().second;
|
||
|
for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
|
||
|
it != ie;
|
||
|
++it) {
|
||
|
// substitute the rhs dot with the appropriate helper expr
|
||
|
if ((*it)->kind() == ExprToken::OPERAND &&
|
||
|
llvm::cast<Operand>(*it)->isDot()) {
|
||
|
*it = &(prevDotAssign.symbol());
|
||
|
}
|
||
|
} // end of for
|
||
|
}
|
||
|
|
||
|
if (isLhsDot) {
|
||
|
in->dotAssignments().push_back(std::make_pair(
|
||
|
in->getSection()->getSectionData()->front().getNextNode(), *this));
|
||
|
} else {
|
||
|
script.assignments().push_back(
|
||
|
std::make_pair(reinterpret_cast<LDSymbol*>(NULL), *this));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
} // end of switch
|
||
|
}
|
||
|
|
||
|
bool Assignment::assign(RpnEvaluator& pEvaluator) {
|
||
|
uint64_t result = 0;
|
||
|
bool success = pEvaluator.eval(m_RpnExpr, result);
|
||
|
if (success)
|
||
|
m_Symbol.setValue(result);
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
} // namespace mcld
|