| //===-- MipsMCAsmInfo.cpp - Mips Asm Properties ---------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains the declarations of the MipsMCAsmInfo properties. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "MipsMCAsmInfo.h" |
| #include "MipsABIInfo.h" |
| #include "llvm/MC/MCValue.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/TargetParser/Triple.h" |
| |
| using namespace llvm; |
| |
| void MipsELFMCAsmInfo::anchor() {} |
| |
| MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple, |
| const MCTargetOptions &Options) { |
| IsLittleEndian = TheTriple.isLittleEndian(); |
| |
| MipsABIInfo ABI = |
| MipsABIInfo::computeTargetABI(TheTriple, Options.getABIName()); |
| |
| if (TheTriple.isMIPS64() && !ABI.IsN32()) |
| CodePointerSize = CalleeSaveStackSlotSize = 8; |
| |
| if (ABI.IsO32()) |
| PrivateGlobalPrefix = "$"; |
| else if (ABI.IsN32() || ABI.IsN64()) |
| PrivateGlobalPrefix = ".L"; |
| PrivateLabelPrefix = PrivateGlobalPrefix; |
| |
| AlignmentIsInBytes = false; |
| Data16bitsDirective = "\t.2byte\t"; |
| Data32bitsDirective = "\t.4byte\t"; |
| Data64bitsDirective = "\t.8byte\t"; |
| CommentString = "#"; |
| AllowDollarAtStartOfIdentifier = false; |
| ZeroDirective = "\t.space\t"; |
| UseAssignmentForEHBegin = true; |
| SupportsDebugInformation = true; |
| ExceptionsType = ExceptionHandling::DwarfCFI; |
| DwarfRegNumForCFI = true; |
| } |
| |
| void MipsCOFFMCAsmInfo::anchor() {} |
| |
| MipsCOFFMCAsmInfo::MipsCOFFMCAsmInfo() { |
| HasSingleParameterDotFile = true; |
| WinEHEncodingType = WinEH::EncodingType::Itanium; |
| |
| ExceptionsType = ExceptionHandling::WinEH; |
| |
| PrivateGlobalPrefix = ".L"; |
| PrivateLabelPrefix = ".L"; |
| AllowAtInName = true; |
| } |
| |
| const MCSpecifierExpr *Mips::createGpOff(const MCExpr *Expr, Mips::Specifier S, |
| MCContext &Ctx) { |
| Expr = MCSpecifierExpr::create(Expr, Mips::S_GPREL, Ctx); |
| Expr = MCSpecifierExpr::create(Expr, Mips::S_NEG, Ctx); |
| return MCSpecifierExpr::create(Expr, S, Ctx); |
| } |
| |
| static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS, |
| const MCSpecifierExpr &Expr) { |
| int64_t AbsVal; |
| |
| switch (Expr.getSpecifier()) { |
| case Mips::S_None: |
| case Mips::S_Special: |
| llvm_unreachable("Mips::S_None and MEK_Special are invalid"); |
| break; |
| case Mips::S_DTPREL: |
| // Mips::S_DTPREL is used for marking TLS DIEExpr only |
| // and contains a regular sub-expression. |
| MAI.printExpr(OS, *Expr.getSubExpr()); |
| return; |
| case Mips::S_CALL_HI16: |
| OS << "%call_hi"; |
| break; |
| case Mips::S_CALL_LO16: |
| OS << "%call_lo"; |
| break; |
| case Mips::S_DTPREL_HI: |
| OS << "%dtprel_hi"; |
| break; |
| case Mips::S_DTPREL_LO: |
| OS << "%dtprel_lo"; |
| break; |
| case Mips::S_GOT: |
| OS << "%got"; |
| break; |
| case Mips::S_GOTTPREL: |
| OS << "%gottprel"; |
| break; |
| case Mips::S_GOT_CALL: |
| OS << "%call16"; |
| break; |
| case Mips::S_GOT_DISP: |
| OS << "%got_disp"; |
| break; |
| case Mips::S_GOT_HI16: |
| OS << "%got_hi"; |
| break; |
| case Mips::S_GOT_LO16: |
| OS << "%got_lo"; |
| break; |
| case Mips::S_GOT_PAGE: |
| OS << "%got_page"; |
| break; |
| case Mips::S_GOT_OFST: |
| OS << "%got_ofst"; |
| break; |
| case Mips::S_GPREL: |
| OS << "%gp_rel"; |
| break; |
| case Mips::S_HI: |
| OS << "%hi"; |
| break; |
| case Mips::S_HIGHER: |
| OS << "%higher"; |
| break; |
| case Mips::S_HIGHEST: |
| OS << "%highest"; |
| break; |
| case Mips::S_LO: |
| OS << "%lo"; |
| break; |
| case Mips::S_NEG: |
| OS << "%neg"; |
| break; |
| case Mips::S_PCREL_HI16: |
| OS << "%pcrel_hi"; |
| break; |
| case Mips::S_PCREL_LO16: |
| OS << "%pcrel_lo"; |
| break; |
| case Mips::S_TLSGD: |
| OS << "%tlsgd"; |
| break; |
| case Mips::S_TLSLDM: |
| OS << "%tlsldm"; |
| break; |
| case Mips::S_TPREL_HI: |
| OS << "%tprel_hi"; |
| break; |
| case Mips::S_TPREL_LO: |
| OS << "%tprel_lo"; |
| break; |
| } |
| |
| OS << '('; |
| if (Expr.evaluateAsAbsolute(AbsVal)) |
| OS << AbsVal; |
| else |
| MAI.printExpr(OS, *Expr.getSubExpr()); |
| OS << ')'; |
| } |
| |
| bool Mips::isGpOff(const MCSpecifierExpr &E) { |
| if (E.getSpecifier() == Mips::S_HI || E.getSpecifier() == Mips::S_LO) { |
| if (const auto *S1 = dyn_cast<const MCSpecifierExpr>(E.getSubExpr())) { |
| if (const auto *S2 = dyn_cast<const MCSpecifierExpr>(S1->getSubExpr())) { |
| if (S1->getSpecifier() == Mips::S_NEG && |
| S2->getSpecifier() == Mips::S_GPREL) { |
| // S = E.getSpecifier(); |
| return true; |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res, |
| const MCAssembler *Asm) { |
| // Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X))) |
| // special cases. |
| if (Mips::isGpOff(Expr)) { |
| const MCExpr *SubExpr = |
| cast<MCSpecifierExpr>( |
| cast<MCSpecifierExpr>(Expr.getSubExpr())->getSubExpr()) |
| ->getSubExpr(); |
| if (!SubExpr->evaluateAsRelocatable(Res, Asm)) |
| return false; |
| |
| Res.setSpecifier(Mips::S_Special); |
| return true; |
| } |
| |
| if (!Expr.getSubExpr()->evaluateAsRelocatable(Res, Asm)) |
| return false; |
| Res.setSpecifier(Expr.getSpecifier()); |
| return !Res.getSubSym(); |
| } |
| |
| void MipsELFMCAsmInfo::printSpecifierExpr(raw_ostream &OS, |
| const MCSpecifierExpr &Expr) const { |
| printImpl(*this, OS, Expr); |
| } |
| |
| bool MipsELFMCAsmInfo::evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, |
| MCValue &Res, |
| const MCAssembler *Asm) const { |
| return evaluate(Expr, Res, Asm); |
| } |
| |
| void MipsCOFFMCAsmInfo::printSpecifierExpr(raw_ostream &OS, |
| const MCSpecifierExpr &Expr) const { |
| printImpl(*this, OS, Expr); |
| } |
| |
| bool MipsCOFFMCAsmInfo::evaluateAsRelocatableImpl( |
| const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const { |
| return evaluate(Expr, Res, Asm); |
| } |