LLVM  13.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  if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
96  return false;
97 
98  // Some custom fixup types are not valid with symbol difference expressions
99  if (Res.getSymA() && Res.getSymB()) {
100  switch (getKind()) {
101  default:
102  return true;
103  case VK_RISCV_LO:
104  case VK_RISCV_HI:
105  case VK_RISCV_PCREL_LO:
106  case VK_RISCV_PCREL_HI:
107  case VK_RISCV_GOT_HI:
108  case VK_RISCV_TPREL_LO:
109  case VK_RISCV_TPREL_HI:
110  case VK_RISCV_TPREL_ADD:
111  case VK_RISCV_TLS_GOT_HI:
112  case VK_RISCV_TLS_GD_HI:
113  return false;
114  }
115  }
116 
117  return true;
118 }
119 
120 void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
121  Streamer.visitUsedExpr(*getSubExpr());
122 }
123 
126  .Case("lo", VK_RISCV_LO)
127  .Case("hi", VK_RISCV_HI)
128  .Case("pcrel_lo", VK_RISCV_PCREL_LO)
129  .Case("pcrel_hi", VK_RISCV_PCREL_HI)
130  .Case("got_pcrel_hi", VK_RISCV_GOT_HI)
131  .Case("tprel_lo", VK_RISCV_TPREL_LO)
132  .Case("tprel_hi", VK_RISCV_TPREL_HI)
133  .Case("tprel_add", VK_RISCV_TPREL_ADD)
134  .Case("tls_ie_pcrel_hi", VK_RISCV_TLS_GOT_HI)
135  .Case("tls_gd_pcrel_hi", VK_RISCV_TLS_GD_HI)
137 }
138 
140  switch (Kind) {
141  case VK_RISCV_Invalid:
142  case VK_RISCV_None:
143  llvm_unreachable("Invalid ELF symbol kind");
144  case VK_RISCV_LO:
145  return "lo";
146  case VK_RISCV_HI:
147  return "hi";
148  case VK_RISCV_PCREL_LO:
149  return "pcrel_lo";
150  case VK_RISCV_PCREL_HI:
151  return "pcrel_hi";
152  case VK_RISCV_GOT_HI:
153  return "got_pcrel_hi";
154  case VK_RISCV_TPREL_LO:
155  return "tprel_lo";
156  case VK_RISCV_TPREL_HI:
157  return "tprel_hi";
158  case VK_RISCV_TPREL_ADD:
159  return "tprel_add";
160  case VK_RISCV_TLS_GOT_HI:
161  return "tls_ie_pcrel_hi";
162  case VK_RISCV_TLS_GD_HI:
163  return "tls_gd_pcrel_hi";
164  case VK_RISCV_CALL:
165  return "call";
166  case VK_RISCV_CALL_PLT:
167  return "call_plt";
168  case VK_RISCV_32_PCREL:
169  return "32_pcrel";
170  }
171  llvm_unreachable("Invalid ELF symbol kind");
172 }
173 
175  switch (Expr->getKind()) {
176  case MCExpr::Target:
177  llvm_unreachable("Can't handle nested target expression");
178  break;
179  case MCExpr::Constant:
180  break;
181 
182  case MCExpr::Binary: {
183  const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
186  break;
187  }
188 
189  case MCExpr::SymbolRef: {
190  // We're known to be under a TLS fixup, so any symbol should be
191  // modified. There should be only one.
192  const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
193  cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
194  break;
195  }
196 
197  case MCExpr::Unary:
198  fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
199  break;
200  }
201 }
202 
204  switch (getKind()) {
205  default:
206  return;
207  case VK_RISCV_TPREL_HI:
208  case VK_RISCV_TLS_GOT_HI:
209  case VK_RISCV_TLS_GD_HI:
210  break;
211  }
212 
214 }
215 
216 bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
217  MCValue Value;
218 
219  if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
220  Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI ||
221  Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD ||
222  Kind == VK_RISCV_TLS_GOT_HI || Kind == VK_RISCV_TLS_GD_HI ||
223  Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT)
224  return false;
225 
226  if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
227  return false;
228 
229  if (!Value.isAbsolute())
230  return false;
231 
232  Res = evaluateAsInt64(Value.getConstant());
233  return true;
234 }
235 
236 int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
237  switch (Kind) {
238  default:
239  llvm_unreachable("Invalid kind");
240  case VK_RISCV_LO:
241  return SignExtend64<12>(Value);
242  case VK_RISCV_HI:
243  // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
244  return ((Value + 0x800) >> 12) & 0xfffff;
245  }
246 }
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:1046
llvm
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:71
llvm::StringSwitch::Default
LLVM_NODISCARD R Default(T Value)
Definition: StringSwitch.h:181
llvm::MCSymbol::getOffset
uint64_t getOffset() const
Definition: MCSymbol.h:317
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:216
llvm::RISCV::fixup_riscv_tls_gd_hi20
@ fixup_riscv_tls_gd_hi20
Definition: RISCVFixupKinds.h:57
ErrorHandling.h
MCAssembler.h
fixELFSymbolsInTLSFixupsImpl
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm)
Definition: RISCVMCExpr.cpp:174
llvm::MCSymbol::getFragment
MCFragment * getFragment(bool SetUsed=true) const
Definition: MCSymbol.h:389
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:124
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:479
F
#define F(x, y, z)
Definition: MD5.cpp:56
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:766
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:197
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:54
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:629
llvm::RISCV::fixup_riscv_got_hi20
@ fixup_riscv_got_hi20
Definition: RISCVFixupKinds.h:39
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
llvm::MCSymbolRefExpr::getSymbol
const MCSymbol & getSymbol() const
Definition: MCExpr.h:397
llvm::MCValue::getSymA
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:45
llvm::MCExpr::getKind
ExprKind getKind() const
Definition: MCExpr.h:81
llvm::ELF::STT_TLS
@ STT_TLS
Definition: ELF.h:1150
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
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:120
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
Fixup
PowerPC TLS Dynamic Call Fixup
Definition: PPCTLSDynamicCall.cpp:235
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::RISCV::fixup_riscv_pcrel_hi20
@ fixup_riscv_pcrel_hi20
Definition: RISCVFixupKinds.h:30
llvm::RISCVMCExpr::fixELFSymbolsInTLSFixups
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override
Definition: RISCVMCExpr.cpp:203
MCAsmLayout.h
llvm::RISCVMCExpr::getKind
VariantKind getKind() const
Definition: RISCVMCExpr.h:56
name
static const char * name
Definition: SVEIntrinsicOpts.cpp:83
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:139
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:81
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
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:626
RISCVFixupKinds.h
llvm::RISCVMCExpr
Definition: RISCVMCExpr.h:23