blob: b36236ea155f32c6c920d8f586286889ad0410f3 [file] [log] [blame]
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001//===-- 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 "RISCVMCExpr.h"
16#include "llvm/MC/MCAssembler.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCSymbolELF.h"
20#include "llvm/MC/MCValue.h"
21#include "llvm/Object/ELF.h"
22#include "llvm/Support/ErrorHandling.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "riscvmcexpr"
27
28const RISCVMCExpr *RISCVMCExpr::create(const MCExpr *Expr, VariantKind Kind,
29 MCContext &Ctx) {
30 return new (Ctx) RISCVMCExpr(Expr, Kind);
31}
32
33void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
34 bool HasVariant = getKind() != VK_RISCV_None;
35 if (HasVariant)
36 OS << '%' << getVariantKindName(getKind()) << '(';
37 Expr->print(OS, MAI);
38 if (HasVariant)
39 OS << ')';
40}
41
42bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
43 const MCAsmLayout *Layout,
44 const MCFixup *Fixup) const {
45 return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
46}
47
48void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
49 Streamer.visitUsedExpr(*getSubExpr());
50}
51
52RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {
53 return StringSwitch<RISCVMCExpr::VariantKind>(name)
54 .Case("lo", VK_RISCV_LO)
55 .Case("hi", VK_RISCV_HI)
56 .Case("pcrel_hi", VK_RISCV_PCREL_HI)
57 .Default(VK_RISCV_Invalid);
58}
59
60StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {
61 switch (Kind) {
62 default:
63 llvm_unreachable("Invalid ELF symbol kind");
64 case VK_RISCV_LO:
65 return "lo";
66 case VK_RISCV_HI:
67 return "hi";
68 case VK_RISCV_PCREL_HI:
69 return "pcrel_hi";
70 }
71}
72
73bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
74 MCValue Value;
75
76 if (Kind == VK_RISCV_PCREL_HI)
77 return false;
78
79 if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
80 return false;
81
82 if (!Value.isAbsolute())
83 return false;
84
85 Res = evaluateAsInt64(Value.getConstant());
86 return true;
87}
88
89int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
90 switch (Kind) {
91 default:
92 llvm_unreachable("Invalid kind");
93 case VK_RISCV_LO:
94 return SignExtend64<12>(Value);
95 case VK_RISCV_HI:
96 // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
97 return ((Value + 0x800) >> 12) & 0xfffff;
98 }
99}