LLVM  9.0.0svn
RISCVMCExpr.cpp
Go to the documentation of this file.
1 //===-- RISCVMCExpr.cpp - RISCV specific MC expression classes ------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the implementation of the assembly expression modifiers
10 // accepted by the RISCV architecture (e.g. ":lo12:", ":gottprel_g1:", ...).
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "RISCV.h"
15 #include "RISCVMCExpr.h"
16 #include "RISCVFixupKinds.h"
17 #include "llvm/MC/MCAssembler.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCStreamer.h"
20 #include "llvm/MC/MCSymbolELF.h"
21 #include "llvm/MC/MCValue.h"
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "riscvmcexpr"
27 
29  MCContext &Ctx) {
30  return new (Ctx) RISCVMCExpr(Expr, Kind);
31 }
32 
33 void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
34  bool HasVariant =
35  ((getKind() != VK_RISCV_None) && (getKind() != VK_RISCV_CALL));
36  if (HasVariant)
37  OS << '%' << getVariantKindName(getKind()) << '(';
38  Expr->print(OS, MAI);
39  if (HasVariant)
40  OS << ')';
41 }
42 
44  MCValue AUIPCLoc;
45  if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr))
46  return nullptr;
47 
48  const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA();
49  if (!AUIPCSRE)
50  return nullptr;
51 
52  const auto *DF =
53  dyn_cast_or_null<MCDataFragment>(AUIPCSRE->findAssociatedFragment());
54  if (!DF)
55  return nullptr;
56 
57  const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol();
58  for (const MCFixup &F : DF->getFixups()) {
59  if (F.getOffset() != AUIPCSymbol->getOffset())
60  continue;
61 
62  switch ((unsigned)F.getKind()) {
63  default:
64  continue;
67  return &F;
68  }
69  }
70 
71  return nullptr;
72 }
73 
74 bool RISCVMCExpr::evaluatePCRelLo(MCValue &Res, const MCAsmLayout *Layout,
75  const MCFixup *Fixup) const {
76  // VK_RISCV_PCREL_LO has to be handled specially. The MCExpr inside is
77  // actually the location of a auipc instruction with a VK_RISCV_PCREL_HI fixup
78  // pointing to the real target. We need to generate an MCValue in the form of
79  // (<real target> + <offset from this fixup to the auipc fixup>). The Fixup
80  // is pcrel relative to the VK_RISCV_PCREL_LO fixup, so we need to add the
81  // offset to the VK_RISCV_PCREL_HI Fixup from VK_RISCV_PCREL_LO to correct.
82  MCValue AUIPCLoc;
83  if (!getSubExpr()->evaluateAsValue(AUIPCLoc, *Layout))
84  return false;
85 
86  const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA();
87  // Don't try to evaluate %pcrel_hi/%pcrel_lo pairs that cross fragment
88  // boundries.
89  if (!AUIPCSRE ||
91  return false;
92 
93  const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol();
94  if (!AUIPCSymbol)
95  return false;
96 
97  const MCFixup *TargetFixup = getPCRelHiFixup();
98  if (!TargetFixup)
99  return false;
100 
101  if ((unsigned)TargetFixup->getKind() != RISCV::fixup_riscv_pcrel_hi20)
102  return false;
103 
104  MCValue Target;
105  if (!TargetFixup->getValue()->evaluateAsValue(Target, *Layout))
106  return false;
107 
108  if (!Target.getSymA() || !Target.getSymA()->getSymbol().isInSection())
109  return false;
110 
111  if (&Target.getSymA()->getSymbol().getSection() !=
113  return false;
114 
115  uint64_t AUIPCOffset = AUIPCSymbol->getOffset();
116 
117  Res = MCValue::get(Target.getSymA(), nullptr,
118  Target.getConstant() + (Fixup->getOffset() - AUIPCOffset));
119  return true;
120 }
121 
123  const MCAsmLayout *Layout,
124  const MCFixup *Fixup) const {
125  if (Kind == VK_RISCV_PCREL_LO && evaluatePCRelLo(Res, Layout, Fixup))
126  return true;
127 
128  if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
129  return false;
130 
131  // Some custom fixup types are not valid with symbol difference expressions
132  if (Res.getSymA() && Res.getSymB()) {
133  switch (getKind()) {
134  default:
135  return true;
136  case VK_RISCV_LO:
137  case VK_RISCV_HI:
138  case VK_RISCV_PCREL_LO:
139  case VK_RISCV_PCREL_HI:
140  case VK_RISCV_GOT_HI:
141  return false;
142  }
143  }
144 
145  return true;
146 }
147 
148 void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
149  Streamer.visitUsedExpr(*getSubExpr());
150 }
151 
154  .Case("lo", VK_RISCV_LO)
155  .Case("hi", VK_RISCV_HI)
156  .Case("pcrel_lo", VK_RISCV_PCREL_LO)
157  .Case("pcrel_hi", VK_RISCV_PCREL_HI)
158  .Case("got_pcrel_hi", VK_RISCV_GOT_HI)
160 }
161 
163  switch (Kind) {
164  default:
165  llvm_unreachable("Invalid ELF symbol kind");
166  case VK_RISCV_LO:
167  return "lo";
168  case VK_RISCV_HI:
169  return "hi";
170  case VK_RISCV_PCREL_LO:
171  return "pcrel_lo";
172  case VK_RISCV_PCREL_HI:
173  return "pcrel_hi";
174  case VK_RISCV_GOT_HI:
175  return "got_pcrel_hi";
176  }
177 }
178 
179 bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
180  MCValue Value;
181 
182  if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
183  Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_CALL)
184  return false;
185 
186  if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
187  return false;
188 
189  if (!Value.isAbsolute())
190  return false;
191 
192  Res = evaluateAsInt64(Value.getConstant());
193  return true;
194 }
195 
196 int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
197  switch (Kind) {
198  default:
199  llvm_unreachable("Invalid kind");
200  case VK_RISCV_LO:
201  return SignExtend64<12>(Value);
202  case VK_RISCV_HI:
203  // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
204  return ((Value + 0x800) >> 12) & 0xfffff;
205  }
206 }
bool evaluateAsConstant(int64_t &Res) const
This class represents lattice values for constants.
Definition: AllocatorList.h:23
This represents an "assembler immediate".
Definition: MCValue.h:39
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override
Definition: RISCVMCExpr.cpp:33
VariantKind getKind() const
Definition: RISCVMCExpr.h:52
bool isAbsolute() const
Is this an absolute (as opposed to relocatable) value.
Definition: MCValue.h:52
F(f)
static StringRef getVariantKindName(VariantKind Kind)
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:67
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:73
int64_t getConstant() const
Definition: MCValue.h:46
const MCSymbolRefExpr * getSymB() const
Definition: MCValue.h:48
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute)...
Definition: MCSymbol.h:251
LLVM_NODISCARD R Default(T Value)
Definition: StringSwitch.h:181
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:165
Context object for machine code objects.
Definition: MCContext.h:62
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Definition: MCExpr.cpp:646
const MCFixup * getPCRelHiFixup() const
Get the corresponding PC-relative HI fixup that a VK_RISCV_PCREL_LO points to.
Definition: RISCVMCExpr.cpp:43
const MCExpr * getSubExpr() const
Definition: RISCVMCExpr.h:54
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:55
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:42
Streaming machine code generation interface.
Definition: MCStreamer.h:188
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:41
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:47
uint64_t getOffset() const
Definition: MCSymbol.h:320
uint32_t getOffset() const
Definition: MCFixup.h:124
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
PowerPC TLS Dynamic Call Fixup
const MCSymbol & getSymbol() const
Definition: MCExpr.h:335
MCFragment * findAssociatedFragment() const
Find the "associated section" for this expression, which is currently defined as the absolute section...
Definition: MCExpr.cpp:866
MCFragment * findAssociatedFragment() const override
Definition: RISCVMCExpr.h:67
void visitUsedExpr(const MCExpr &Expr)
Definition: MCStreamer.cpp:929
MCSection * getParent() const
Definition: MCFragment.h:98
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
Definition: MCSymbol.h:266
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const override
static VariantKind getVariantKindForName(StringRef name)
static MCValue get(const MCSymbolRefExpr *SymA, const MCSymbolRefExpr *SymB=nullptr, int64_t Val=0, uint32_t RefKind=0)
Definition: MCValue.h:62
bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const
Try to evaluate the expression to the form (a - b + constant) where neither a nor b are variables...
Definition: MCExpr.cpp:654
const unsigned Kind
LLVM Value Representation.
Definition: Value.h:72
static const char * name
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
const MCExpr * getValue() const
Definition: MCFixup.h:127
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Target specific expression.
Definition: MCExpr.h:42
void visitUsedExpr(MCStreamer &Streamer) const override
static const RISCVMCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
Definition: RISCVMCExpr.cpp:28
MCFixupKind getKind() const
Definition: MCFixup.h:122