Skip to content

Commit 25d8502

Browse files
MaskRaytru
authored andcommitted
[PPC32] Parse bl __tls_get_addr(x@tlsgd)@plt+32768
PPC32 -fpic/-fPIC generates `bl __tls_get_addr(x@tlsgd)@PLT` or `bl __tls_get_addr(x@tlsgd)@plt+32768`. `powerpc-linux-gnu-gcc -fPIC` generates `bl __tls_get_addr+32668(x@tlsgd)@plt`. These expressions can be parsed by GNU assembler but not by the integrated assembler. Add the support. Differential Revision: https://reviews.llvm.org/D153206 (cherry picked from commit 6e07e90)
1 parent 700fa26 commit 25d8502

File tree

3 files changed

+105
-12
lines changed

3 files changed

+105
-12
lines changed

llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,24 +1544,58 @@ bool PPCAsmParser::ParseOperand(OperandVector &Operands) {
15441544
Operands.push_back(PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64()));
15451545

15461546
// Check whether this is a TLS call expression
1547-
bool TLSCall = false;
1548-
if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(EVal))
1549-
TLSCall = Ref->getSymbol().getName() == "__tls_get_addr";
1547+
const char TlsGetAddr[] = "__tls_get_addr";
1548+
bool TlsCall = false;
1549+
const MCExpr *TlsCallAddend = nullptr;
1550+
if (auto *Ref = dyn_cast<MCSymbolRefExpr>(EVal)) {
1551+
TlsCall = Ref->getSymbol().getName() == TlsGetAddr;
1552+
} else if (auto *Bin = dyn_cast<MCBinaryExpr>(EVal);
1553+
Bin && Bin->getOpcode() == MCBinaryExpr::Add) {
1554+
if (auto *Ref = dyn_cast<MCSymbolRefExpr>(Bin->getLHS())) {
1555+
TlsCall = Ref->getSymbol().getName() == TlsGetAddr;
1556+
TlsCallAddend = Bin->getRHS();
1557+
}
1558+
}
15501559

1551-
if (TLSCall && parseOptionalToken(AsmToken::LParen)) {
1560+
if (TlsCall && parseOptionalToken(AsmToken::LParen)) {
15521561
const MCExpr *TLSSym;
1553-
S = Parser.getTok().getLoc();
1562+
const SMLoc S2 = Parser.getTok().getLoc();
15541563
if (ParseExpression(TLSSym))
1555-
return Error(S, "invalid TLS call expression");
1564+
return Error(S2, "invalid TLS call expression");
1565+
E = Parser.getTok().getLoc();
15561566
if (parseToken(AsmToken::RParen, "expected ')'"))
15571567
return true;
1558-
E = Parser.getTok().getLoc();
1568+
// PPC32 allows bl __tls_get_addr[+a](x@tlsgd)@plt+b. Parse "@plt[+b]".
1569+
if (!isPPC64() && parseOptionalToken(AsmToken::At)) {
1570+
AsmToken Tok = getTok();
1571+
if (!(parseOptionalToken(AsmToken::Identifier) &&
1572+
Tok.getString().compare_insensitive("plt") == 0))
1573+
return Error(Tok.getLoc(), "expected 'plt'");
1574+
EVal = MCSymbolRefExpr::create(TlsGetAddr, MCSymbolRefExpr::VK_PLT,
1575+
getContext());
1576+
if (parseOptionalToken(AsmToken::Plus)) {
1577+
const MCExpr *Addend = nullptr;
1578+
SMLoc EndLoc;
1579+
if (parsePrimaryExpr(Addend, EndLoc))
1580+
return true;
1581+
if (TlsCallAddend) // __tls_get_addr+a(x@tlsgd)@plt+b
1582+
TlsCallAddend =
1583+
MCBinaryExpr::createAdd(TlsCallAddend, Addend, getContext());
1584+
else // __tls_get_addr(x@tlsgd)@plt+b
1585+
TlsCallAddend = Addend;
1586+
}
1587+
if (TlsCallAddend)
1588+
EVal = MCBinaryExpr::createAdd(EVal, TlsCallAddend, getContext());
1589+
// Add a __tls_get_addr operand with addend a, b, or a+b.
1590+
Operands.back() = PPCOperand::CreateFromMCExpr(
1591+
EVal, S, Parser.getTok().getLoc(), false);
1592+
}
15591593

15601594
Operands.push_back(PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64()));
15611595
}
15621596

15631597
// Otherwise, check for D-form memory operands
1564-
if (!TLSCall && parseOptionalToken(AsmToken::LParen)) {
1598+
if (!TlsCall && parseOptionalToken(AsmToken::LParen)) {
15651599
S = Parser.getTok().getLoc();
15661600

15671601
int64_t IntVal;

llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -564,10 +564,10 @@ void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
564564
// come at the _end_ of the expression.
565565
const MCOperand &Op = MI->getOperand(OpNo);
566566
const MCSymbolRefExpr *RefExp = nullptr;
567-
const MCConstantExpr *ConstExp = nullptr;
567+
const MCExpr *Rhs = nullptr;
568568
if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Op.getExpr())) {
569569
RefExp = cast<MCSymbolRefExpr>(BinExpr->getLHS());
570-
ConstExp = cast<MCConstantExpr>(BinExpr->getRHS());
570+
Rhs = BinExpr->getRHS();
571571
} else
572572
RefExp = cast<MCSymbolRefExpr>(Op.getExpr());
573573

