1249259Sdim//===-- AArch64MCExpr.cpp - AArch64 specific MC expression classes --------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file contains the implementation of the assembly expression modifiers 11249259Sdim// accepted by the AArch64 architecture (e.g. ":lo12:", ":gottprel_g1:", ...). 12249259Sdim// 13249259Sdim//===----------------------------------------------------------------------===// 14249259Sdim 15249259Sdim#define DEBUG_TYPE "aarch64mcexpr" 16249259Sdim#include "AArch64MCExpr.h" 17249259Sdim#include "llvm/MC/MCContext.h" 18249259Sdim#include "llvm/MC/MCAssembler.h" 19249259Sdim#include "llvm/MC/MCELF.h" 20249259Sdim#include "llvm/Object/ELF.h" 21249259Sdim 22249259Sdimusing namespace llvm; 23249259Sdim 24249259Sdimconst AArch64MCExpr* 25249259SdimAArch64MCExpr::Create(VariantKind Kind, const MCExpr *Expr, 26249259Sdim MCContext &Ctx) { 27249259Sdim return new (Ctx) AArch64MCExpr(Kind, Expr); 28249259Sdim} 29249259Sdim 30249259Sdimvoid AArch64MCExpr::PrintImpl(raw_ostream &OS) const { 31249259Sdim switch (Kind) { 32249259Sdim default: llvm_unreachable("Invalid kind!"); 33249259Sdim case VK_AARCH64_GOT: OS << ":got:"; break; 34249259Sdim case VK_AARCH64_GOT_LO12: OS << ":got_lo12:"; break; 35249259Sdim case VK_AARCH64_LO12: OS << ":lo12:"; break; 36249259Sdim case VK_AARCH64_ABS_G0: OS << ":abs_g0:"; break; 37249259Sdim case VK_AARCH64_ABS_G0_NC: OS << ":abs_g0_nc:"; break; 38249259Sdim case VK_AARCH64_ABS_G1: OS << ":abs_g1:"; break; 39249259Sdim case VK_AARCH64_ABS_G1_NC: OS << ":abs_g1_nc:"; break; 40249259Sdim case VK_AARCH64_ABS_G2: OS << ":abs_g2:"; break; 41249259Sdim case VK_AARCH64_ABS_G2_NC: OS << ":abs_g2_nc:"; break; 42249259Sdim case VK_AARCH64_ABS_G3: OS << ":abs_g3:"; break; 43249259Sdim case VK_AARCH64_SABS_G0: OS << ":abs_g0_s:"; break; 44249259Sdim case VK_AARCH64_SABS_G1: OS << ":abs_g1_s:"; break; 45249259Sdim case VK_AARCH64_SABS_G2: OS << ":abs_g2_s:"; break; 46249259Sdim case VK_AARCH64_DTPREL_G2: OS << ":dtprel_g2:"; break; 47249259Sdim case VK_AARCH64_DTPREL_G1: OS << ":dtprel_g1:"; break; 48249259Sdim case VK_AARCH64_DTPREL_G1_NC: OS << ":dtprel_g1_nc:"; break; 49249259Sdim case VK_AARCH64_DTPREL_G0: OS << ":dtprel_g0:"; break; 50249259Sdim case VK_AARCH64_DTPREL_G0_NC: OS << ":dtprel_g0_nc:"; break; 51249259Sdim case VK_AARCH64_DTPREL_HI12: OS << ":dtprel_hi12:"; break; 52249259Sdim case VK_AARCH64_DTPREL_LO12: OS << ":dtprel_lo12:"; break; 53249259Sdim case VK_AARCH64_DTPREL_LO12_NC: OS << ":dtprel_lo12_nc:"; break; 54249259Sdim case VK_AARCH64_GOTTPREL_G1: OS << ":gottprel_g1:"; break; 55249259Sdim case VK_AARCH64_GOTTPREL_G0_NC: OS << ":gottprel_g0_nc:"; break; 56249259Sdim case VK_AARCH64_GOTTPREL: OS << ":gottprel:"; break; 57249259Sdim case VK_AARCH64_GOTTPREL_LO12: OS << ":gottprel_lo12:"; break; 58249259Sdim case VK_AARCH64_TPREL_G2: OS << ":tprel_g2:"; break; 59249259Sdim case VK_AARCH64_TPREL_G1: OS << ":tprel_g1:"; break; 60249259Sdim case VK_AARCH64_TPREL_G1_NC: OS << ":tprel_g1_nc:"; break; 61249259Sdim case VK_AARCH64_TPREL_G0: OS << ":tprel_g0:"; break; 62249259Sdim case VK_AARCH64_TPREL_G0_NC: OS << ":tprel_g0_nc:"; break; 63249259Sdim case VK_AARCH64_TPREL_HI12: OS << ":tprel_hi12:"; break; 64249259Sdim case VK_AARCH64_TPREL_LO12: OS << ":tprel_lo12:"; break; 65249259Sdim case VK_AARCH64_TPREL_LO12_NC: OS << ":tprel_lo12_nc:"; break; 66249259Sdim case VK_AARCH64_TLSDESC: OS << ":tlsdesc:"; break; 67249259Sdim case VK_AARCH64_TLSDESC_LO12: OS << ":tlsdesc_lo12:"; break; 68249259Sdim 69249259Sdim } 70249259Sdim 71249259Sdim const MCExpr *Expr = getSubExpr(); 72249259Sdim if (Expr->getKind() != MCExpr::SymbolRef) 73249259Sdim OS << '('; 74249259Sdim Expr->print(OS); 75249259Sdim if (Expr->getKind() != MCExpr::SymbolRef) 76249259Sdim OS << ')'; 77249259Sdim} 78249259Sdim 79249259Sdimbool 80249259SdimAArch64MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, 81249259Sdim const MCAsmLayout *Layout) const { 82249259Sdim return getSubExpr()->EvaluateAsRelocatable(Res, *Layout); 83249259Sdim} 84249259Sdim 85249259Sdimstatic void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 86249259Sdim switch (Expr->getKind()) { 87249259Sdim case MCExpr::Target: 88249259Sdim llvm_unreachable("Can't handle nested target expression"); 89249259Sdim break; 90249259Sdim case MCExpr::Constant: 91249259Sdim break; 92249259Sdim 93249259Sdim case MCExpr::Binary: { 94249259Sdim const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 95249259Sdim fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); 96249259Sdim fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); 97249259Sdim break; 98249259Sdim } 99249259Sdim 100249259Sdim case MCExpr::SymbolRef: { 101249259Sdim // We're known to be under a TLS fixup, so any symbol should be 102249259Sdim // modified. There should be only one. 103249259Sdim const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 104249259Sdim MCSymbolData &SD = Asm.getOrCreateSymbolData(SymRef.getSymbol()); 105249259Sdim MCELF::SetType(SD, ELF::STT_TLS); 106249259Sdim break; 107249259Sdim } 108249259Sdim 109249259Sdim case MCExpr::Unary: 110249259Sdim fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); 111249259Sdim break; 112249259Sdim } 113249259Sdim} 114249259Sdim 115249259Sdimvoid AArch64MCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 116249259Sdim switch (getKind()) { 117249259Sdim default: 118249259Sdim return; 119249259Sdim case VK_AARCH64_DTPREL_G2: 120249259Sdim case VK_AARCH64_DTPREL_G1: 121249259Sdim case VK_AARCH64_DTPREL_G1_NC: 122249259Sdim case VK_AARCH64_DTPREL_G0: 123249259Sdim case VK_AARCH64_DTPREL_G0_NC: 124249259Sdim case VK_AARCH64_DTPREL_HI12: 125249259Sdim case VK_AARCH64_DTPREL_LO12: 126249259Sdim case VK_AARCH64_DTPREL_LO12_NC: 127249259Sdim case VK_AARCH64_GOTTPREL_G1: 128249259Sdim case VK_AARCH64_GOTTPREL_G0_NC: 129249259Sdim case VK_AARCH64_GOTTPREL: 130249259Sdim case VK_AARCH64_GOTTPREL_LO12: 131249259Sdim case VK_AARCH64_TPREL_G2: 132249259Sdim case VK_AARCH64_TPREL_G1: 133249259Sdim case VK_AARCH64_TPREL_G1_NC: 134249259Sdim case VK_AARCH64_TPREL_G0: 135249259Sdim case VK_AARCH64_TPREL_G0_NC: 136249259Sdim case VK_AARCH64_TPREL_HI12: 137249259Sdim case VK_AARCH64_TPREL_LO12: 138249259Sdim case VK_AARCH64_TPREL_LO12_NC: 139249259Sdim case VK_AARCH64_TLSDESC: 140249259Sdim case VK_AARCH64_TLSDESC_LO12: 141249259Sdim break; 142249259Sdim } 143249259Sdim 144249259Sdim fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 145249259Sdim} 146249259Sdim 147249259Sdim// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps 148249259Sdim// that method should be made public? 149249259Sdim// FIXME: really do above: now that two backends are using it. 150249259Sdimstatic void AddValueSymbolsImpl(const MCExpr *Value, MCAssembler *Asm) { 151249259Sdim switch (Value->getKind()) { 152249259Sdim case MCExpr::Target: 153249259Sdim llvm_unreachable("Can't handle nested target expr!"); 154249259Sdim break; 155249259Sdim 156249259Sdim case MCExpr::Constant: 157249259Sdim break; 158249259Sdim 159249259Sdim case MCExpr::Binary: { 160249259Sdim const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); 161249259Sdim AddValueSymbolsImpl(BE->getLHS(), Asm); 162249259Sdim AddValueSymbolsImpl(BE->getRHS(), Asm); 163249259Sdim break; 164249259Sdim } 165249259Sdim 166249259Sdim case MCExpr::SymbolRef: 167249259Sdim Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol()); 168249259Sdim break; 169249259Sdim 170249259Sdim case MCExpr::Unary: 171249259Sdim AddValueSymbolsImpl(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm); 172249259Sdim break; 173249259Sdim } 174249259Sdim} 175249259Sdim 176249259Sdimvoid AArch64MCExpr::AddValueSymbols(MCAssembler *Asm) const { 177249259Sdim AddValueSymbolsImpl(getSubExpr(), Asm); 178249259Sdim} 179