256 lines · cpp
1//===-- PPCMCAsmInfo.cpp - PPC 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 MCAsmInfoDarwin properties.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/PPCMCAsmInfo.h"14#include "llvm/MC/MCExpr.h"15#include "llvm/Support/raw_ostream.h"16#include "llvm/TargetParser/Triple.h"17 18using namespace llvm;19 20void PPCELFMCAsmInfo::anchor() { }21 22const MCAsmInfo::AtSpecifier elfAtSpecifiers[] = {23 {PPC::S_DTPREL, "DTPREL"},24 {PPC::S_GOT, "GOT"},25 {PPC::S_GOT_HA, "got@ha"},26 {PPC::S_GOT_HI, "got@h"},27 {PPC::S_GOT_LO, "got@l"},28 {PPC::S_HA, "ha"},29 {PPC::S_HI, "h"},30 {PPC::S_HIGH, "high"},31 {PPC::S_HIGHA, "higha"},32 {PPC::S_HIGHER, "higher"},33 {PPC::S_HIGHERA, "highera"},34 {PPC::S_HIGHEST, "highest"},35 {PPC::S_HIGHESTA, "highesta"},36 {PPC::S_LO, "l"},37 {PPC::S_PCREL, "PCREL"},38 {PPC::S_PLT, "PLT"},39 {PPC::S_TLSGD, "tlsgd"},40 {PPC::S_TLSLD, "tlsld"},41 {PPC::S_TOC, "toc"},42 {PPC::S_TOCBASE, "tocbase"},43 {PPC::S_TOC_HA, "toc@ha"},44 {PPC::S_TOC_HI, "toc@h"},45 {PPC::S_TOC_LO, "toc@l"},46 {PPC::S_TPREL, "TPREL"},47 {PPC::S_AIX_TLSGD, "gd"},48 {PPC::S_AIX_TLSGDM, "m"},49 {PPC::S_AIX_TLSIE, "ie"},50 {PPC::S_AIX_TLSLD, "ld"},51 {PPC::S_AIX_TLSLE, "le"},52 {PPC::S_AIX_TLSML, "ml"},53 {PPC::S_DTPMOD, "dtpmod"},54 {PPC::S_DTPREL_HA, "dtprel@ha"},55 {PPC::S_DTPREL_HI, "dtprel@h"},56 {PPC::S_DTPREL_HIGH, "dtprel@high"},57 {PPC::S_DTPREL_HIGHA, "dtprel@higha"},58 {PPC::S_DTPREL_HIGHER, "dtprel@higher"},59 {PPC::S_DTPREL_HIGHERA, "dtprel@highera"},60 {PPC::S_DTPREL_HIGHEST, "dtprel@highest"},61 {PPC::S_DTPREL_HIGHESTA, "dtprel@highesta"},62 {PPC::S_DTPREL_LO, "dtprel@l"},63 {PPC::S_GOT_DTPREL, "got@dtprel"},64 {PPC::S_GOT_DTPREL_HA, "got@dtprel@ha"},65 {PPC::S_GOT_DTPREL_HI, "got@dtprel@h"},66 {PPC::S_GOT_DTPREL_LO, "got@dtprel@l"},67 {PPC::S_GOT_PCREL, "got@pcrel"},68 {PPC::S_GOT_TLSGD, "got@tlsgd"},69 {PPC::S_GOT_TLSGD_HA, "got@tlsgd@ha"},70 {PPC::S_GOT_TLSGD_HI, "got@tlsgd@h"},71 {PPC::S_GOT_TLSGD_LO, "got@tlsgd@l"},72 {PPC::S_GOT_TLSGD_PCREL, "got@tlsgd@pcrel"},73 {PPC::S_GOT_TLSLD, "got@tlsld"},74 {PPC::S_GOT_TLSLD_HA, "got@tlsld@ha"},75 {PPC::S_GOT_TLSLD_HI, "got@tlsld@h"},76 {PPC::S_GOT_TLSLD_LO, "got@tlsld@l"},77 {PPC::S_GOT_TLSLD_PCREL, "got@tlsld@pcrel"},78 {PPC::S_GOT_TPREL, "got@tprel"},79 {PPC::S_GOT_TPREL_HA, "got@tprel@ha"},80 {PPC::S_GOT_TPREL_HI, "got@tprel@h"},81 {PPC::S_GOT_TPREL_LO, "got@tprel@l"},82 {PPC::S_GOT_TPREL_PCREL, "got@tprel@pcrel"},83 {PPC::S_LOCAL, "local"},84 {PPC::S_NOTOC, "notoc"},85 {PPC::S_PCREL_OPT, "<<invalid>>"},86 {PPC::S_TLS, "tls"},87 {PPC::S_TLS_PCREL, "tls@pcrel"},88 {PPC::S_TPREL_HA, "tprel@ha"},89 {PPC::S_TPREL_HI, "tprel@h"},90 {PPC::S_TPREL_HIGH, "tprel@high"},91 {PPC::S_TPREL_HIGHA, "tprel@higha"},92 {PPC::S_TPREL_HIGHER, "tprel@higher"},93 {PPC::S_TPREL_HIGHERA, "tprel@highera"},94 {PPC::S_TPREL_HIGHEST, "tprel@highest"},95 {PPC::S_TPREL_HIGHESTA, "tprel@highesta"},96 {PPC::S_TPREL_LO, "tprel@l"},97};98 99const MCAsmInfo::AtSpecifier xcoffAtSpecifiers[] = {100 // clang-format off101 {PPC::S_AIX_TLSGD, "gd"},102 {PPC::S_AIX_TLSGDM, "m"},103 {PPC::S_AIX_TLSIE, "ie"},104 {PPC::S_AIX_TLSLD, "ld"},105 {PPC::S_AIX_TLSLE, "le"},106 {PPC::S_AIX_TLSML, "ml"},107 {PPC::S_L, "l"},108 {PPC::S_U, "u"},109 // clang-format on110};111 112static std::optional<int64_t> evaluateAsInt64(uint16_t specifier,113 int64_t Value) {114 switch (specifier) {115 case PPC::S_LO:116 return Value & 0xffff;117 case PPC::S_HI:118 return (Value >> 16) & 0xffff;119 case PPC::S_HA:120 return ((Value + 0x8000) >> 16) & 0xffff;121 case PPC::S_HIGH:122 return (Value >> 16) & 0xffff;123 case PPC::S_HIGHA:124 return ((Value + 0x8000) >> 16) & 0xffff;125 case PPC::S_HIGHER:126 return (Value >> 32) & 0xffff;127 case PPC::S_HIGHERA:128 return ((Value + 0x8000) >> 32) & 0xffff;129 case PPC::S_HIGHEST:130 return (Value >> 48) & 0xffff;131 case PPC::S_HIGHESTA:132 return ((Value + 0x8000) >> 48) & 0xffff;133 default:134 return {};135 }136}137 138bool PPC::evaluateAsConstant(const MCSpecifierExpr &Expr, int64_t &Res) {139 MCValue Value;140 141 if (!Expr.getSubExpr()->evaluateAsRelocatable(Value, nullptr))142 return false;143 144 if (!Value.isAbsolute())145 return false;146 auto Tmp = evaluateAsInt64(Expr.getSpecifier(), Value.getConstant());147 if (!Tmp)148 return false;149 Res = *Tmp;150 return true;151}152 153static bool evaluateAsRelocatable(const MCSpecifierExpr &Expr, MCValue &Res,154 const MCAssembler *Asm) {155 if (!Expr.getSubExpr()->evaluateAsRelocatable(Res, Asm))156 return false;157 158 // The signedness of the result is dependent on the instruction operand. E.g.159 // in addis 3,3,65535@l, 65535@l is signed. In the absence of information at160 // parse time (!Asm), disable the folding.161 std::optional<int64_t> MaybeInt =162 evaluateAsInt64(Expr.getSpecifier(), Res.getConstant());163 if (Res.isAbsolute() && MaybeInt) {164 Res = MCValue::get(*MaybeInt);165 } else {166 Res.setSpecifier(Expr.getSpecifier());167 }168 169 return true;170}171 172PPCELFMCAsmInfo::PPCELFMCAsmInfo(bool is64Bit, const Triple& T) {173 // FIXME: This is not always needed. For example, it is not needed in the174 // v2 abi.175 NeedsLocalForSize = true;176 177 if (is64Bit) {178 CodePointerSize = CalleeSaveStackSlotSize = 8;179 }180 IsLittleEndian =181 T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle;182 183 // ".comm align is in bytes but .align is pow-2."184 AlignmentIsInBytes = false;185 186 CommentString = "#";187 188 // Uses '.section' before '.bss' directive189 UsesELFSectionDirectiveForBSS = true;190 191 // Debug Information192 SupportsDebugInformation = true;193 194 DollarIsPC = true;195 AllowDollarAtStartOfIdentifier = false;196 197 // Set up DWARF directives198 MinInstAlignment = 4;199 200 // Exceptions handling201 ExceptionsType = ExceptionHandling::DwarfCFI;202 203 ZeroDirective = "\t.space\t";204 Data64bitsDirective = is64Bit ? "\t.quad\t" : nullptr;205 AssemblerDialect = 1; // New-Style mnemonics.206 LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;207 208 initializeAtSpecifiers(elfAtSpecifiers);209}210 211void PPCELFMCAsmInfo::printSpecifierExpr(raw_ostream &OS,212 const MCSpecifierExpr &Expr) const {213 printExpr(OS, *Expr.getSubExpr());214 OS << '@' << getSpecifierName(Expr.getSpecifier());215}216 217bool PPCELFMCAsmInfo::evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr,218 MCValue &Res,219 const MCAssembler *Asm) const {220 return evaluateAsRelocatable(Expr, Res, Asm);221}222 223PPCXCOFFMCAsmInfo::PPCXCOFFMCAsmInfo(bool Is64Bit, const Triple &T) {224 if (T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle)225 report_fatal_error("XCOFF is not supported for little-endian targets");226 CodePointerSize = CalleeSaveStackSlotSize = Is64Bit ? 8 : 4;227 228 // A size of 8 is only supported by the assembler under 64-bit.229 Data64bitsDirective = Is64Bit ? "\t.vbyte\t8, " : nullptr;230 231 // Debug Information232 SupportsDebugInformation = true;233 234 // Set up DWARF directives235 MinInstAlignment = 4;236 237 // Support $ as PC in inline asm238 DollarIsPC = true;239 AllowDollarAtStartOfIdentifier = false;240 241 UsesSetToEquateSymbol = true;242 243 initializeAtSpecifiers(xcoffAtSpecifiers);244}245 246void PPCXCOFFMCAsmInfo::printSpecifierExpr(raw_ostream &OS,247 const MCSpecifierExpr &Expr) const {248 printExpr(OS, *Expr.getSubExpr());249 OS << '@' << getSpecifierName(Expr.getSpecifier());250}251 252bool PPCXCOFFMCAsmInfo::evaluateAsRelocatableImpl(253 const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const {254 return evaluateAsRelocatable(Expr, Res, Asm);255}256