mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[AArch64] Implement .variant_pcs directive
A dynamic linker with lazy binding support may need to handle variant PCS function symbols specially, so an ELF symbol table marking STO_AARCH64_VARIANT_PCS [1] was added to address this. Function symbols that follow the vector PCS are marked via the .variant_pcs assembler directive, which takes a single parameter specifying the symbol name and sets the STO_AARCH64_VARIANT_PCS st_other flag in the object file. [1] https://github.com/ARM-software/abi-aa/blob/master/aaelf64/aaelf64.rst#st-other-values Reviewed By: sdesmalen Differential Revision: https://reviews.llvm.org/D89138
This commit is contained in:
parent
a5e5f602ef
commit
5dfa2f5625
@ -406,6 +406,12 @@ enum {
|
||||
#include "ELFRelocs/AArch64.def"
|
||||
};
|
||||
|
||||
// Special values for the st_other field in the symbol table entry for AArch64.
|
||||
enum {
|
||||
// Symbol may follow different calling convention than base PCS.
|
||||
STO_AARCH64_VARIANT_PCS = 0x80
|
||||
};
|
||||
|
||||
// ARM Specific e_flags
|
||||
enum : unsigned {
|
||||
EF_ARM_SOFT_FLOAT = 0x00000200U, // Legacy pre EABI_VER5
|
||||
|
@ -89,6 +89,8 @@ public:
|
||||
void emitStartOfAsmFile(Module &M) override;
|
||||
void emitJumpTableInfo() override;
|
||||
|
||||
void emitFunctionEntryLabel() override;
|
||||
|
||||
void LowerJumpTableDest(MCStreamer &OutStreamer, const MachineInstr &MI);
|
||||
|
||||
void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
|
||||
@ -787,6 +789,19 @@ void AArch64AsmPrinter::emitJumpTableInfo() {
|
||||
}
|
||||
}
|
||||
|
||||
void AArch64AsmPrinter::emitFunctionEntryLabel() {
|
||||
if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall ||
|
||||
MF->getFunction().getCallingConv() ==
|
||||
CallingConv::AArch64_SVE_VectorCall ||
|
||||
STI->getRegisterInfo()->hasSVEArgsOrReturn(MF)) {
|
||||
auto *TS =
|
||||
static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
|
||||
TS->emitDirectiveVariantPCS(CurrentFnSym);
|
||||
}
|
||||
|
||||
return AsmPrinter::emitFunctionEntryLabel();
|
||||
}
|
||||
|
||||
/// Small jump tables contain an unsigned byte or half, representing the offset
|
||||
/// from the lowest-addressed possible destination to the desired basic
|
||||
/// block. Since all instructions are 4-byte aligned, this is further compressed
|
||||
|
@ -184,6 +184,8 @@ private:
|
||||
bool parseDirectiveCFINegateRAState();
|
||||
bool parseDirectiveCFIBKeyFrame();
|
||||
|
||||
bool parseDirectiveVariantPCS(SMLoc L);
|
||||
|
||||
bool parseDirectiveSEHAllocStack(SMLoc L);
|
||||
bool parseDirectiveSEHPrologEnd(SMLoc L);
|
||||
bool parseDirectiveSEHSaveR19R20X(SMLoc L);
|
||||
@ -5171,6 +5173,8 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
parseDirectiveCFIBKeyFrame();
|
||||
else if (IDVal == ".arch_extension")
|
||||
parseDirectiveArchExtension(Loc);
|
||||
else if (IDVal == ".variant_pcs")
|
||||
parseDirectiveVariantPCS(Loc);
|
||||
else if (IsMachO) {
|
||||
if (IDVal == MCLOHDirectiveName())
|
||||
parseDirectiveLOH(IDVal, Loc);
|
||||
@ -5650,6 +5654,32 @@ bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveVariantPCS
|
||||
/// ::= .variant_pcs symbolname
|
||||
bool AArch64AsmParser::parseDirectiveVariantPCS(SMLoc L) {
|
||||
MCAsmParser &Parser = getParser();
|
||||
|
||||
const AsmToken &Tok = Parser.getTok();
|
||||
if (Tok.isNot(AsmToken::Identifier))
|
||||
return TokError("expected symbol name");
|
||||
|
||||
StringRef SymbolName = Tok.getIdentifier();
|
||||
|
||||
MCSymbol *Sym = getContext().lookupSymbol(SymbolName);
|
||||
if (!Sym)
|
||||
return TokError("unknown symbol in '.variant_pcs' directive");
|
||||
|
||||
Parser.Lex(); // Eat the symbol
|
||||
|
||||
// Shouldn't be any more tokens
|
||||
if (parseToken(AsmToken::EndOfStatement))
|
||||
return addErrorSuffix(" in '.variant_pcs' directive");
|
||||
|
||||
getTargetStreamer().emitDirectiveVariantPCS(Sym);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveSEHAllocStack
|
||||
/// ::= .seh_stackalloc
|
||||
bool AArch64AsmParser::parseDirectiveSEHAllocStack(SMLoc L) {
|
||||
|
@ -47,6 +47,10 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
|
||||
|
||||
void emitInst(uint32_t Inst) override;
|
||||
|
||||
void emitDirectiveVariantPCS(MCSymbol *Symbol) override {
|
||||
OS << "\t.variant_pcs " << Symbol->getName() << "\n";
|
||||
}
|
||||
|
||||
void EmitARM64WinCFIAllocStack(unsigned Size) override {
|
||||
OS << "\t.seh_stackalloc " << Size << "\n";
|
||||
}
|
||||
@ -249,6 +253,10 @@ void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
|
||||
getStreamer().emitInst(Inst);
|
||||
}
|
||||
|
||||
void AArch64TargetELFStreamer::emitDirectiveVariantPCS(MCSymbol *Symbol) {
|
||||
cast<MCSymbolELF>(Symbol)->setOther(ELF::STO_AARCH64_VARIANT_PCS);
|
||||
}
|
||||
|
||||
MCTargetStreamer *createAArch64AsmTargetStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS,
|
||||
MCInstPrinter *InstPrint,
|
||||
|
@ -39,6 +39,9 @@ public:
|
||||
/// Callback used to implement the .inst directive.
|
||||
virtual void emitInst(uint32_t Inst);
|
||||
|
||||
/// Callback used to implement the .variant_pcs directive.
|
||||
virtual void emitDirectiveVariantPCS(MCSymbol *Symbol) {};
|
||||
|
||||
virtual void EmitARM64WinCFIAllocStack(unsigned Size) {}
|
||||
virtual void EmitARM64WinCFISaveR19R20X(int Offset) {}
|
||||
virtual void EmitARM64WinCFISaveFPLR(int Offset) {}
|
||||
@ -73,6 +76,7 @@ private:
|
||||
AArch64ELFStreamer &getStreamer();
|
||||
|
||||
void emitInst(uint32_t Inst) override;
|
||||
void emitDirectiveVariantPCS(MCSymbol *Symbol) override;
|
||||
|
||||
public:
|
||||
AArch64TargetELFStreamer(MCStreamer &S) : AArch64TargetStreamer(S) {}
|
||||
|
51
test/CodeGen/AArch64/variant-pcs.ll
Normal file
51
test/CodeGen/AArch64/variant-pcs.ll
Normal file
@ -0,0 +1,51 @@
|
||||
; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve -o - %s | FileCheck %s --check-prefix=CHECK-ASM
|
||||
; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve -filetype=obj -o - %s \
|
||||
; RUN: | llvm-readobj --symbols - | FileCheck %s --check-prefix=CHECK-OBJ
|
||||
|
||||
define i32 @base_pcs() {
|
||||
; CHECK-ASM-LABEL: base_pcs:
|
||||
; CHECK-ASM-NOT: .variant_pcs
|
||||
; CHECK-OBJ-LABEL: Name: base_pcs
|
||||
; CHECK-OBJ: Other: 0
|
||||
ret i32 42
|
||||
}
|
||||
|
||||
define aarch64_vector_pcs <4 x i32> @neon_vector_pcs_1(<4 x i32> %arg) {
|
||||
; CHECK-ASM: .variant_pcs neon_vector_pcs_1
|
||||
; CHECK-ASM-NEXT: neon_vector_pcs_1:
|
||||
; CHECK-OBJ-LABEL: Name: neon_vector_pcs_1
|
||||
; CHECK-OBJ: Other [ (0x80)
|
||||
ret <4 x i32> %arg
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @sve_vector_pcs_1() {
|
||||
; CHECK-ASM: .variant_pcs sve_vector_pcs_1
|
||||
; CHECK-ASM-NEXT: sve_vector_pcs_1:
|
||||
; CHECK-OBJ-LABEL: Name: sve_vector_pcs_1
|
||||
; CHECK-OBJ: Other [ (0x80)
|
||||
ret <vscale x 4 x i32> undef
|
||||
}
|
||||
|
||||
define <vscale x 4 x i1> @sve_vector_pcs_2() {
|
||||
; CHECK-ASM: .variant_pcs sve_vector_pcs_2
|
||||
; CHECK-ASM-NEXT: sve_vector_pcs_2:
|
||||
; CHECK-OBJ-LABEL: Name: sve_vector_pcs_2
|
||||
; CHECK-OBJ: Other [ (0x80)
|
||||
ret <vscale x 4 x i1> undef
|
||||
}
|
||||
|
||||
define void @sve_vector_pcs_3(<vscale x 4 x i32> %arg) {
|
||||
; CHECK-ASM: .variant_pcs sve_vector_pcs_3
|
||||
; CHECK-ASM-NEXT: sve_vector_pcs_3:
|
||||
; CHECK-OBJ-LABEL: Name: sve_vector_pcs_3
|
||||
; CHECK-OBJ: Other [ (0x80)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sve_vector_pcs_4(<vscale x 4 x i1> %arg) {
|
||||
; CHECK-ASM: .variant_pcs sve_vector_pcs_4
|
||||
; CHECK-ASM-NEXT: sve_vector_pcs_4:
|
||||
; CHECK-OBJ-LABEL: Name: sve_vector_pcs_4
|
||||
; CHECK-OBJ: Other [ (0x80)
|
||||
ret void
|
||||
}
|
17
test/MC/AArch64/directive-variant_pcs-err.s
Normal file
17
test/MC/AArch64/directive-variant_pcs-err.s
Normal file
@ -0,0 +1,17 @@
|
||||
// RUN: not llvm-mc -triple aarch64-unknown-none-eabi -filetype asm -o - %s 2>&1 | FileCheck %s
|
||||
|
||||
.variant_pcs
|
||||
// CHECK: error: expected symbol name
|
||||
// CHECK-NEXT: .variant_pcs
|
||||
// CHECK-NEXT: ^
|
||||
|
||||
.variant_pcs foo
|
||||
// CHECK: error: unknown symbol in '.variant_pcs' directive
|
||||
// CHECK-NEXT: .variant_pcs foo
|
||||
// CHECK-NEXT: ^
|
||||
|
||||
.global foo
|
||||
.variant_pcs foo bar
|
||||
// CHECK: error: unexpected token in '.variant_pcs' directive
|
||||
// CHECK-NEXT: .variant_pcs foo bar
|
||||
// CHECK-NEXT: ^
|
11
test/MC/AArch64/directive-variant_pcs.s
Normal file
11
test/MC/AArch64/directive-variant_pcs.s
Normal file
@ -0,0 +1,11 @@
|
||||
// RUN: llvm-mc -triple aarch64-elf -filetype asm -o - %s | FileCheck %s
|
||||
// RUN: llvm-mc -triple aarch64-elf -filetype obj -o - %s \
|
||||
// RUN: | llvm-readobj --symbols - | FileCheck %s --check-prefix=CHECK-ST_OTHER
|
||||
|
||||
.text
|
||||
.global foo
|
||||
.variant_pcs foo
|
||||
// CHECK: .variant_pcs foo
|
||||
|
||||
// CHECK-ST_OTHER: Name: foo
|
||||
// CHECK-ST_OTHER: Other [ (0x80)
|
Loading…
Reference in New Issue
Block a user