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 //===----------------------------------------------------------------------===//
Assignment(Level pLevel,Type pType,SymOperand & pSymbol,RpnExpr & pRpnExpr)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
~Assignment()39 Assignment::~Assignment()
40 {
41 }
42
operator =(const Assignment & pAssignment)43 Assignment& Assignment::operator=(const Assignment& pAssignment)
44 {
45 return *this;
46 }
47
dump() const48 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
activate(Module & pModule)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
assign(RpnEvaluator & pEvaluator)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