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 "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"
22 #include "llvm/Object/ELF.h"
23 #include "llvm/Support/ErrorHandling.h"
24
25 using namespace llvm;
26
27 #define DEBUG_TYPE "riscvmcexpr"
28
create(const MCExpr * Expr,VariantKind Kind,MCContext & Ctx)29 const RISCVMCExpr *RISCVMCExpr::create(const MCExpr *Expr, VariantKind Kind,
30 MCContext &Ctx) {
31 return new (Ctx) RISCVMCExpr(Expr, Kind);
32 }
33
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const34 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
evaluateAsRelocatableImpl(MCValue & Res,const MCAsmLayout * Layout,const MCFixup * Fixup) const44 bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
45 const MCAsmLayout *Layout,
46 const MCFixup *Fixup) const {
47 if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
48 return false;
49
50 // Some custom fixup types are not valid with symbol difference expressions
51 if (Res.getSymA() && Res.getSymB()) {
52 switch (getKind()) {
53 default:
54 return true;
55 case VK_RISCV_LO:
56 case VK_RISCV_HI:
57 case VK_RISCV_PCREL_LO:
58 case VK_RISCV_PCREL_HI:
59 return false;
60 }
61 }
62
63 return true;
64 }
65
visitUsedExpr(MCStreamer & Streamer) const66 void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
67 Streamer.visitUsedExpr(*getSubExpr());
68 }
69
getVariantKindForName(StringRef name)70 RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {
71 return StringSwitch<RISCVMCExpr::VariantKind>(name)
72 .Case("lo", VK_RISCV_LO)
73 .Case("hi", VK_RISCV_HI)
74 .Case("pcrel_lo", VK_RISCV_PCREL_LO)
75 .Case("pcrel_hi", VK_RISCV_PCREL_HI)
76 .Default(VK_RISCV_Invalid);
77 }
78
getVariantKindName(VariantKind Kind)79 StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {
80 switch (Kind) {
81 default:
82 llvm_unreachable("Invalid ELF symbol kind");
83 case VK_RISCV_LO:
84 return "lo";
85 case VK_RISCV_HI:
86 return "hi";
87 case VK_RISCV_PCREL_LO:
88 return "pcrel_lo";
89 case VK_RISCV_PCREL_HI:
90 return "pcrel_hi";
91 }
92 }
93
evaluateAsConstant(int64_t & Res) const94 bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
95 MCValue Value;
96
97 if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
98 Kind == VK_RISCV_CALL)
99 return false;
100
101 if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
102 return false;
103
104 if (!Value.isAbsolute())
105 return false;
106
107 Res = evaluateAsInt64(Value.getConstant());
108 return true;
109 }
110
evaluateAsInt64(int64_t Value) const111 int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
112 switch (Kind) {
113 default:
114 llvm_unreachable("Invalid kind");
115 case VK_RISCV_LO:
116 return SignExtend64<12>(Value);
117 case VK_RISCV_HI:
118 // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
119 return ((Value + 0x800) >> 12) & 0xfffff;
120 }
121 }
122