LLVM  14.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"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "riscvmcexpr"
29 
31  MCContext &Ctx) {
32  return new (Ctx) RISCVMCExpr(Expr, Kind);
33 }
34 
35 void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
36  VariantKind Kind = getKind();
37  bool HasVariant = ((Kind != VK_RISCV_None) && (Kind != VK_RISCV_CALL) &&
38  (Kind != VK_RISCV_CALL_PLT));
39 
40  if (HasVariant)
41  OS << '%' << getVariantKindName(getKind()) << '(';
42  Expr->print(OS, MAI);
43  if (Kind == VK_RISCV_CALL_PLT)
44  OS << "@plt";
45  if (HasVariant)
46  OS << ')';
47 }
48 
49 const MCFixup *RISCVMCExpr::getPCRelHiFixup(const MCFragment **DFOut) const {
50  MCValue AUIPCLoc;
51  if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr))
52  return nullptr;
53 
54  const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA();
55  if (!AUIPCSRE)
56  return nullptr;
57 
58  const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol();
59  const auto *DF = dyn_cast_or_null<MCDataFragment>(AUIPCSymbol->getFragment());
60 
61  if (!DF)
62  return nullptr;
63 
64  uint64_t Offset = AUIPCSymbol->getOffset();
65  if (DF->getContents().size() == Offset) {
66  DF = dyn_cast_or_null<MCDataFragment>(DF->getNextNode());
67  if (!DF)
68  return nullptr;
69  Offset = 0;
70  }
71 
72  for (const MCFixup &F : DF->getFixups()) {
73  if (F.getOffset() != Offset)
74  continue;
75 
76  switch ((unsigned)F.getKind()) {
77  default:
78  continue;
83  if (DFOut)
84  *DFOut = DF;
85  return &F;
86  }
87  }
88 
89  return nullptr;
90 }
91 
93  const MCAsmLayout *Layout,
94  const MCFixup *Fixup) const {
95  // Explicitly drop the layout and assembler to prevent any symbolic folding in
96  // the expression handling. This is required to preserve symbolic difference
97  // expressions to emit the paired relocations.
98  if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr))
99  return false;
100 
101  Res =
102  MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
103  // Custom fixup types are not valid with symbol difference expressions.
104  return Res.getSymB() ? getKind() == VK_RISCV_None : true;
105 }
106 
107 void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
108  Streamer.visitUsedExpr(*getSubExpr());
109 }
110 
113  .Case("lo", VK_RISCV_LO)
114  .Case("hi", VK_RISCV_HI)
115  .Case("pcrel_lo", VK_RISCV_PCREL_LO)
116  .Case("pcrel_hi", VK_RISCV_PCREL_HI)
117  .Case("got_pcrel_hi", VK_RISCV_GOT_HI)
118  .Case("tprel_lo", VK_RISCV_TPREL_LO)
119  .Case("tprel_hi", VK_RISCV_TPREL_HI)
120  .Case("tprel_add", VK_RISCV_TPREL_ADD)
121  .Case("tls_ie_pcrel_hi", VK_RISCV_TLS_GOT_HI)
122  .Case("tls_gd_pcrel_hi", VK_RISCV_TLS_GD_HI)
124 }
125 
127  switch (Kind) {
128  case VK_RISCV_Invalid:
129  case VK_RISCV_None:
130  llvm_unreachable("Invalid ELF symbol kind");
131  case VK_RISCV_LO:
132  return "lo";
133  case VK_RISCV_HI:
134  return "hi";
135  case VK_RISCV_PCREL_LO:
136  return "pcrel_lo";
137  case VK_RISCV_PCREL_HI:
138  return "pcrel_hi";
139  case VK_RISCV_GOT_HI:
140  return "got_pcrel_hi";
141  case VK_RISCV_TPREL_LO:
142  return "tprel_lo";
143  case VK_RISCV_TPREL_HI:
144  return "tprel_hi";
145  case VK_RISCV_TPREL_ADD:
146  return "tprel_add";
147  case VK_RISCV_TLS_GOT_HI:
148  return "tls_ie_pcrel_hi";
149  case VK_RISCV_TLS_GD_HI:
150  return "tls_gd_pcrel_hi";
151  case VK_RISCV_CALL:
152  return "call";
153  case VK_RISCV_CALL_PLT:
154  return "call_plt";
155  case VK_RISCV_32_PCREL:
156  return "32_pcrel";
157  }
158  llvm_unreachable("Invalid ELF symbol kind");
159 }
160 
162  switch (Expr->getKind()) {
163  case MCExpr::Target:
164  llvm_unreachable("Can't handle nested target expression");
165  break;
166  case MCExpr::Constant:
167  break;
168 
169  case MCExpr::Binary: {
170  const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
173  break;
174  }
175 
176  case MCExpr::SymbolRef: {
177  // We're known to be under a TLS fixup, so any symbol should be
178  // modified. There should be only one.
179  const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
180  cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
181  break;
182  }
183 
184  case MCExpr::Unary:
185  fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
186  break;
187  }
188 }
189 
191  switch (getKind()) {
192  default:
193  return;
194  case VK_RISCV_TPREL_HI:
195  case VK_RISCV_TLS_GOT_HI:
196  case VK_RISCV_TLS_GD_HI:
197  break;
198  }
199 
201 }
202 
203 bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
204  MCValue Value;
205 
206  if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
207  Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI ||
208  Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD ||
209  Kind == VK_RISCV_TLS_GOT_HI || Kind == VK_RISCV_TLS_GD_HI ||
210  Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT)
211  return false;
212 
213  if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
214  return false;
215 
216  if (!Value.isAbsolute())
217  return false;
218 
219  Res = evaluateAsInt64(Value.getConstant());
220  return true;
221 }
222 
223 int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
224  switch (Kind) {
225  default:
226  llvm_unreachable("Invalid kind");
227  case VK_RISCV_LO:
228  return SignExtend64<12>(Value);
229  case VK_RISCV_HI:
230  // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
231  return ((Value + 0x800) >> 12) & 0xfffff;
232  }
233 }
llvm::StringSwitch::Case
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:67
llvm::RISCVMCExpr::VK_RISCV_Invalid
@ VK_RISCV_Invalid
Definition: RISCVMCExpr.h:40
llvm::MCStreamer::visitUsedExpr
void visitUsedExpr(const MCExpr &Expr)
Definition: MCStreamer.cpp:1061
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
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:35
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:72
llvm::StringSwitch::Default
LLVM_NODISCARD R Default(T Value)
Definition: StringSwitch.h:181
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:203
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:161
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
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::RISCVMCExpr::getVariantKindForName
static VariantKind getVariantKindForName(StringRef name)
Definition: RISCVMCExpr.cpp:111
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:480
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::ELF::STT_TLS
@ STT_TLS
Definition: ELF.h:1162
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:747
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:31
llvm::MCStreamer
Streaming machine code generation interface.
Definition: MCStreamer.h:199
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:630
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:53
llvm::MCSymbolRefExpr::getSymbol
const MCSymbol & getSymbol() const
Definition: MCExpr.h:398
llvm::MCValue::getConstant
int64_t getConstant() const
Definition: MCValue.h:44
llvm::MCValue::getSymA
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:45
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:30
RISCVAsmBackend.h
llvm::MCAssembler
Definition: MCAssembler.h:60
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:60
llvm::RISCVMCExpr::evaluateAsRelocatableImpl
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const override
Definition: RISCVMCExpr.cpp:92
llvm::RISCVMCExpr::visitUsedExpr
void visitUsedExpr(MCStreamer &Streamer) const override
Definition: RISCVMCExpr.cpp:107
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:134
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:190
MCAsmLayout.h
llvm::RISCVMCExpr::getKind
VariantKind getKind() const
Definition: RISCVMCExpr.h:56
name
static const char * name
Definition: SVEIntrinsicOpts.cpp:78
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
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::RISCVMCExpr::getVariantKindName
static StringRef getVariantKindName(VariantKind Kind)
Definition: RISCVMCExpr.cpp:126
MCValue.h
llvm::MCExpr::print
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:42
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:42
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:49
llvm::MCValue
This represents an "assembler immediate".
Definition: MCValue.h:37
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:46
llvm::MCBinaryExpr::getLHS
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition: MCExpr.h:627
RISCVFixupKinds.h
llvm::RISCVMCExpr
Definition: RISCVMCExpr.h:23