diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h @@ -66,6 +66,12 @@ bool reverseBranchCondition(SmallVectorImpl &Cond) const override; + std::pair + decomposeMachineOperandsTargetFlags(unsigned TF) const override; + + ArrayRef> + getSerializableDirectMachineOperandTargetFlags() const override; + protected: const LoongArchSubtarget &STI; }; diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -341,3 +341,28 @@ Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm())); return false; } + +std::pair +LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { + return std::make_pair(TF, 0u); +} + +ArrayRef> +LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { + using namespace LoongArchII; + // TODO: Add more target flags. + static const std::pair TargetFlags[] = { + {MO_CALL, "loongarch-call"}, + {MO_CALL_PLT, "loongarch-call-plt"}, + {MO_PCREL_HI, "loongarch-pcrel-hi"}, + {MO_PCREL_LO, "loongarch-pcrel-lo"}, + {MO_GOT_PC_HI, "loongarch-got-pc-hi"}, + {MO_GOT_PC_LO, "loongarch-got-pc-lo"}, + {MO_LE_HI, "loongarch-le-hi"}, + {MO_LE_LO, "loongarch-le-lo"}, + {MO_IE_PC_HI, "loongarch-ie-pc-hi"}, + {MO_IE_PC_LO, "loongarch-ie-pc-lo"}, + {MO_LD_PC_HI, "loongarch-ld-pc-hi"}, + {MO_GD_PC_HI, "loongarch-gd-pc-hi"}}; + return makeArrayRef(TargetFlags); +} diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h @@ -86,7 +86,7 @@ return getSubExpr()->findAssociatedFragment(); } - void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {} + void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override; static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp @@ -16,7 +16,9 @@ #include "LoongArchFixupKinds.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -179,3 +181,45 @@ .Case("gd_hi20", VK_LoongArch_TLS_GD_HI20) .Default(VK_LoongArch_Invalid); } + +static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { + switch (Expr->getKind()) { + case MCExpr::Target: + llvm_unreachable("Can't handle nested target expression"); + break; + case MCExpr::Constant: + break; + case MCExpr::Unary: + fixELFSymbolsInTLSFixupsImpl(cast(Expr)->getSubExpr(), Asm); + break; + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(Expr); + fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); + fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); + break; + } + case MCExpr::SymbolRef: { + // We're known to be under a TLS fixup, so any symbol should be + // modified. There should be only one. + const MCSymbolRefExpr &SymRef = *cast(Expr); + cast(SymRef.getSymbol()).setType(ELF::STT_TLS); + break; + } + } +} + +void LoongArchMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { + switch (getKind()) { + default: + return; + case VK_LoongArch_TLS_LE_HI20: + case VK_LoongArch_TLS_IE_PC_HI20: + case VK_LoongArch_TLS_IE_HI20: + case VK_LoongArch_TLS_LD_PC_HI20: + case VK_LoongArch_TLS_LD_HI20: + case VK_LoongArch_TLS_GD_PC_HI20: + case VK_LoongArch_TLS_GD_HI20: + break; + } + fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); +} diff --git a/llvm/test/CodeGen/LoongArch/tls-symbols.ll b/llvm/test/CodeGen/LoongArch/tls-symbols.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/tls-symbols.ll @@ -0,0 +1,32 @@ +; RUN: llc --mtriple=loongarch64 --relocation-model=pic --filetype=obj < %s \ +; RUN: -o - | llvm-readelf -s - | FileCheck %s + +@unspecified = external thread_local global i32 +@ld = external thread_local(localdynamic) global i32 +@ie = external thread_local(initialexec) global i32 +@le = external thread_local(localexec) global i32 + +; CHECK-LABEL: Symbol table +define ptr @f1() nounwind { +entry: +; CHECK: TLS{{.*}}UND unspecified + ret ptr @unspecified +} + +define ptr @f2() nounwind { +entry: +; CHECK: TLS{{.*}}UND ld + ret ptr @ld +} + +define ptr @f3() nounwind { +entry: +; CHECK: TLS{{.*}}UND ie + ret ptr @ie +} + +define ptr @f4() nounwind { +entry: +; CHECK: TLS{{.*}}UND le + ret ptr @le +}