304 lines · cpp
1//===-- AArch64MCAsmInfo.cpp - AArch64 asm properties ---------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the declarations of the AArch64MCAsmInfo properties.10//11//===----------------------------------------------------------------------===//12 13#include "AArch64MCAsmInfo.h"14#include "llvm/MC/MCContext.h"15#include "llvm/MC/MCExpr.h"16#include "llvm/MC/MCStreamer.h"17#include "llvm/MC/MCValue.h"18#include "llvm/Support/CommandLine.h"19#include "llvm/TargetParser/Triple.h"20using namespace llvm;21 22enum AsmWriterVariantTy {23 Default = -1,24 Generic = 0,25 Apple = 126};27 28static cl::opt<AsmWriterVariantTy> AsmWriterVariant(29 "aarch64-neon-syntax", cl::init(Default),30 cl::desc("Choose style of NEON code to emit from AArch64 backend:"),31 cl::values(clEnumValN(Generic, "generic", "Emit generic NEON assembly"),32 clEnumValN(Apple, "apple", "Emit Apple-style NEON assembly")));33 34const MCAsmInfo::AtSpecifier COFFAtSpecifiers[] = {35 {MCSymbolRefExpr::VK_COFF_IMGREL32, "IMGREL"},36 {AArch64::S_MACHO_PAGEOFF, "PAGEOFF"},37};38 39const MCAsmInfo::AtSpecifier ELFAtSpecifiers[] = {40 {AArch64::S_GOT, "GOT"},41 {AArch64::S_GOTPCREL, "GOTPCREL"},42 {AArch64::S_PLT, "PLT"},43 {AArch64::S_FUNCINIT, "FUNCINIT"},44};45 46const MCAsmInfo::AtSpecifier MachOAtSpecifiers[] = {47 {AArch64::S_MACHO_GOT, "GOT"},48 {AArch64::S_MACHO_GOTPAGE, "GOTPAGE"},49 {AArch64::S_MACHO_GOTPAGEOFF, "GOTPAGEOFF"},50 {AArch64::S_MACHO_PAGE, "PAGE"},51 {AArch64::S_MACHO_PAGEOFF, "PAGEOFF"},52 {AArch64::S_MACHO_TLVP, "TLVP"},53 {AArch64::S_MACHO_TLVPPAGE, "TLVPPAGE"},54 {AArch64::S_MACHO_TLVPPAGEOFF, "TLVPPAGEOFF"},55};56 57StringRef AArch64::getSpecifierName(AArch64::Specifier S) {58 // clang-format off59 switch (static_cast<uint32_t>(S)) {60 case AArch64::S_CALL: return "";61 case AArch64::S_LO12: return ":lo12:";62 case AArch64::S_ABS_G3: return ":abs_g3:";63 case AArch64::S_ABS_G2: return ":abs_g2:";64 case AArch64::S_ABS_G2_S: return ":abs_g2_s:";65 case AArch64::S_ABS_G2_NC: return ":abs_g2_nc:";66 case AArch64::S_ABS_G1: return ":abs_g1:";67 case AArch64::S_ABS_G1_S: return ":abs_g1_s:";68 case AArch64::S_ABS_G1_NC: return ":abs_g1_nc:";69 case AArch64::S_ABS_G0: return ":abs_g0:";70 case AArch64::S_ABS_G0_S: return ":abs_g0_s:";71 case AArch64::S_ABS_G0_NC: return ":abs_g0_nc:";72 case AArch64::S_PREL_G3: return ":prel_g3:";73 case AArch64::S_PREL_G2: return ":prel_g2:";74 case AArch64::S_PREL_G2_NC: return ":prel_g2_nc:";75 case AArch64::S_PREL_G1: return ":prel_g1:";76 case AArch64::S_PREL_G1_NC: return ":prel_g1_nc:";77 case AArch64::S_PREL_G0: return ":prel_g0:";78 case AArch64::S_PREL_G0_NC: return ":prel_g0_nc:";79 case AArch64::S_DTPREL_G2: return ":dtprel_g2:";80 case AArch64::S_DTPREL_G1: return ":dtprel_g1:";81 case AArch64::S_DTPREL_G1_NC: return ":dtprel_g1_nc:";82 case AArch64::S_DTPREL_G0: return ":dtprel_g0:";83 case AArch64::S_DTPREL_G0_NC: return ":dtprel_g0_nc:";84 case AArch64::S_DTPREL_HI12: return ":dtprel_hi12:";85 case AArch64::S_DTPREL_LO12: return ":dtprel_lo12:";86 case AArch64::S_DTPREL_LO12_NC: return ":dtprel_lo12_nc:";87 case AArch64::S_TPREL_G2: return ":tprel_g2:";88 case AArch64::S_TPREL_G1: return ":tprel_g1:";89 case AArch64::S_TPREL_G1_NC: return ":tprel_g1_nc:";90 case AArch64::S_TPREL_G0: return ":tprel_g0:";91 case AArch64::S_TPREL_G0_NC: return ":tprel_g0_nc:";92 case AArch64::S_TPREL_HI12: return ":tprel_hi12:";93 case AArch64::S_TPREL_LO12: return ":tprel_lo12:";94 case AArch64::S_TPREL_LO12_NC: return ":tprel_lo12_nc:";95 case AArch64::S_TLSDESC_LO12: return ":tlsdesc_lo12:";96 case AArch64::S_TLSDESC_AUTH_LO12: return ":tlsdesc_auth_lo12:";97 case AArch64::S_ABS_PAGE: return "";98 case AArch64::S_ABS_PAGE_NC: return ":pg_hi21_nc:";99 case AArch64::S_GOT: return ":got:";100 case AArch64::S_GOT_PAGE: return ":got:";101 case AArch64::S_GOT_PAGE_LO15: return ":gotpage_lo15:";102 case AArch64::S_GOT_LO12: return ":got_lo12:";103 case AArch64::S_GOTTPREL: return ":gottprel:";104 case AArch64::S_GOTTPREL_PAGE: return ":gottprel:";105 case AArch64::S_GOTTPREL_LO12_NC: return ":gottprel_lo12:";106 case AArch64::S_GOTTPREL_G1: return ":gottprel_g1:";107 case AArch64::S_GOTTPREL_G0_NC: return ":gottprel_g0_nc:";108 case AArch64::S_TLSDESC: return "";109 case AArch64::S_TLSDESC_PAGE: return ":tlsdesc:";110 case AArch64::S_TLSDESC_AUTH: return "";111 case AArch64::S_TLSDESC_AUTH_PAGE: return ":tlsdesc_auth:";112 case AArch64::S_SECREL_LO12: return ":secrel_lo12:";113 case AArch64::S_SECREL_HI12: return ":secrel_hi12:";114 case AArch64::S_GOT_AUTH: return ":got_auth:";115 case AArch64::S_GOT_AUTH_PAGE: return ":got_auth:";116 case AArch64::S_GOT_AUTH_LO12: return ":got_auth_lo12:";117 default:118 llvm_unreachable("Invalid relocation specifier");119 }120 // clang-format on121}122 123static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res,124 const MCAssembler *Asm) {125 if (!Expr.getSubExpr()->evaluateAsRelocatable(Res, Asm))126 return false;127 Res.setSpecifier(Expr.getSpecifier());128 return !Res.getSubSym();129}130 131AArch64MCAsmInfoDarwin::AArch64MCAsmInfoDarwin(bool IsILP32) {132 // We prefer NEON instructions to be printed in the short, Apple-specific133 // form when targeting Darwin.134 AssemblerDialect = AsmWriterVariant == Default ? Apple : AsmWriterVariant;135 136 PrivateGlobalPrefix = "L";137 PrivateLabelPrefix = "L";138 SeparatorString = "%%";139 CommentString = ";";140 CalleeSaveStackSlotSize = 8;141 CodePointerSize = IsILP32 ? 4 : 8;142 143 AlignmentIsInBytes = false;144 UsesELFSectionDirectiveForBSS = true;145 SupportsDebugInformation = true;146 UseDataRegionDirectives = true;147 UseAtForSpecifier = false;148 149 ExceptionsType = ExceptionHandling::DwarfCFI;150 151 initializeAtSpecifiers(MachOAtSpecifiers);152}153 154const MCExpr *AArch64MCAsmInfoDarwin::getExprForPersonalitySymbol(155 const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const {156 // On Darwin, we can reference dwarf symbols with foo@GOT-., which157 // is an indirect pc-relative reference. The default implementation158 // won't reference using the GOT, so we need this target-specific159 // version.160 MCContext &Context = Streamer.getContext();161 const MCExpr *Res =162 MCSymbolRefExpr::create(Sym, AArch64::S_MACHO_GOT, Context);163 MCSymbol *PCSym = Context.createTempSymbol();164 Streamer.emitLabel(PCSym);165 const MCExpr *PC = MCSymbolRefExpr::create(PCSym, Context);166 return MCBinaryExpr::createSub(Res, PC, Context);167}168 169void AArch64AuthMCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {170 bool WrapSubExprInParens = !isa<MCSymbolRefExpr>(getSubExpr());171 if (WrapSubExprInParens)172 OS << '(';173 MAI->printExpr(OS, *getSubExpr());174 if (WrapSubExprInParens)175 OS << ')';176 177 OS << "@AUTH(" << AArch64PACKeyIDToString(Key) << ',' << Discriminator;178 if (hasAddressDiversity())179 OS << ",addr";180 OS << ')';181}182 183void AArch64MCAsmInfoDarwin::printSpecifierExpr(184 raw_ostream &OS, const MCSpecifierExpr &Expr) const {185 if (auto *AE = dyn_cast<AArch64AuthMCExpr>(&Expr))186 return AE->print(OS, this);187 OS << AArch64::getSpecifierName(Expr.getSpecifier());188 printExpr(OS, *Expr.getSubExpr());189}190 191bool AArch64MCAsmInfoDarwin::evaluateAsRelocatableImpl(192 const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const {193 return evaluate(Expr, Res, Asm);194}195 196AArch64MCAsmInfoELF::AArch64MCAsmInfoELF(const Triple &T) {197 if (T.getArch() == Triple::aarch64_be)198 IsLittleEndian = false;199 200 // We prefer NEON instructions to be printed in the generic form when201 // targeting ELF.202 AssemblerDialect = AsmWriterVariant == Default ? Generic : AsmWriterVariant;203 204 CodePointerSize = T.getEnvironment() == Triple::GNUILP32 ? 4 : 8;205 206 // ".comm align is in bytes but .align is pow-2."207 AlignmentIsInBytes = false;208 209 CommentString = "//";210 PrivateGlobalPrefix = ".L";211 PrivateLabelPrefix = ".L";212 213 Data16bitsDirective = "\t.hword\t";214 Data32bitsDirective = "\t.word\t";215 Data64bitsDirective = "\t.xword\t";216 217 UseDataRegionDirectives = false;218 UseAtForSpecifier = false;219 220 WeakRefDirective = "\t.weak\t";221 222 SupportsDebugInformation = true;223 224 // Exceptions handling225 ExceptionsType = ExceptionHandling::DwarfCFI;226 227 HasIdentDirective = true;228 229 initializeAtSpecifiers(ELFAtSpecifiers);230}231 232void AArch64MCAsmInfoELF::printSpecifierExpr(233 raw_ostream &OS, const MCSpecifierExpr &Expr) const {234 if (auto *AE = dyn_cast<AArch64AuthMCExpr>(&Expr))235 return AE->print(OS, this);236 OS << AArch64::getSpecifierName(Expr.getSpecifier());237 printExpr(OS, *Expr.getSubExpr());238}239 240bool AArch64MCAsmInfoELF::evaluateAsRelocatableImpl(241 const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const {242 return evaluate(Expr, Res, Asm);243}244 245AArch64MCAsmInfoMicrosoftCOFF::AArch64MCAsmInfoMicrosoftCOFF() {246 PrivateGlobalPrefix = ".L";247 PrivateLabelPrefix = ".L";248 249 Data16bitsDirective = "\t.hword\t";250 Data32bitsDirective = "\t.word\t";251 Data64bitsDirective = "\t.xword\t";252 253 AlignmentIsInBytes = false;254 SupportsDebugInformation = true;255 CodePointerSize = 8;256 257 CommentString = "//";258 ExceptionsType = ExceptionHandling::WinEH;259 WinEHEncodingType = WinEH::EncodingType::Itanium;260 261 initializeAtSpecifiers(COFFAtSpecifiers);262}263 264void AArch64MCAsmInfoMicrosoftCOFF::printSpecifierExpr(265 raw_ostream &OS, const MCSpecifierExpr &Expr) const {266 OS << AArch64::getSpecifierName(Expr.getSpecifier());267 printExpr(OS, *Expr.getSubExpr());268}269 270bool AArch64MCAsmInfoMicrosoftCOFF::evaluateAsRelocatableImpl(271 const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const {272 return evaluate(Expr, Res, Asm);273}274 275AArch64MCAsmInfoGNUCOFF::AArch64MCAsmInfoGNUCOFF() {276 PrivateGlobalPrefix = ".L";277 PrivateLabelPrefix = ".L";278 279 Data16bitsDirective = "\t.hword\t";280 Data32bitsDirective = "\t.word\t";281 Data64bitsDirective = "\t.xword\t";282 283 AlignmentIsInBytes = false;284 SupportsDebugInformation = true;285 CodePointerSize = 8;286 287 CommentString = "//";288 ExceptionsType = ExceptionHandling::WinEH;289 WinEHEncodingType = WinEH::EncodingType::Itanium;290 291 initializeAtSpecifiers(COFFAtSpecifiers);292}293 294void AArch64MCAsmInfoGNUCOFF::printSpecifierExpr(295 raw_ostream &OS, const MCSpecifierExpr &Expr) const {296 OS << AArch64::getSpecifierName(Expr.getSpecifier());297 printExpr(OS, *Expr.getSubExpr());298}299 300bool AArch64MCAsmInfoGNUCOFF::evaluateAsRelocatableImpl(301 const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const {302 return evaluate(Expr, Res, Asm);303}304