blob: 1df7817e74a4ece68321ba2bcf42f16ac056df15 [file] [log] [blame]
Stephen Hinesf33f6de2014-02-14 18:00:16 -08001//===- 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//===----------------------------------------------------------------------===//
Stephen Hines37b74a32014-11-26 18:48:20 -08009#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
Stephen Hinesf33f6de2014-02-14 18:00:16 -080021#include <llvm/Support/Casting.h>
Stephen Hines37b74a32014-11-26 18:48:20 -080022
Stephen Hinesf33f6de2014-02-14 18:00:16 -080023#include <cassert>
24
Stephen Hines37b74a32014-11-26 18:48:20 -080025namespace mcld {
Stephen Hinesf33f6de2014-02-14 18:00:16 -080026
27//===----------------------------------------------------------------------===//
28// Assignment
29//===----------------------------------------------------------------------===//
30Assignment::Assignment(Level pLevel,
31 Type pType,
32 SymOperand& pSymbol,
33 RpnExpr& pRpnExpr)
Stephen Hines37b74a32014-11-26 18:48:20 -080034 : ScriptCommand(ScriptCommand::ASSIGNMENT),
35 m_Level(pLevel),
36 m_Type(pType),
37 m_Symbol(pSymbol),
38 m_RpnExpr(pRpnExpr) {
Stephen Hinesf33f6de2014-02-14 18:00:16 -080039}
40
Stephen Hines37b74a32014-11-26 18:48:20 -080041Assignment::~Assignment() {
Stephen Hinesf33f6de2014-02-14 18:00:16 -080042}
43
Stephen Hines37b74a32014-11-26 18:48:20 -080044Assignment& Assignment::operator=(const Assignment& pAssignment) {
Stephen Hinesf33f6de2014-02-14 18:00:16 -080045 return *this;
46}
47
Stephen Hines37b74a32014-11-26 18:48:20 -080048void Assignment::dump() const {
Stephen Hinesf33f6de2014-02-14 18:00:16 -080049 switch (type()) {
Stephen Hines37b74a32014-11-26 18:48:20 -080050 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;
Stephen Hinesf33f6de2014-02-14 18:00:16 -080063 }
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
Stephen Hines37b74a32014-11-26 18:48:20 -080077void Assignment::activate(Module& pModule) {
Stephen Hinesf33f6de2014-02-14 18:00:16 -080078 bool isLhsDot = m_Symbol.isDot();
79 LinkerScript& script = pModule.getScript();
80 switch (m_Level) {
Stephen Hines37b74a32014-11-26 18:48:20 -080081 case OUTSIDE_SECTIONS:
82 assert(!isLhsDot);
Colin Cross662e4772022-01-13 15:01:43 -080083 script.assignments().push_back(std::make_pair(nullptr, *this));
Stephen Hines37b74a32014-11-26 18:48:20 -080084 break;
Stephen Hinesf33f6de2014-02-14 18:00:16 -080085
Stephen Hines37b74a32014-11-26 18:48:20 -080086 case OUTPUT_SECTION: {
87 bool hasDotInRhs = m_RpnExpr.hasDot();
88 SectionMap::reference out = script.sectionMap().back();
89 if (hasDotInRhs) {
90 if (!isLhsDot && out->dotAssignments().empty()) {
91 // . = ADDR ( `prev_output_sect' ) + SIZEOF ( `prev_output_sect' )
92 SectionMap::iterator prev =
93 script.sectionMap().begin() + script.sectionMap().size() - 2;
94 Assignment assign(OUTPUT_SECTION,
95 HIDDEN,
96 *SymOperand::create("."),
97 *RpnExpr::buildHelperExpr(prev));
98 out->dotAssignments().push_back(assign);
99 }
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800100
Stephen Hines37b74a32014-11-26 18:48:20 -0800101 if (!out->dotAssignments().empty()) {
102 Assignment& prevDotAssign = out->dotAssignments().back();
103 // If this is the 1st explicit assignment that includes both lhs dot
104 // and
105 // rhs dot, then because of possible orphan sections, we are unable to
106 // substitute the rhs dot now.
107 if (!isLhsDot || prevDotAssign.type() == DEFAULT) {
108 for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
109 it != ie;
110 ++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 }
116 } // for each expression token
117 }
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800118 }
119 }
Stephen Hines37b74a32014-11-26 18:48:20 -0800120
121 if (isLhsDot) {
122 out->dotAssignments().push_back(*this);
123 } else {
Colin Cross662e4772022-01-13 15:01:43 -0800124 script.assignments().push_back(std::make_pair(nullptr, *this));
Stephen Hines37b74a32014-11-26 18:48:20 -0800125 }
126 break;
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800127 }
128
Stephen Hines37b74a32014-11-26 18:48:20 -0800129 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 = RpnExpr::buildHelperExpr(
136 in->getSection()->getSectionData()->front());
137 Assignment assign(
138 INPUT_SECTION, HIDDEN, *SymOperand::create("."), *expr);
Colin Cross662e4772022-01-13 15:01:43 -0800139 in->dotAssignments().push_back(std::make_pair(nullptr, assign));
Stephen Hines37b74a32014-11-26 18:48:20 -0800140 }
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800141
Stephen Hines37b74a32014-11-26 18:48:20 -0800142 Assignment& prevDotAssign = in->dotAssignments().back().second;
143 for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
144 it != ie;
145 ++it) {
146 // substitute the rhs dot with the appropriate helper expr
147 if ((*it)->kind() == ExprToken::OPERAND &&
148 llvm::cast<Operand>(*it)->isDot()) {
149 *it = &(prevDotAssign.symbol());
150 }
151 } // end of for
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800152 }
153
Stephen Hines37b74a32014-11-26 18:48:20 -0800154 if (isLhsDot) {
155 in->dotAssignments().push_back(std::make_pair(
156 in->getSection()->getSectionData()->front().getNextNode(), *this));
157 } else {
Colin Cross662e4772022-01-13 15:01:43 -0800158 script.assignments().push_back(std::make_pair(nullptr, *this));
Stephen Hines37b74a32014-11-26 18:48:20 -0800159 }
160 break;
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800161 }
Stephen Hines37b74a32014-11-26 18:48:20 -0800162 } // end of switch
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800163}
164
Stephen Hines37b74a32014-11-26 18:48:20 -0800165bool Assignment::assign(RpnEvaluator& pEvaluator) {
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800166 uint64_t result = 0;
167 bool success = pEvaluator.eval(m_RpnExpr, result);
168 if (success)
169 m_Symbol.setValue(result);
170 return success;
171}
Stephen Hines37b74a32014-11-26 18:48:20 -0800172
173} // namespace mcld