| //===-- LoongArchMCAsmInfo.cpp - LoongArch Asm properties ------*- C++ -*--===// |
| // |
| // 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 LoongArchMCAsmInfo properties. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "LoongArchMCAsmInfo.h" |
| #include "llvm/BinaryFormat/Dwarf.h" |
| #include "llvm/BinaryFormat/ELF.h" |
| #include "llvm/MC/MCContext.h" |
| #include "llvm/MC/MCStreamer.h" |
| #include "llvm/TargetParser/Triple.h" |
| |
| using namespace llvm; |
| |
| const LoongArchMCExpr *LoongArchMCExpr::create(const MCExpr *Expr, uint16_t S, |
| MCContext &Ctx, bool Hint) { |
| return new (Ctx) LoongArchMCExpr(Expr, S, Hint); |
| } |
| |
| static StringRef getLoongArchSpecifierName(uint16_t S) { |
| switch (S) { |
| default: |
| llvm_unreachable("Invalid ELF symbol kind"); |
| case ELF::R_LARCH_B16: |
| return "b16"; |
| case ELF::R_LARCH_B21: |
| return "b21"; |
| case ELF::R_LARCH_MARK_LA: |
| case ELF::R_LARCH_ABS_HI20: |
| return "abs_hi20"; |
| case ELF::R_LARCH_ABS_LO12: |
| return "abs_lo12"; |
| case ELF::R_LARCH_ABS64_LO20: |
| return "abs64_lo20"; |
| case ELF::R_LARCH_ABS64_HI12: |
| return "abs64_hi12"; |
| case ELF::R_LARCH_PCALA_HI20: |
| return "pc_hi20"; |
| case ELF::R_LARCH_PCALA_LO12: |
| return "pc_lo12"; |
| case ELF::R_LARCH_PCALA64_LO20: |
| return "pc64_lo20"; |
| case ELF::R_LARCH_PCALA64_HI12: |
| return "pc64_hi12"; |
| case ELF::R_LARCH_GOT_PC_HI20: |
| return "got_pc_hi20"; |
| case ELF::R_LARCH_GOT_PC_LO12: |
| return "got_pc_lo12"; |
| case ELF::R_LARCH_GOT64_PC_LO20: |
| return "got64_pc_lo20"; |
| case ELF::R_LARCH_GOT64_PC_HI12: |
| return "got64_pc_hi12"; |
| case ELF::R_LARCH_GOT_HI20: |
| return "got_hi20"; |
| case ELF::R_LARCH_GOT_LO12: |
| return "got_lo12"; |
| case ELF::R_LARCH_GOT64_LO20: |
| return "got64_lo20"; |
| case ELF::R_LARCH_GOT64_HI12: |
| return "got64_hi12"; |
| case ELF::R_LARCH_TLS_LE_HI20: |
| return "le_hi20"; |
| case ELF::R_LARCH_TLS_LE_LO12: |
| return "le_lo12"; |
| case ELF::R_LARCH_TLS_LE64_LO20: |
| return "le64_lo20"; |
| case ELF::R_LARCH_TLS_LE64_HI12: |
| return "le64_hi12"; |
| case ELF::R_LARCH_TLS_IE_PC_HI20: |
| return "ie_pc_hi20"; |
| case ELF::R_LARCH_TLS_IE_PC_LO12: |
| return "ie_pc_lo12"; |
| case ELF::R_LARCH_TLS_IE64_PC_LO20: |
| return "ie64_pc_lo20"; |
| case ELF::R_LARCH_TLS_IE64_PC_HI12: |
| return "ie64_pc_hi12"; |
| case ELF::R_LARCH_TLS_IE_HI20: |
| return "ie_hi20"; |
| case ELF::R_LARCH_TLS_IE_LO12: |
| return "ie_lo12"; |
| case ELF::R_LARCH_TLS_IE64_LO20: |
| return "ie64_lo20"; |
| case ELF::R_LARCH_TLS_IE64_HI12: |
| return "ie64_hi12"; |
| case ELF::R_LARCH_TLS_LD_PC_HI20: |
| return "ld_pc_hi20"; |
| case ELF::R_LARCH_TLS_LD_HI20: |
| return "ld_hi20"; |
| case ELF::R_LARCH_TLS_GD_PC_HI20: |
| return "gd_pc_hi20"; |
| case ELF::R_LARCH_TLS_GD_HI20: |
| return "gd_hi20"; |
| case ELF::R_LARCH_CALL36: |
| return "call36"; |
| case ELF::R_LARCH_TLS_DESC_PC_HI20: |
| return "desc_pc_hi20"; |
| case ELF::R_LARCH_TLS_DESC_PC_LO12: |
| return "desc_pc_lo12"; |
| case ELF::R_LARCH_TLS_DESC64_PC_LO20: |
| return "desc64_pc_lo20"; |
| case ELF::R_LARCH_TLS_DESC64_PC_HI12: |
| return "desc64_pc_hi12"; |
| case ELF::R_LARCH_TLS_DESC_HI20: |
| return "desc_hi20"; |
| case ELF::R_LARCH_TLS_DESC_LO12: |
| return "desc_lo12"; |
| case ELF::R_LARCH_TLS_DESC64_LO20: |
| return "desc64_lo20"; |
| case ELF::R_LARCH_TLS_DESC64_HI12: |
| return "desc64_hi12"; |
| case ELF::R_LARCH_TLS_DESC_LD: |
| return "desc_ld"; |
| case ELF::R_LARCH_TLS_DESC_CALL: |
| return "desc_call"; |
| case ELF::R_LARCH_TLS_LE_HI20_R: |
| return "le_hi20_r"; |
| case ELF::R_LARCH_TLS_LE_ADD_R: |
| return "le_add_r"; |
| case ELF::R_LARCH_TLS_LE_LO12_R: |
| return "le_lo12_r"; |
| case ELF::R_LARCH_PCREL20_S2: |
| return "pcrel_20"; |
| case ELF::R_LARCH_TLS_LD_PCREL20_S2: |
| return "ld_pcrel_20"; |
| case ELF::R_LARCH_TLS_GD_PCREL20_S2: |
| return "gd_pcrel_20"; |
| case ELF::R_LARCH_TLS_DESC_PCREL20_S2: |
| return "desc_pcrel_20"; |
| } |
| } |
| |
| LoongArchMCExpr::Specifier LoongArch::parseSpecifier(StringRef name) { |
| return StringSwitch<LoongArchMCExpr::Specifier>(name) |
| .Case("plt", ELF::R_LARCH_B26) |
| .Case("b16", ELF::R_LARCH_B16) |
| .Case("b21", ELF::R_LARCH_B21) |
| .Case("b26", ELF::R_LARCH_B26) |
| .Case("abs_hi20", ELF::R_LARCH_ABS_HI20) |
| .Case("abs_lo12", ELF::R_LARCH_ABS_LO12) |
| .Case("abs64_lo20", ELF::R_LARCH_ABS64_LO20) |
| .Case("abs64_hi12", ELF::R_LARCH_ABS64_HI12) |
| .Case("pc_hi20", ELF::R_LARCH_PCALA_HI20) |
| .Case("pc_lo12", ELF::R_LARCH_PCALA_LO12) |
| .Case("pc64_lo20", ELF::R_LARCH_PCALA64_LO20) |
| .Case("pc64_hi12", ELF::R_LARCH_PCALA64_HI12) |
| .Case("got_pc_hi20", ELF::R_LARCH_GOT_PC_HI20) |
| .Case("got_pc_lo12", ELF::R_LARCH_GOT_PC_LO12) |
| .Case("got64_pc_lo20", ELF::R_LARCH_GOT64_PC_LO20) |
| .Case("got64_pc_hi12", ELF::R_LARCH_GOT64_PC_HI12) |
| .Case("got_hi20", ELF::R_LARCH_GOT_HI20) |
| .Case("got_lo12", ELF::R_LARCH_GOT_LO12) |
| .Case("got64_lo20", ELF::R_LARCH_GOT64_LO20) |
| .Case("got64_hi12", ELF::R_LARCH_GOT64_HI12) |
| .Case("le_hi20", ELF::R_LARCH_TLS_LE_HI20) |
| .Case("le_lo12", ELF::R_LARCH_TLS_LE_LO12) |
| .Case("le64_lo20", ELF::R_LARCH_TLS_LE64_LO20) |
| .Case("le64_hi12", ELF::R_LARCH_TLS_LE64_HI12) |
| .Case("ie_pc_hi20", ELF::R_LARCH_TLS_IE_PC_HI20) |
| .Case("ie_pc_lo12", ELF::R_LARCH_TLS_IE_PC_LO12) |
| .Case("ie64_pc_lo20", ELF::R_LARCH_TLS_IE64_PC_LO20) |
| .Case("ie64_pc_hi12", ELF::R_LARCH_TLS_IE64_PC_HI12) |
| .Case("ie_hi20", ELF::R_LARCH_TLS_IE_HI20) |
| .Case("ie_lo12", ELF::R_LARCH_TLS_IE_LO12) |
| .Case("ie64_lo20", ELF::R_LARCH_TLS_IE64_LO20) |
| .Case("ie64_hi12", ELF::R_LARCH_TLS_IE64_HI12) |
| .Case("ld_pc_hi20", ELF::R_LARCH_TLS_LD_PC_HI20) |
| .Case("ld_hi20", ELF::R_LARCH_TLS_LD_HI20) |
| .Case("gd_pc_hi20", ELF::R_LARCH_TLS_GD_PC_HI20) |
| .Case("gd_hi20", ELF::R_LARCH_TLS_GD_HI20) |
| .Case("call36", ELF::R_LARCH_CALL36) |
| .Case("desc_pc_hi20", ELF::R_LARCH_TLS_DESC_PC_HI20) |
| .Case("desc_pc_lo12", ELF::R_LARCH_TLS_DESC_PC_LO12) |
| .Case("desc64_pc_lo20", ELF::R_LARCH_TLS_DESC64_PC_LO20) |
| .Case("desc64_pc_hi12", ELF::R_LARCH_TLS_DESC64_PC_HI12) |
| .Case("desc_hi20", ELF::R_LARCH_TLS_DESC_HI20) |
| .Case("desc_lo12", ELF::R_LARCH_TLS_DESC_LO12) |
| .Case("desc64_lo20", ELF::R_LARCH_TLS_DESC64_LO20) |
| .Case("desc64_hi12", ELF::R_LARCH_TLS_DESC64_HI12) |
| .Case("desc_ld", ELF::R_LARCH_TLS_DESC_LD) |
| .Case("desc_call", ELF::R_LARCH_TLS_DESC_CALL) |
| .Case("le_hi20_r", ELF::R_LARCH_TLS_LE_HI20_R) |
| .Case("le_add_r", ELF::R_LARCH_TLS_LE_ADD_R) |
| .Case("le_lo12_r", ELF::R_LARCH_TLS_LE_LO12_R) |
| .Case("pcrel_20", ELF::R_LARCH_PCREL20_S2) |
| .Case("ld_pcrel_20", ELF::R_LARCH_TLS_LD_PCREL20_S2) |
| .Case("gd_pcrel_20", ELF::R_LARCH_TLS_GD_PCREL20_S2) |
| .Case("desc_pcrel_20", ELF::R_LARCH_TLS_DESC_PCREL20_S2) |
| .Default(0); |
| } |
| |
| void LoongArchMCAsmInfo::anchor() {} |
| |
| LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TT) { |
| CodePointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4; |
| AlignmentIsInBytes = false; |
| Data8bitsDirective = "\t.byte\t"; |
| Data16bitsDirective = "\t.half\t"; |
| Data32bitsDirective = "\t.word\t"; |
| Data64bitsDirective = "\t.dword\t"; |
| ZeroDirective = "\t.space\t"; |
| CommentString = "#"; |
| AllowDollarAtStartOfIdentifier = false; |
| SupportsDebugInformation = true; |
| DwarfRegNumForCFI = true; |
| ExceptionsType = ExceptionHandling::DwarfCFI; |
| } |
| |
| void LoongArchMCAsmInfo::printSpecifierExpr(raw_ostream &OS, |
| const MCSpecifierExpr &Expr) const { |
| auto S = Expr.getSpecifier(); |
| bool HasSpecifier = S != 0 && S != ELF::R_LARCH_B26; |
| if (HasSpecifier) |
| OS << '%' << getLoongArchSpecifierName(S) << '('; |
| printExpr(OS, *Expr.getSubExpr()); |
| if (HasSpecifier) |
| OS << ')'; |
| } |