LLVM  15.0.0git
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 "RISCVMCExpr.h"
16 #include "RISCVFixupKinds.h"
17 #include "llvm/BinaryFormat/ELF.h"
18 #include "llvm/MC/MCAsmLayout.h"
19 #include "llvm/MC/MCAssembler.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCStreamer.h"
22 #include "llvm/MC/MCSymbolELF.h"
23 #include "llvm/MC/MCValue.h"
24 #include "llvm/Support/Casting.h"
26 
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "riscvmcexpr"
30 
32  MCContext &Ctx) {
33  return new (Ctx) RISCVMCExpr(Expr, Kind);
34 }
35 
36 void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
37  VariantKind Kind = getKind();
38  bool HasVariant = ((Kind != VK_RISCV_None) && (Kind != VK_RISCV_CALL) &&
39  (Kind != VK_RISCV_CALL_PLT));
40 
41  if (HasVariant)
42  OS << '%' << getVariantKindName(getKind()) << '(';
43  Expr->print(OS, MAI);
44  if (Kind == VK_RISCV_CALL_PLT)
45  OS << "@plt";
46  if (HasVariant)
47  OS << ')';
48 }
49 
50 const MCFixup *RISCVMCExpr::getPCRelHiFixup(const MCFragment **DFOut) const {
51  MCValue AUIPCLoc;
52  if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr))
53  return nullptr;
54 
55  const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA();
56  if (!AUIPCSRE)
57  return nullptr;
58 
59  const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol();
60  const auto *DF = dyn_cast_or_null<MCDataFragment>(AUIPCSymbol->getFragment());
61 
62  if (!DF)
63  return nullptr;
64 
65  uint64_t Offset = AUIPCSymbol->getOffset();
66  if (DF->getContents().size() == Offset) {
67  DF = dyn_cast_or_null<MCDataFragment>(DF->getNextNode());
68  if (!DF)
69  return nullptr;
70  Offset = 0;
71  }
72 
73  for (const MCFixup &F : DF->getFixups()) {
74  if (F.getOffset() != Offset)
75  continue;
76 
77  switch ((unsigned)F.getKind()) {
78  default:
79  continue;
84  if (DFOut)
85  *DFOut = DF;
86  return &F;
87  }
88  }
89 
90  return nullptr;
91 }
92 
94  const MCAsmLayout *Layout,
95  const MCFixup *Fixup) const {
96  // Explicitly drop the layout and assembler to prevent any symbolic folding in
97  // the expression handling. This is required to preserve symbolic difference
98  // expressions to emit the paired relocations.
99  if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr))
100  return false;
101 
102  Res =
103  MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
104  // Custom fixup types are not valid with symbol difference expressions.
105  return Res.getSymB() ? getKind() == VK_RISCV_None : true;
106 }
107 
108 void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
109  Streamer.visitUsedExpr(*getSubExpr());
110 }
111 
114  .Case("lo", VK_RISCV_LO)
115  .Case("hi", VK_RISCV_HI)
116  .Case("pcrel_lo", VK_RISCV_PCREL_LO)
117  .Case("pcrel_hi", VK_RISCV_PCREL_HI)
118  .Case("got_pcrel_hi", VK_RISCV_GOT_HI)
119  .Case("tprel_lo", VK_RISCV_TPREL_LO)
120  .Case("tprel_hi", VK_RISCV_TPREL_HI)
121  .Case("tprel_add", VK_RISCV_TPREL_ADD)
122  .Case("tls_ie_pcrel_hi", VK_RISCV_TLS_GOT_HI)
123  .Case("tls_gd_pcrel_hi", VK_RISCV_TLS_GD_HI)
125 }
126 
128  switch (Kind) {
129  case VK_RISCV_Invalid:
130  case VK_RISCV_None:
131  llvm_unreachable("Invalid ELF symbol kind");
132  case VK_RISCV_LO:
133  return "lo";
134  case VK_RISCV_HI:
135  return "hi";
136  case VK_RISCV_PCREL_LO:
137  return "pcrel_lo";
138  case VK_RISCV_PCREL_HI:
139  return "pcrel_hi";
140  case VK_RISCV_GOT_HI:
141  return "got_pcrel_hi";
142  case VK_RISCV_TPREL_LO:
143  return "tprel_lo";
144  case VK_RISCV_TPREL_HI:
145  return "tprel_hi";
146  case VK_RISCV_TPREL_ADD:
147  return "tprel_add";
148  case VK_RISCV_TLS_GOT_HI:
149  return "tls_ie_pcrel_hi";
150  case VK_RISCV_TLS_GD_HI:
151  return "tls_gd_pcrel_hi";
152  case VK_RISCV_CALL:
153  return "call";
154  case VK_RISCV_CALL_PLT:
155  return "call_plt";
156  case VK_RISCV_32_PCREL:
157  return "32_pcrel";
158  }
159  llvm_unreachable("Invalid ELF symbol kind");
160 }
161 
163  switch (Expr->getKind()) {
164  case MCExpr::Target:
165  llvm_unreachable("Can't handle nested target expression");
166  break;
167  case MCExpr::Constant:
168  break;
169 
170  case MCExpr::Binary: {
171  const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
174  break;
175  }
176 
177  case MCExpr::SymbolRef: {
178  // We're known to be under a TLS fixup, so any symbol should be
179  // modified. There should be only one.
180  const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
181  cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
182  break;
183  }
184 
185  case MCExpr::Unary:
186  fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
187  break;
188  }
189 }
190 
192  switch (getKind()) {
193  default:
194  return;
195  case VK_RISCV_TPREL_HI:
196  case VK_RISCV_TLS_GOT_HI:
197  case VK_RISCV_TLS_GD_HI:
198  break;
199  }
200 
202 }
203 
204 bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
205  MCValue Value;
206 
207  if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
208  Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI ||
209  Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD ||
210  Kind == VK_RISCV_TLS_GOT_HI || Kind == VK_RISCV_TLS_GD_HI ||
211  Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT)
212  return false;
213 
214  if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
215  return false;
216 
217  if (!Value.isAbsolute())
218  return false;
219 
220  Res = evaluateAsInt64(Value.getConstant());
221  return true;
222 }
223 
224 int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
225  switch (Kind) {
226  default:
227  llvm_unreachable("Invalid kind");
228  case VK_RISCV_LO:
229  return SignExtend64<12>(Value);
230  case VK_RISCV_HI:
231  // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
232  return ((Value + 0x800) >> 12) & 0xfffff;
233  }
234 }
llvm::StringSwitch::Case
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
llvm::RISCVMCExpr::VK_RISCV_Invalid
@ VK_RISCV_Invalid
Definition: RISCVMCExpr.h:40
llvm::MCStreamer::visitUsedExpr
void visitUsedExpr(const MCExpr &Expr)
Definition: MCStreamer.cpp:1063
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
llvm::RISCVMCExpr::printImpl
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override
Definition: RISCVMCExpr.cpp:36
llvm::RISCVMCExpr::VK_RISCV_TLS_GD_HI
@ VK_RISCV_TLS_GD_HI
Definition: RISCVMCExpr.h:36
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:74
llvm::StringSwitch::Default
LLVM_NODISCARD R Default(T Value)
Definition: StringSwitch.h:183
llvm::MCSymbol::getOffset
uint64_t getOffset() const
Definition: MCSymbol.h:320
llvm::RISCVMCExpr::VK_RISCV_TPREL_ADD
@ VK_RISCV_TPREL_ADD
Definition: RISCVMCExpr.h:34
llvm::MCAsmInfo
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:56
llvm::RISCVMCExpr::evaluateAsConstant
bool evaluateAsConstant(int64_t &Res) const
Definition: RISCVMCExpr.cpp:204
llvm::RISCV::fixup_riscv_tls_gd_hi20
@ fixup_riscv_tls_gd_hi20
Definition: RISCVFixupKinds.h:50
ErrorHandling.h
MCAssembler.h
fixELFSymbolsInTLSFixupsImpl
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm)
Definition: RISCVMCExpr.cpp:162
llvm::MCSymbol::getFragment
MCFragment * getFragment(bool SetUsed=true) const
Definition: MCSymbol.h:392
RISCVMCExpr.h
llvm::RISCVMCExpr::VK_RISCV_TPREL_LO
@ VK_RISCV_TPREL_LO
Definition: RISCVMCExpr.h:32
llvm::RISCVMCExpr::getVariantKindForName
static VariantKind getVariantKindForName(StringRef name)
Definition: RISCVMCExpr.cpp:112
llvm::ELF::STT_TLS
@ STT_TLS
Definition: ELF.h:1206
llvm::RISCVMCExpr::VK_RISCV_HI
@ VK_RISCV_HI
Definition: RISCVMCExpr.h:28
llvm::RISCVMCExpr::VK_RISCV_TPREL_HI
@ VK_RISCV_TPREL_HI
Definition: RISCVMCExpr.h:33
llvm::MCBinaryExpr
Binary assembler expressions.
Definition: MCExpr.h:481
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::MCExpr::evaluateAsRelocatable
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:749
llvm::RISCVMCExpr::VK_RISCV_TLS_GOT_HI
@ VK_RISCV_TLS_GOT_HI
Definition: RISCVMCExpr.h:35
llvm::RISCVMCExpr::VariantKind
VariantKind
Definition: RISCVMCExpr.h:25
llvm::MCFragment
Definition: MCFragment.h:30
llvm::MCStreamer
Streaming machine code generation interface.
Definition: MCStreamer.h:201
ELF.h
llvm::RISCVMCExpr::VK_RISCV_LO
@ VK_RISCV_LO
Definition: RISCVMCExpr.h:27
llvm::RISCV::fixup_riscv_tls_got_hi20
@ fixup_riscv_tls_got_hi20
Definition: RISCVFixupKinds.h:47
llvm::MCExpr::Target
@ Target
Target specific expression.
Definition: MCExpr.h:42
MCSymbolELF.h
MCContext.h
llvm::MCBinaryExpr::getRHS
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition: MCExpr.h:631
llvm::RISCV::fixup_riscv_got_hi20
@ fixup_riscv_got_hi20
Definition: RISCVFixupKinds.h:34
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::MCSymbolRefExpr::getSymbol
const MCSymbol & getSymbol() const
Definition: MCExpr.h:399
llvm::MCValue::getConstant
int64_t getConstant() const
Definition: MCValue.h:43
llvm::MCValue::getSymA
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:44
llvm::MCExpr::getKind
ExprKind getKind() const
Definition: MCExpr.h:81
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::MCExpr::Binary
@ Binary
Binary expressions.
Definition: MCExpr.h:38
DF
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
llvm::RISCVMCExpr::getSubExpr
const MCExpr * getSubExpr() const
Definition: RISCVMCExpr.h:58
llvm::RISCVMCExpr::VK_RISCV_None
@ VK_RISCV_None
Definition: RISCVMCExpr.h:26
llvm::RISCVMCExpr::create
static const RISCVMCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
Definition: RISCVMCExpr.cpp:31
RISCVAsmBackend.h
llvm::MCAssembler
Definition: MCAssembler.h:73
llvm::RISCVMCExpr::VK_RISCV_PCREL_HI
@ VK_RISCV_PCREL_HI
Definition: RISCVMCExpr.h:30
uint64_t
llvm::MCValue::get
static MCValue get(const MCSymbolRefExpr *SymA, const MCSymbolRefExpr *SymB=nullptr, int64_t Val=0, uint32_t RefKind=0)
Definition: MCValue.h:59
llvm::RISCVMCExpr::evaluateAsRelocatableImpl
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const override
Definition: RISCVMCExpr.cpp:93
llvm::RISCVMCExpr::visitUsedExpr
void visitUsedExpr(MCStreamer &Streamer) const override
Definition: RISCVMCExpr.cpp:108
llvm::RISCVMCExpr::VK_RISCV_PCREL_LO
@ VK_RISCV_PCREL_LO
Definition: RISCVMCExpr.h:29
llvm::RISCVMCExpr::VK_RISCV_GOT_HI
@ VK_RISCV_GOT_HI
Definition: RISCVMCExpr.h:31
llvm::MCSymbolRefExpr
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::RISCV::fixup_riscv_pcrel_hi20
@ fixup_riscv_pcrel_hi20
Definition: RISCVFixupKinds.h:26
llvm::RISCVMCExpr::fixELFSymbolsInTLSFixups
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override
Definition: RISCVMCExpr.cpp:191
MCAsmLayout.h
llvm::RISCVMCExpr::getKind
VariantKind getKind() const
Definition: RISCVMCExpr.h:56
name
static const char * name
Definition: SVEIntrinsicOpts.cpp:74
llvm::RISCVMCExpr::VK_RISCV_32_PCREL
@ VK_RISCV_32_PCREL
Definition: RISCVMCExpr.h:39
llvm::MCAsmLayout
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
Casting.h
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::RISCVMCExpr::getVariantKindName
static StringRef getVariantKindName(VariantKind Kind)
Definition: RISCVMCExpr.cpp:127
MCValue.h
llvm::MCExpr::print
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:41
llvm::RISCVMCExpr::VK_RISCV_CALL
@ VK_RISCV_CALL
Definition: RISCVMCExpr.h:37
llvm::MCExpr::SymbolRef
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:40
llvm::MCExpr::Unary
@ Unary
Unary expressions.
Definition: MCExpr.h:41
MCStreamer.h
llvm::MCExpr::Constant
@ Constant
Constant expressions.
Definition: MCExpr.h:39
llvm::StringSwitch
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
llvm::HexStyle::Asm
@ Asm
0ffh
Definition: MCInstPrinter.h:34
llvm::RISCVMCExpr::getPCRelHiFixup
const MCFixup * getPCRelHiFixup(const MCFragment **DFOut) const
Get the corresponding PC-relative HI fixup that a VK_RISCV_PCREL_LO points to, and optionally the fra...
Definition: RISCVMCExpr.cpp:50
llvm::MCValue
This represents an "assembler immediate".
Definition: MCValue.h:36
llvm::RISCVMCExpr::VK_RISCV_CALL_PLT
@ VK_RISCV_CALL_PLT
Definition: RISCVMCExpr.h:38
llvm::MCFixup
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
llvm::MCValue::getSymB
const MCSymbolRefExpr * getSymB() const
Definition: MCValue.h:45
llvm::MCBinaryExpr::getLHS
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition: MCExpr.h:628
RISCVFixupKinds.h
llvm::RISCVMCExpr
Definition: RISCVMCExpr.h:23