• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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