[AArch64] Allow .variant_pcs before the symbol is registered

glibc sysdeps/aarch64/tst-vpcs-mod.S has something like:
```
.variant_pcs    vpcs_call
.global vpcs_call
```

This is supported by GNU as but leads to an error in MC. Use getOrCreateSymbol
to support a not-yet-registered symbol: call `registerSymbol` to ensure the
symbol exists even if there is no binding directive/label, to match GNU as.

While here, improve tests to check (1) a local symbol can get
STO_AARCH64_VARIANT_PCS (2) undefined .variant_pcs (3) an alias does not
inherit STO_AARCH64_VARIANT_PCS.

Reviewed By: efriedma

Differential Revision: https://reviews.llvm.org/D122507
This commit is contained in:
Fangrui Song 2022-03-28 17:52:27 -07:00
parent a427e18896
commit cfbd5c8e4a
4 changed files with 39 additions and 23 deletions

View File

@ -6526,21 +6526,13 @@ bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
/// parseDirectiveVariantPCS
/// ::= .variant_pcs symbolname
bool AArch64AsmParser::parseDirectiveVariantPCS(SMLoc L) {
const AsmToken &Tok = getTok();
if (Tok.isNot(AsmToken::Identifier))
StringRef Name;
if (getParser().parseIdentifier(Name))
return TokError("expected symbol name");
StringRef SymbolName = Tok.getIdentifier();
MCSymbol *Sym = getContext().lookupSymbol(SymbolName);
if (!Sym)
return TokError("unknown symbol");
Lex(); // Eat the symbol
if (parseEOL())
return true;
getTargetStreamer().emitDirectiveVariantPCS(Sym);
getTargetStreamer().emitDirectiveVariantPCS(
getContext().getOrCreateSymbol(Name));
return false;
}

View File

@ -254,6 +254,7 @@ void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
}
void AArch64TargetELFStreamer::emitDirectiveVariantPCS(MCSymbol *Symbol) {
getStreamer().getAssembler().registerSymbol(*Symbol);
cast<MCSymbolELF>(Symbol)->setOther(ELF::STO_AARCH64_VARIANT_PCS);
}

View File

@ -3,9 +3,6 @@
// CHECK: [[#@LINE+1]]:13: error: expected symbol name
.variant_pcs
// CHECK: [[#@LINE+1]]:14: error: unknown symbol
.variant_pcs foo
.global foo
// CHECK: [[#@LINE+1]]:18: error: expected newline
.variant_pcs foo bar

View File

@ -1,11 +1,37 @@
// 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
// RUN: llvm-mc -triple aarch64-elf -filetype asm %s | FileCheck %s --check-prefix=ASM
// RUN: llvm-mc -triple aarch64-elf -filetype obj %s \
// RUN: | llvm-readelf -s - | FileCheck %s --check-prefix=OBJ
// ASM: .variant_pcs local
// ASM-NEXT: local:
.text
.global foo
.variant_pcs foo
// CHECK: .variant_pcs foo
.variant_pcs local
local:
// CHECK-ST_OTHER: Name: foo
// CHECK-ST_OTHER: Other [ (0x80)
/// Binding directive before .variant_pcs.
// ASM: .globl def1
// ASM-NEXT: .variant_pcs def1
// ASM-NEXT: def1:
.global def1
.variant_pcs def1
def1:
/// .variant_pcs before binding directive.
// ASM: .variant_pcs def2
// ASM-NEXT: .weak def2
// ASM-NEXT: def2:
.variant_pcs def2
.weak def2
def2:
.globl alias_def1
.set alias_def1, def1
// ASM: .variant_pcs undef
.variant_pcs undef
// OBJ: NOTYPE LOCAL DEFAULT [VARIANT_PCS] [[#]] local
// OBJ-NEXT: NOTYPE GLOBAL DEFAULT [VARIANT_PCS] [[#]] def1
// OBJ-NEXT: NOTYPE WEAK DEFAULT [VARIANT_PCS] [[#]] def2
// OBJ-NEXT: NOTYPE GLOBAL DEFAULT [[#]] alias_def1
// OBJ-NEXT: NOTYPE GLOBAL DEFAULT [VARIANT_PCS] UND undef