Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 1 | //===-- AArch64MCExpr.cpp - AArch64 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 AArch64 architecture (e.g. ":lo12:", ":gottprel_g1:", ...). |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #include "AArch64MCExpr.h" |
| 16 | #include "llvm/MC/MCAssembler.h" |
| 17 | #include "llvm/MC/MCContext.h" |
Pete Cooper | ef21bd4 | 2015-03-04 01:24:11 +0000 | [diff] [blame] | 18 | #include "llvm/MC/MCStreamer.h" |
Rafael Espindola | 95fb9b9 | 2015-06-02 20:38:46 +0000 | [diff] [blame] | 19 | #include "llvm/MC/MCSymbolELF.h" |
Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 20 | #include "llvm/MC/MCValue.h" |
| 21 | #include "llvm/Object/ELF.h" |
| 22 | #include "llvm/Support/ErrorHandling.h" |
| 23 | |
| 24 | using namespace llvm; |
| 25 | |
| 26 | #define DEBUG_TYPE "aarch64symbolrefexpr" |
| 27 | |
Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 28 | const AArch64MCExpr *AArch64MCExpr::create(const MCExpr *Expr, VariantKind Kind, |
Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 29 | MCContext &Ctx) { |
| 30 | return new (Ctx) AArch64MCExpr(Expr, Kind); |
| 31 | } |
| 32 | |
| 33 | StringRef AArch64MCExpr::getVariantKindName() const { |
| 34 | switch (static_cast<uint32_t>(getKind())) { |
| 35 | case VK_CALL: return ""; |
| 36 | case VK_LO12: return ":lo12:"; |
| 37 | case VK_ABS_G3: return ":abs_g3:"; |
| 38 | case VK_ABS_G2: return ":abs_g2:"; |
| 39 | case VK_ABS_G2_S: return ":abs_g2_s:"; |
| 40 | case VK_ABS_G2_NC: return ":abs_g2_nc:"; |
| 41 | case VK_ABS_G1: return ":abs_g1:"; |
| 42 | case VK_ABS_G1_S: return ":abs_g1_s:"; |
| 43 | case VK_ABS_G1_NC: return ":abs_g1_nc:"; |
| 44 | case VK_ABS_G0: return ":abs_g0:"; |
| 45 | case VK_ABS_G0_S: return ":abs_g0_s:"; |
| 46 | case VK_ABS_G0_NC: return ":abs_g0_nc:"; |
| 47 | case VK_DTPREL_G2: return ":dtprel_g2:"; |
| 48 | case VK_DTPREL_G1: return ":dtprel_g1:"; |
| 49 | case VK_DTPREL_G1_NC: return ":dtprel_g1_nc:"; |
| 50 | case VK_DTPREL_G0: return ":dtprel_g0:"; |
| 51 | case VK_DTPREL_G0_NC: return ":dtprel_g0_nc:"; |
| 52 | case VK_DTPREL_HI12: return ":dtprel_hi12:"; |
| 53 | case VK_DTPREL_LO12: return ":dtprel_lo12:"; |
| 54 | case VK_DTPREL_LO12_NC: return ":dtprel_lo12_nc:"; |
| 55 | case VK_TPREL_G2: return ":tprel_g2:"; |
| 56 | case VK_TPREL_G1: return ":tprel_g1:"; |
| 57 | case VK_TPREL_G1_NC: return ":tprel_g1_nc:"; |
| 58 | case VK_TPREL_G0: return ":tprel_g0:"; |
| 59 | case VK_TPREL_G0_NC: return ":tprel_g0_nc:"; |
| 60 | case VK_TPREL_HI12: return ":tprel_hi12:"; |
| 61 | case VK_TPREL_LO12: return ":tprel_lo12:"; |
| 62 | case VK_TPREL_LO12_NC: return ":tprel_lo12_nc:"; |
| 63 | case VK_TLSDESC_LO12: return ":tlsdesc_lo12:"; |
| 64 | case VK_ABS_PAGE: return ""; |
| 65 | case VK_GOT_PAGE: return ":got:"; |
| 66 | case VK_GOT_LO12: return ":got_lo12:"; |
| 67 | case VK_GOTTPREL_PAGE: return ":gottprel:"; |
| 68 | case VK_GOTTPREL_LO12_NC: return ":gottprel_lo12:"; |
| 69 | case VK_GOTTPREL_G1: return ":gottprel_g1:"; |
| 70 | case VK_GOTTPREL_G0_NC: return ":gottprel_g0_nc:"; |
| 71 | case VK_TLSDESC: return ""; |
| 72 | case VK_TLSDESC_PAGE: return ":tlsdesc:"; |
| 73 | default: |
| 74 | llvm_unreachable("Invalid ELF symbol kind"); |
| 75 | } |
| 76 | } |
| 77 | |
Matt Arsenault | 8b64355 | 2015-06-09 00:31:39 +0000 | [diff] [blame] | 78 | void AArch64MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { |
Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 79 | if (getKind() != VK_NONE) |
| 80 | OS << getVariantKindName(); |
Matt Arsenault | 8b64355 | 2015-06-09 00:31:39 +0000 | [diff] [blame] | 81 | Expr->print(OS, MAI); |
Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 82 | } |
| 83 | |
Rafael Espindola | e2c6624 | 2014-06-25 15:45:33 +0000 | [diff] [blame] | 84 | void AArch64MCExpr::visitUsedExpr(MCStreamer &Streamer) const { |
Rafael Espindola | 2be1281 | 2014-06-25 15:29:54 +0000 | [diff] [blame] | 85 | Streamer.visitUsedExpr(*getSubExpr()); |
Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 86 | } |
| 87 | |
Rafael Espindola | e3a20f5 | 2015-10-05 12:07:05 +0000 | [diff] [blame] | 88 | MCFragment *AArch64MCExpr::findAssociatedFragment() const { |
Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 89 | llvm_unreachable("FIXME: what goes here?"); |
| 90 | } |
| 91 | |
Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 92 | bool AArch64MCExpr::evaluateAsRelocatableImpl(MCValue &Res, |
NAKAMURA Takumi | 0a7d0ad | 2015-09-22 11:15:07 +0000 | [diff] [blame] | 93 | const MCAsmLayout *Layout, |
| 94 | const MCFixup *Fixup) const { |
Jim Grosbach | 13760bd | 2015-05-30 01:25:56 +0000 | [diff] [blame] | 95 | if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) |
Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 96 | return false; |
| 97 | |
| 98 | Res = |
| 99 | MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); |
| 100 | |
| 101 | return true; |
| 102 | } |
| 103 | |
| 104 | static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { |
| 105 | switch (Expr->getKind()) { |
| 106 | case MCExpr::Target: |
| 107 | llvm_unreachable("Can't handle nested target expression"); |
| 108 | break; |
| 109 | case MCExpr::Constant: |
| 110 | break; |
| 111 | |
| 112 | case MCExpr::Binary: { |
| 113 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); |
| 114 | fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); |
| 115 | fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); |
| 116 | break; |
| 117 | } |
| 118 | |
| 119 | case MCExpr::SymbolRef: { |
| 120 | // We're known to be under a TLS fixup, so any symbol should be |
| 121 | // modified. There should be only one. |
| 122 | const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); |
Rafael Espindola | 95fb9b9 | 2015-06-02 20:38:46 +0000 | [diff] [blame] | 123 | cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); |
Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 124 | break; |
| 125 | } |
| 126 | |
| 127 | case MCExpr::Unary: |
| 128 | fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); |
| 129 | break; |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | void AArch64MCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { |
| 134 | switch (getSymbolLoc(Kind)) { |
| 135 | default: |
| 136 | return; |
| 137 | case VK_DTPREL: |
| 138 | case VK_GOTTPREL: |
| 139 | case VK_TPREL: |
| 140 | case VK_TLSDESC: |
| 141 | break; |
| 142 | } |
| 143 | |
| 144 | fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); |
| 145 | } |