brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.0 KiB · 130b6a6 Raw
340 lines · cpp
1//===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- C++ -*---------===//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 implements the ARMTargetStreamer class.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/ARMMCTargetDesc.h"14#include "llvm/MC/ConstantPools.h"15#include "llvm/MC/MCAsmInfo.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCExpr.h"18#include "llvm/MC/MCStreamer.h"19#include "llvm/MC/MCSubtargetInfo.h"20#include "llvm/Support/ARMBuildAttributes.h"21 22using namespace llvm;23 24//25// ARMTargetStreamer Implemenation26//27 28ARMTargetStreamer::ARMTargetStreamer(MCStreamer &S)29    : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {}30 31ARMTargetStreamer::~ARMTargetStreamer() = default;32 33// The constant pool handling is shared by all ARMTargetStreamer34// implementations.35const MCExpr *ARMTargetStreamer::addConstantPoolEntry(const MCExpr *Expr, SMLoc Loc) {36  return ConstantPools->addEntry(Streamer, Expr, 4, Loc);37}38 39void ARMTargetStreamer::emitCurrentConstantPool() {40  ConstantPools->emitForCurrentSection(Streamer);41  ConstantPools->clearCacheForCurrentSection(Streamer);42}43 44// finish() - write out any non-empty assembler constant pools.45void ARMTargetStreamer::emitConstantPools() {46  ConstantPools->emitAll(Streamer);47}48 49// reset() - Reset any state50void ARMTargetStreamer::reset() {}51 52void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {53  unsigned Size;54  char Buffer[4];55  const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian();56 57  switch (Suffix) {58  case '\0':59    Size = 4;60 61    for (unsigned II = 0, IE = Size; II != IE; II++) {62      const unsigned I = LittleEndian ? (Size - II - 1) : II;63      Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT);64    }65 66    break;67  case 'n':68  case 'w':69    Size = (Suffix == 'n' ? 2 : 4);70 71    // Thumb wide instructions are emitted as a pair of 16-bit words of the72    // appropriate endianness.73    for (unsigned II = 0, IE = Size; II != IE; II = II + 2) {74      const unsigned I0 = LittleEndian ? II + 0 : II + 1;75      const unsigned I1 = LittleEndian ? II + 1 : II + 0;76      Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT);77      Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT);78    }79 80    break;81  default:82    llvm_unreachable("Invalid Suffix");83  }84  getStreamer().emitBytes(StringRef(Buffer, Size));85}86 87// The remaining callbacks should be handled separately by each88// streamer.89void ARMTargetStreamer::emitFnStart() {}90void ARMTargetStreamer::emitFnEnd() {}91void ARMTargetStreamer::emitCantUnwind() {}92void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) {}93void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) {}94void ARMTargetStreamer::emitHandlerData() {}95void ARMTargetStreamer::emitSetFP(MCRegister FpReg, MCRegister SpReg,96                                  int64_t Offset) {}97void ARMTargetStreamer::emitMovSP(MCRegister Reg, int64_t Offset) {}98void ARMTargetStreamer::emitPad(int64_t Offset) {}99void ARMTargetStreamer::emitRegSave(const SmallVectorImpl<MCRegister> &RegList,100                                    bool isVector) {}101void ARMTargetStreamer::emitUnwindRaw(int64_t StackOffset,102                                      const SmallVectorImpl<uint8_t> &Opcodes) {103}104void ARMTargetStreamer::switchVendor(StringRef Vendor) {}105void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {}106void ARMTargetStreamer::emitTextAttribute(unsigned Attribute,107                                          StringRef String) {}108void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute,109                                             unsigned IntValue,110                                             StringRef StringValue) {}111void ARMTargetStreamer::emitArch(ARM::ArchKind Arch) {}112void ARMTargetStreamer::emitArchExtension(uint64_t ArchExt) {}113void ARMTargetStreamer::emitObjectArch(ARM::ArchKind Arch) {}114void ARMTargetStreamer::emitFPU(ARM::FPUKind FPU) {}115void ARMTargetStreamer::finishAttributeSection() {}116void ARMTargetStreamer::annotateTLSDescriptorSequence(117    const MCSymbolRefExpr *SRE) {}118void ARMTargetStreamer::emitSyntaxUnified() {}119void ARMTargetStreamer::emitCode16() {}120void ARMTargetStreamer::emitCode32() {}121void ARMTargetStreamer::emitThumbFunc(MCSymbol *Symbol) {}122void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {}123 124void ARMTargetStreamer::emitARMWinCFIAllocStack(unsigned Size, bool Wide) {}125void ARMTargetStreamer::emitARMWinCFISaveRegMask(unsigned Mask, bool Wide) {}126void ARMTargetStreamer::emitARMWinCFISaveSP(unsigned Reg) {}127void ARMTargetStreamer::emitARMWinCFISaveFRegs(unsigned First, unsigned Last) {}128void ARMTargetStreamer::emitARMWinCFISaveLR(unsigned Offset) {}129void ARMTargetStreamer::emitARMWinCFINop(bool Wide) {}130void ARMTargetStreamer::emitARMWinCFIPrologEnd(bool Fragment) {}131void ARMTargetStreamer::emitARMWinCFIEpilogStart(unsigned Condition) {}132void ARMTargetStreamer::emitARMWinCFIEpilogEnd() {}133void ARMTargetStreamer::emitARMWinCFICustom(unsigned Opcode) {}134 135static ARMBuildAttrs::CPUArch getArchForCPU(const MCSubtargetInfo &STI) {136  if (STI.getCPU() == "xscale")137    return ARMBuildAttrs::v5TEJ;138 139  if (STI.hasFeature(ARM::HasV9_0aOps))140    return ARMBuildAttrs::v9_A;141  else if (STI.hasFeature(ARM::HasV8Ops)) {142    if (STI.hasFeature(ARM::FeatureRClass))143      return ARMBuildAttrs::v8_R;144    return ARMBuildAttrs::v8_A;145  } else if (STI.hasFeature(ARM::HasV8_1MMainlineOps))146    return ARMBuildAttrs::v8_1_M_Main;147  else if (STI.hasFeature(ARM::HasV8MMainlineOps))148    return ARMBuildAttrs::v8_M_Main;149  else if (STI.hasFeature(ARM::HasV7Ops)) {150    if (STI.hasFeature(ARM::FeatureMClass) && STI.hasFeature(ARM::FeatureDSP))151      return ARMBuildAttrs::v7E_M;152    return ARMBuildAttrs::v7;153  } else if (STI.hasFeature(ARM::HasV6T2Ops))154    return ARMBuildAttrs::v6T2;155  else if (STI.hasFeature(ARM::HasV8MBaselineOps))156    return ARMBuildAttrs::v8_M_Base;157  else if (STI.hasFeature(ARM::HasV6MOps))158    return ARMBuildAttrs::v6S_M;159  else if (STI.hasFeature(ARM::HasV6Ops))160    return ARMBuildAttrs::v6;161  else if (STI.hasFeature(ARM::HasV5TEOps))162    return ARMBuildAttrs::v5TE;163  else if (STI.hasFeature(ARM::HasV5TOps))164    return ARMBuildAttrs::v5T;165  else if (STI.hasFeature(ARM::HasV4TOps))166    return ARMBuildAttrs::v4T;167  else168    return ARMBuildAttrs::v4;169}170 171static bool isV8M(const MCSubtargetInfo &STI) {172  // Note that v8M Baseline is a subset of v6T2!173  return (STI.hasFeature(ARM::HasV8MBaselineOps) &&174          !STI.hasFeature(ARM::HasV6T2Ops)) ||175         STI.hasFeature(ARM::HasV8MMainlineOps);176}177 178/// Emit the build attributes that only depend on the hardware that we expect179// /to be available, and not on the ABI, or any source-language choices.180void ARMTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {181  switchVendor("aeabi");182 183  const StringRef CPUString = STI.getCPU();184  if (!CPUString.empty() && !CPUString.starts_with("generic")) {185    // FIXME: remove krait check when GNU tools support krait cpu186    if (STI.hasFeature(ARM::ProcKrait)) {187      emitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a9");188      // We consider krait as a "cortex-a9" + hwdiv CPU189      // Enable hwdiv through ".arch_extension idiv"190      if (STI.hasFeature(ARM::FeatureHWDivThumb) ||191          STI.hasFeature(ARM::FeatureHWDivARM))192        emitArchExtension(ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM);193    } else {194      emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);195    }196  }197 198  emitAttribute(ARMBuildAttrs::CPU_arch, getArchForCPU(STI));199 200  if (STI.hasFeature(ARM::FeatureAClass)) {201    emitAttribute(ARMBuildAttrs::CPU_arch_profile,202                      ARMBuildAttrs::ApplicationProfile);203  } else if (STI.hasFeature(ARM::FeatureRClass)) {204    emitAttribute(ARMBuildAttrs::CPU_arch_profile,205                      ARMBuildAttrs::RealTimeProfile);206  } else if (STI.hasFeature(ARM::FeatureMClass)) {207    emitAttribute(ARMBuildAttrs::CPU_arch_profile,208                      ARMBuildAttrs::MicroControllerProfile);209  }210 211  emitAttribute(ARMBuildAttrs::ARM_ISA_use, STI.hasFeature(ARM::FeatureNoARM)212                                                ? ARMBuildAttrs::Not_Allowed213                                                : ARMBuildAttrs::Allowed);214 215  if (isV8M(STI)) {216    emitAttribute(ARMBuildAttrs::THUMB_ISA_use,217                      ARMBuildAttrs::AllowThumbDerived);218  } else if (STI.hasFeature(ARM::FeatureThumb2)) {219    emitAttribute(ARMBuildAttrs::THUMB_ISA_use,220                      ARMBuildAttrs::AllowThumb32);221  } else if (STI.hasFeature(ARM::HasV4TOps)) {222    emitAttribute(ARMBuildAttrs::THUMB_ISA_use, ARMBuildAttrs::Allowed);223  }224 225  if (STI.hasFeature(ARM::FeatureNEON)) {226    /* NEON is not exactly a VFP architecture, but GAS emit one of227     * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */228    if (STI.hasFeature(ARM::FeatureFPARMv8)) {229      if (STI.hasFeature(ARM::FeatureCrypto))230        emitFPU(ARM::FK_CRYPTO_NEON_FP_ARMV8);231      else232        emitFPU(ARM::FK_NEON_FP_ARMV8);233    } else if (STI.hasFeature(ARM::FeatureVFP4))234      emitFPU(ARM::FK_NEON_VFPV4);235    else236      emitFPU(STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_NEON_FP16237                                               : ARM::FK_NEON);238    // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture239    if (STI.hasFeature(ARM::HasV8Ops))240      emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,241                    STI.hasFeature(ARM::HasV8_1aOps)242                        ? ARMBuildAttrs::AllowNeonARMv8_1a243                        : ARMBuildAttrs::AllowNeonARMv8);244  } else {245    if (STI.hasFeature(ARM::FeatureFPARMv8_D16_SP)) {246      // FPv5 and FP-ARMv8 have the same instructions, so are modeled as one247      // FPU, but there are two different names for it depending on the CPU.248      if (STI.hasFeature(ARM::FeatureD32))249        emitFPU(ARM::FK_FP_ARMV8);250      else {251        emitFPU(STI.hasFeature(ARM::FeatureFP64) ? ARM::FK_FPV5_D16252                                                 : ARM::FK_FPV5_SP_D16);253        if (STI.hasFeature(ARM::HasMVEFloatOps))254          emitArchExtension(ARM::AEK_MVE | ARM::AEK_DSP | ARM::AEK_FP);255      }256    } else if (STI.hasFeature(ARM::FeatureVFP4_D16_SP))257      emitFPU(STI.hasFeature(ARM::FeatureD32)258                  ? ARM::FK_VFPV4259                  : (STI.hasFeature(ARM::FeatureFP64) ? ARM::FK_VFPV4_D16260                                                      : ARM::FK_FPV4_SP_D16));261    else if (STI.hasFeature(ARM::FeatureVFP3_D16_SP))262      emitFPU(263          STI.hasFeature(ARM::FeatureD32)264              // +d32265              ? (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3_FP16266                                                  : ARM::FK_VFPV3)267              // -d32268              : (STI.hasFeature(ARM::FeatureFP64)269                     ? (STI.hasFeature(ARM::FeatureFP16)270                            ? ARM::FK_VFPV3_D16_FP16271                            : ARM::FK_VFPV3_D16)272                     : (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3XD_FP16273                                                         : ARM::FK_VFPV3XD)));274    else if (STI.hasFeature(ARM::FeatureVFP2_SP))275      emitFPU(ARM::FK_VFPV2);276  }277 278  // ABI_HardFP_use attribute to indicate single precision FP.279  if (STI.hasFeature(ARM::FeatureVFP2_SP) && !STI.hasFeature(ARM::FeatureFP64))280    emitAttribute(ARMBuildAttrs::ABI_HardFP_use,281                  ARMBuildAttrs::HardFPSinglePrecision);282 283  if (STI.hasFeature(ARM::FeatureFP16))284    emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP);285 286  if (STI.hasFeature(ARM::FeatureMP))287    emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP);288 289  if (STI.hasFeature(ARM::HasMVEFloatOps))290    emitAttribute(ARMBuildAttrs::MVE_arch, ARMBuildAttrs::AllowMVEIntegerAndFloat);291  else if (STI.hasFeature(ARM::HasMVEIntegerOps))292    emitAttribute(ARMBuildAttrs::MVE_arch, ARMBuildAttrs::AllowMVEInteger);293 294  // Hardware divide in ARM mode is part of base arch, starting from ARMv8.295  // If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M).296  // It is not possible to produce DisallowDIV: if hwdiv is present in the base297  // arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits.298  // AllowDIVExt is only emitted if hwdiv isn't available in the base arch;299  // otherwise, the default value (AllowDIVIfExists) applies.300  if (STI.hasFeature(ARM::FeatureHWDivARM) && !STI.hasFeature(ARM::HasV8Ops))301    emitAttribute(ARMBuildAttrs::DIV_use, ARMBuildAttrs::AllowDIVExt);302 303  if (STI.hasFeature(ARM::FeatureDSP) && isV8M(STI))304    emitAttribute(ARMBuildAttrs::DSP_extension, ARMBuildAttrs::Allowed);305 306  if (STI.hasFeature(ARM::FeatureStrictAlign))307    emitAttribute(ARMBuildAttrs::CPU_unaligned_access,308                  ARMBuildAttrs::Not_Allowed);309  else310    emitAttribute(ARMBuildAttrs::CPU_unaligned_access,311                  ARMBuildAttrs::Allowed);312 313  if (STI.hasFeature(ARM::FeatureTrustZone) &&314      STI.hasFeature(ARM::FeatureVirtualization))315    emitAttribute(ARMBuildAttrs::Virtualization_use,316                  ARMBuildAttrs::AllowTZVirtualization);317  else if (STI.hasFeature(ARM::FeatureTrustZone))318    emitAttribute(ARMBuildAttrs::Virtualization_use, ARMBuildAttrs::AllowTZ);319  else if (STI.hasFeature(ARM::FeatureVirtualization))320    emitAttribute(ARMBuildAttrs::Virtualization_use,321                  ARMBuildAttrs::AllowVirtualization);322 323  if (STI.hasFeature(ARM::FeaturePACBTI)) {324    emitAttribute(ARMBuildAttrs::PAC_extension, ARMBuildAttrs::AllowPAC);325    emitAttribute(ARMBuildAttrs::BTI_extension, ARMBuildAttrs::AllowBTI);326  }327}328 329MCTargetStreamer *330llvm::createARMObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {331  const Triple &TT = STI.getTargetTriple();332  if (TT.isOSBinFormatELF())333    return createARMObjectTargetELFStreamer(S);334  if (TT.isOSBinFormatCOFF())335    return createARMObjectTargetWinCOFFStreamer(S);336  if (TT.isOSBinFormatMachO())337    return createARMObjectTargetMachOStreamer(S);338  return new ARMTargetStreamer(S);339}340