LLVM  8.0.1
RISCVMCExpr.cpp
Go to the documentation of this file.
1 //===-- RISCVMCExpr.cpp - RISCV specific MC expression classes ------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the implementation of the assembly expression modifiers
11 // accepted by the RISCV architecture (e.g. ":lo12:", ":gottprel_g1:", ...).
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "RISCV.h"
16 #include "RISCVMCExpr.h"
17 #include "RISCVFixupKinds.h"
18 #include "llvm/MC/MCAssembler.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCStreamer.h"
21 #include "llvm/MC/MCSymbolELF.h"
22 #include "llvm/MC/MCValue.h"
24 
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "riscvmcexpr"
28 
30  MCContext &Ctx) {
31  return new (Ctx) RISCVMCExpr(Expr, Kind);
32 }
33 
34 void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
35  bool HasVariant =
36  ((getKind() != VK_RISCV_None) && (getKind() != VK_RISCV_CALL));
37  if (HasVariant)
38  OS << '%' << getVariantKindName(getKind()) << '(';
39  Expr->print(OS, MAI);
40  if (HasVariant)
41  OS << ')';
42 }
43 
45  MCValue AUIPCLoc;
46  if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr))
47  return nullptr;
48 
49  const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA();
50  if (!AUIPCSRE)
51  return nullptr;
52 
53  const auto *DF =
54  dyn_cast_or_null<MCDataFragment>(AUIPCSRE->findAssociatedFragment());
55  if (!DF)
56  return nullptr;
57 
58  const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol();
59  for (const MCFixup &F : DF->getFixups()) {
60  if (F.getOffset() != AUIPCSymbol->getOffset())
61  continue;
62 
63  switch ((unsigned)F.getKind()) {
64  default:
65  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  return false;
141  }
142  }
143 
144  return true;
145 }
146 
147 void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
148  Streamer.visitUsedExpr(*getSubExpr());
149 }
150 
153  .Case("lo", VK_RISCV_LO)
154  .Case("hi", VK_RISCV_HI)
155  .Case("pcrel_lo", VK_RISCV_PCREL_LO)
156  .Case("pcrel_hi", VK_RISCV_PCREL_HI)
158 }
159 
161  switch (Kind) {
162  default:
163  llvm_unreachable("Invalid ELF symbol kind");
164  case VK_RISCV_LO:
165  return "lo";
166  case VK_RISCV_HI:
167  return "hi";
168  case VK_RISCV_PCREL_LO:
169  return "pcrel_lo";
170  case VK_RISCV_PCREL_HI:
171  return "pcrel_hi";
172  }
173 }
174 
175 bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
176  MCValue Value;
177 
178  if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
179  Kind == VK_RISCV_CALL)
180  return false;
181 
182  if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
183  return false;
184 
185  if (!Value.isAbsolute())
186  return false;
187 
188  Res = evaluateAsInt64(Value.getConstant());
189  return true;
190 }
191 
192 int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
193  switch (Kind) {
194  default:
195  llvm_unreachable("Invalid kind");
196  case VK_RISCV_LO:
197  return SignExtend64<12>(Value);
198  case VK_RISCV_HI:
199  // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
200  return ((Value + 0x800) >> 12) & 0xfffff;
201  }
202 }
bool evaluateAsConstant(int64_t &Res) const
This class represents lattice values for constants.
Definition: AllocatorList.h:24
This represents an "assembler immediate".
Definition: MCValue.h:40
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override
Definition: RISCVMCExpr.cpp:34
VariantKind getKind() const
Definition: RISCVMCExpr.h:52
bool isAbsolute() const
Is this an absolute (as opposed to relocatable) value.
Definition: MCValue.h:53
F(f)
static StringRef getVariantKindName(VariantKind Kind)
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:74
int64_t getConstant() const
Definition: MCValue.h:47
const MCSymbolRefExpr * getSymB() const
Definition: MCValue.h:49
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:29
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute)...
Definition: MCSymbol.h:252
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:166
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(T Value)
Definition: StringSwitch.h:203
Context object for machine code objects.
Definition: MCContext.h:63
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:647
const MCFixup * getPCRelHiFixup() const
Get the MCExpr of the VK_RISCV_PCREL_HI Fixup that the VK_RISCV_PCREL_LO points to.
Definition: RISCVMCExpr.cpp:44
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:56
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
Streaming machine code generation interface.
Definition: MCStreamer.h:189
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:42
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:48
uint64_t getOffset() const
Definition: MCSymbol.h:321
uint32_t getOffset() const
Definition: MCFixup.h:125
#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:336
MCFragment * findAssociatedFragment() const
Find the "associated section" for this expression, which is currently defined as the absolute section...
Definition: MCExpr.cpp:867
MCFragment * findAssociatedFragment() const override
Definition: RISCVMCExpr.h:67
void visitUsedExpr(const MCExpr &Expr)
Definition: MCStreamer.cpp:930
MCSection * getParent() const
Definition: MCFragment.h:99
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
Definition: MCSymbol.h:267
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:70
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:63
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:655
const unsigned Kind
LLVM Value Representation.
Definition: Value.h:73
static const char * name
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
const MCExpr * getValue() const
Definition: MCFixup.h:128
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Target specific expression.
Definition: MCExpr.h:43
void visitUsedExpr(MCStreamer &Streamer) const override
static const RISCVMCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
Definition: RISCVMCExpr.cpp:29
MCFixupKind getKind() const
Definition: MCFixup.h:123