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//===----------------------------------------------------------------------===//
9f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/Assignment.h>
10f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/RpnExpr.h>
11f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/Operand.h>
12f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/Operator.h>
13f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/RpnEvaluator.h>
14f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Support/raw_ostream.h>
15f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/LinkerScript.h>
16f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/LD/LDSection.h>
17f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/LD/SectionData.h>
18f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Module.h>
19f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/Casting.h>
20f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <cassert>
21f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
22f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesusing namespace mcld;
23f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
24f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
25f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// Assignment
26f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
27f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesAssignment::Assignment(Level pLevel,
28f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                       Type pType,
29f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                       SymOperand& pSymbol,
30f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                       RpnExpr& pRpnExpr)
31f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  : ScriptCommand(ScriptCommand::ASSIGNMENT),
32f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_Level(pLevel),
33f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_Type(pType),
34f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_Symbol(pSymbol),
35f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_RpnExpr(pRpnExpr)
36f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
37f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
38f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
39f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesAssignment::~Assignment()
40f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
41f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
42f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
43f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesAssignment& Assignment::operator=(const Assignment& pAssignment)
44f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
45f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return *this;
46f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
48f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesvoid Assignment::dump() const
49f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
50f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  switch (type()) {
51f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  case DEFAULT:
52f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    break;
53f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  case HIDDEN:
54f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    mcld::outs() << "HIDDEN ( ";
55f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    break;
56f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  case PROVIDE:
57f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    mcld::outs() << "PROVIDE ( ";
58f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    break;
59f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  case PROVIDE_HIDDEN:
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    mcld::outs() << "PROVIDE_HIDDEN ( ";
61f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    break;
62f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  default:
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    break;
64f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
66f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_Symbol.dump();
67f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  mcld::outs() << " = ";
69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_RpnExpr.dump();
71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (type() != DEFAULT)
73f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    mcld::outs() << " )";
74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
75f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  mcld::outs() << ";\n";
76f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
77f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
78f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesvoid Assignment::activate(Module& pModule)
79f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
80f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  bool isLhsDot = m_Symbol.isDot();
81f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  LinkerScript& script = pModule.getScript();
82f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  switch (m_Level) {
83f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  case OUTSIDE_SECTIONS:
84f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    assert(!isLhsDot);
85f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    script.assignments().push_back(std::make_pair((LDSymbol*)NULL, *this));
86f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    break;
87f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
88f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  case OUTPUT_SECTION: {
89f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    bool hasDotInRhs = m_RpnExpr.hasDot();
90f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    SectionMap::reference out = script.sectionMap().back();
91f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (hasDotInRhs) {
92f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (!isLhsDot && out->dotAssignments().empty()) {
93f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // . = ADDR ( `prev_output_sect' ) + SIZEOF ( `prev_output_sect' )
94f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        SectionMap::iterator prev = script.sectionMap().begin() +
95f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                    script.sectionMap().size() - 2;
96f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        Assignment assign(OUTPUT_SECTION,
97f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                          HIDDEN,
98f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                          *SymOperand::create("."),
99f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                          *RpnExpr::buildHelperExpr(prev));
100f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        out->dotAssignments().push_back(assign);
101f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
102f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
103f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (!out->dotAssignments().empty()) {
104f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        Assignment& prevDotAssign = out->dotAssignments().back();
105f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // If this is the 1st explicit assignment that includes both lhs dot and
106f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // rhs dot, then because of possible orphan sections, we are unable to
107f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // substitute the rhs dot now.
108f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (!isLhsDot || prevDotAssign.type() == DEFAULT) {
109f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
110f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            it != ie; ++it) {
111f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            // substitute the rhs dot with the appropriate helper expr
112f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            if ((*it)->kind() == ExprToken::OPERAND &&
113f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                llvm::cast<Operand>(*it)->isDot())
114f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines              *it = &(prevDotAssign.symbol());
115f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          } // for each expression token
116f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        }
117f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
118f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
119f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
120f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (isLhsDot) {
121f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      out->dotAssignments().push_back(*this);
122f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    } else {
123f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      script.assignments().push_back(std::make_pair((LDSymbol*)NULL, *this));
124f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
125f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
126f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    break;
127f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
128f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
129f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  case INPUT_SECTION: {
130f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    bool hasDotInRhs = m_RpnExpr.hasDot();
131f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    SectionMap::Output::reference in = script.sectionMap().back()->back();
132f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (hasDotInRhs) {
133f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (in->dotAssignments().empty()) {
134f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // . = `frag'
135f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        RpnExpr* expr =
136f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          RpnExpr::buildHelperExpr(in->getSection()->getSectionData()->front());
137f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        Assignment assign(INPUT_SECTION,
138f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                          HIDDEN,
139f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                          *SymOperand::create("."),
140f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                          *expr);
141f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        in->dotAssignments().push_back(std::make_pair((Fragment*)NULL, assign));
142f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
143f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
144f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      Assignment& prevDotAssign = in->dotAssignments().back().second;
145f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
146f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        it != ie; ++it) {
147f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // substitute the rhs dot with the appropriate helper expr
148f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if ((*it)->kind() == ExprToken::OPERAND &&
149f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            llvm::cast<Operand>(*it)->isDot())
150f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          *it = &(prevDotAssign.symbol());
151f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      } // end of for
152f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
153f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
154f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (isLhsDot) {
155f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      in->dotAssignments().push_back(
156f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        std::make_pair(in->getSection()->getSectionData()->front().getNextNode(),
157f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                       *this));
158f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    } else {
159f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      script.assignments().push_back(std::make_pair((LDSymbol*)NULL, *this));
160f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
161f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
162f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    break;
163f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
164f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
165f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  } // end of switch
166f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
167f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
168f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool Assignment::assign(RpnEvaluator& pEvaluator)
169f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
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}
176