@@ -584,8 +584,14 @@ void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
584584
if (RefExp->getKind() != MCSymbolRefExpr::VK_None &&
585585
RefExp->getKind() != MCSymbolRefExpr::VK_PPC_NOTOC)
586586
O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind());
587-
if (ConstExp != nullptr)
588-
O << '+' << ConstExp->getValue();
587+
if (Rhs) {
588+
SmallString<0> Buf;
589+
raw_svector_ostream Tmp(Buf);
590+
Rhs->print(Tmp, &MAI);
591+
if (isdigit(Buf[0]))
592+
O << '+';
593+
O << Buf;
594+
}
589595
}
590596

591597
/// showRegistersWithPercentPrefix - Check if this register name should be

llvm/test/MC/PowerPC/ppc32-tls.s

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# RUN: llvm-mc -triple=powerpc %s | FileCheck %s --check-prefix=ASM
2+
# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t
3+
# RUN: llvm-readobj -r %t | FileCheck %s
4+
5+
# RUN: not llvm-mc -triple=powerpc --defsym ERR=1 %s 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
6+
7+
# ASM: bl __tls_get_addr(a@tlsgd)
8+
# ASM: bl __tls_get_addr(b@tlsld)
9+
# ASM: bl __tls_get_addr(c@tlsgd)@PLT
10+
# ASM: bl __tls_get_addr(d@tlsld)@PLT+32768
11+
# ASM: bl __tls_get_addr(e@tlsld)@PLT+32768
12+
bl __tls_get_addr(a@tlsgd)
13+
bl __tls_get_addr(b@tlsld)
14+
bl __tls_get_addr(c@tlsgd)@plt
15+
bl __tls_get_addr(d@tlsld)@PLT+32768
16+
bl __tls_get_addr+32768(e@tlsld)@plt # gcc -fPIC
17+
18+
## These are not present in the wild, but just to test we can parse them.
19+
# ASM: bl __tls_get_addr(f@tlsld)@PLT+1+(-2)
20+
bl __tls_get_addr+1(f@tlsld)@PLT+-2
21+
# ASM: bl __tls_get_addr(g@tlsld)@PLT+1+(y-x)
22+
x:
23+
bl __tls_get_addr+1(g@tlsld)@PLT+(y-x)
24+
y:
25+
26+
# CHECK: .rela.text {
27+
# CHECK-NEXT: 0x0 R_PPC_TLSGD a 0x0
28+
# CHECK-NEXT: 0x0 R_PPC_REL24 __tls_get_addr 0x0
29+
# CHECK-NEXT: 0x4 R_PPC_TLSLD b 0x0
30+
# CHECK-NEXT: 0x4 R_PPC_REL24 __tls_get_addr 0x0
31+
# CHECK-NEXT: 0x8 R_PPC_TLSGD c 0x0
32+
# CHECK-NEXT: 0x8 R_PPC_PLTREL24 __tls_get_addr 0x0
33+
# CHECK-NEXT: 0xC R_PPC_TLSLD d 0x0
34+
# CHECK-NEXT: 0xC R_PPC_PLTREL24 __tls_get_addr 0x8000
35+
# CHECK-NEXT: 0x10 R_PPC_TLSLD e 0x0
36+
# CHECK-NEXT: 0x10 R_PPC_PLTREL24 __tls_get_addr 0x8000
37+
# CHECK-NEXT: 0x14 R_PPC_TLSLD f 0x0
38+
# CHECK-NEXT: 0x14 R_PPC_PLTREL24 __tls_get_addr 0xFFFFFFFF
39+
# CHECK-NEXT: 0x18 R_PPC_TLSLD g 0x0
40+
# CHECK-NEXT: 0x18 R_PPC_PLTREL24 __tls_get_addr 0x5
41+
# CHECK-NEXT: }
42+
43+
.ifdef ERR
44+
# ERR: :[[#@LINE+1]]:27: error: unexpected token
45+
bl __tls_get_addr(d@tlsld)plt
46+
# ERR: :[[#@LINE+1]]:28: error: expected 'plt'
47+
bl __tls_get_addr(d@tlsld)@invalid
48+
# ERR: :[[#@LINE+1]]:31: error: unexpected token
49+
bl __tls_get_addr(d@tlsld)@plt-32768
50+
51+
# ERR: :[[#@LINE+1]]:21: error: invalid memory operand
52+
bl __tls_get_addr-1(f@tlsld)@plt
53+
.endif

0 commit comments

Comments
 (0)