Skip to content

Commit 0ed4bdf

Browse files
committed
PPCAsmParser: Detect multiple specifiers
In addition, simplify extractSpecifier and switch to the `Specifier` naming convention.
1 parent 81c6ce3 commit 0ed4bdf

File tree

2 files changed

+51
-65
lines changed

2 files changed

+51
-65
lines changed

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

Lines changed: 36 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,107 +1363,79 @@ ParseStatus PPCAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
13631363
return ParseStatus::Success;
13641364
}
13651365

1366-
/// Extract \code @l/@ha \endcode specifier from expression. Recursively scan
1367-
/// the expression and check for VK_LO/HI/HA
1368-
/// symbol variants. If all symbols with specifier use the same
1369-
/// specifier, return the corresponding PPCMCExpr::Specifier,
1370-
/// and a modified expression using the default symbol variant.
1371-
/// Otherwise, return NULL.
1366+
// Extract the @l or @ha specifier from the expression, returning a modified
1367+
// expression with the specifier removed. Stores the extracted specifier in
1368+
// `Spec`. Reports an error if multiple specifiers are detected.
13721369
const MCExpr *PPCAsmParser::extractSpecifier(const MCExpr *E,
1373-
PPCMCExpr::Specifier &Variant) {
1370+
PPCMCExpr::Specifier &Spec) {
13741371
MCContext &Context = getParser().getContext();
1375-
Variant = PPCMCExpr::VK_None;
1376-
13771372
switch (E->getKind()) {
1378-
case MCExpr::Target:
13791373
case MCExpr::Constant:
1380-
return nullptr;
1374+
break;
1375+
case MCExpr::Target: {
1376+
// Detect error but do not return a modified expression.
1377+
auto *TE = cast<PPCMCExpr>(E);
1378+
Spec = TE->getSpecifier();
1379+
(void)extractSpecifier(TE->getSubExpr(), Spec);
1380+
Spec = PPCMCExpr::VK_None;
1381+
} break;
13811382

13821383
case MCExpr::SymbolRef: {
1383-
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
1384-
Variant = (PPCMCExpr::Specifier)SRE->getKind();
1385-
switch (Variant) {
1386-
case PPCMCExpr::VK_LO:
1387-
Variant = PPCMCExpr::VK_LO;
1384+
const auto *SRE = cast<MCSymbolRefExpr>(E);
1385+
switch (getSpecifier(SRE)) {
1386+
case PPCMCExpr::VK_None:
1387+
default:
13881388
break;
1389+
case PPCMCExpr::VK_LO:
13891390
case PPCMCExpr::VK_HI:
1390-
Variant = PPCMCExpr::VK_HI;
1391-
break;
13921391
case PPCMCExpr::VK_HA:
1393-
Variant = PPCMCExpr::VK_HA;
1394-
break;
13951392
case PPCMCExpr::VK_HIGH:
1396-
Variant = PPCMCExpr::VK_HIGH;
1397-
break;
13981393
case PPCMCExpr::VK_HIGHA:
1399-
Variant = PPCMCExpr::VK_HIGHA;
1400-
break;
14011394
case PPCMCExpr::VK_HIGHER:
1402-
Variant = PPCMCExpr::VK_HIGHER;
1403-
break;
14041395
case PPCMCExpr::VK_HIGHERA:
1405-
Variant = PPCMCExpr::VK_HIGHERA;
1406-
break;
14071396
case PPCMCExpr::VK_HIGHEST:
1408-
Variant = PPCMCExpr::VK_HIGHEST;
1409-
break;
14101397
case PPCMCExpr::VK_HIGHESTA:
1411-
Variant = PPCMCExpr::VK_HIGHESTA;
1412-
break;
1413-
default:
1414-
return nullptr;
1398+
if (Spec == PPCMCExpr::VK_None)
1399+
Spec = getSpecifier(SRE);
1400+
else
1401+
Error(E->getLoc(), "cannot contain more than one relocation specifier");
1402+
return MCSymbolRefExpr::create(&SRE->getSymbol(), Context);
14151403
}
1416-
1417-
return MCSymbolRefExpr::create(&SRE->getSymbol(), Context);
1404+
break;
14181405
}
14191406

14201407
case MCExpr::Unary: {
14211408
const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
1422-
const MCExpr *Sub = extractSpecifier(UE->getSubExpr(), Variant);
1423-
if (!Sub)
1424-
return nullptr;
1425-
return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
1409+
const MCExpr *Sub = extractSpecifier(UE->getSubExpr(), Spec);
1410+
if (Spec != PPCMCExpr::VK_None)
1411+
return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
1412+
break;
14261413
}
14271414

14281415
case MCExpr::Binary: {
14291416
const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
1430-
PPCMCExpr::Specifier LHSVariant, RHSVariant;
1431-
const MCExpr *LHS = extractSpecifier(BE->getLHS(), LHSVariant);
1432-
const MCExpr *RHS = extractSpecifier(BE->getRHS(), RHSVariant);
1433-
1434-
if (!LHS && !RHS)
1435-
return nullptr;
1436-
1437-
if (!LHS) LHS = BE->getLHS();
1438-
if (!RHS) RHS = BE->getRHS();
1439-
1440-
if (LHSVariant == PPCMCExpr::VK_None)
1441-
Variant = RHSVariant;
1442-
else if (RHSVariant == PPCMCExpr::VK_None)
1443-
Variant = LHSVariant;
1444-
else if (LHSVariant == RHSVariant)
1445-
Variant = LHSVariant;
1446-
else
1447-
return nullptr;
1448-
1449-
return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
1417+
const MCExpr *LHS = extractSpecifier(BE->getLHS(), Spec);
1418+
const MCExpr *RHS = extractSpecifier(BE->getRHS(), Spec);
1419+
if (Spec != PPCMCExpr::VK_None)
1420+
return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
1421+
break;
14501422
}
14511423
}
14521424

1453-
llvm_unreachable("Invalid expression kind!");
1425+
return E;
14541426
}
14551427

14561428
/// This differs from the default "parseExpression" in that it handles
1457-
/// modifiers.
1429+
/// specifiers.
14581430
bool PPCAsmParser::parseExpression(const MCExpr *&EVal) {
14591431
// (ELF Platforms)
14601432
// Handle \code @l/@ha \endcode
14611433
if (getParser().parseExpression(EVal))
14621434
return true;
14631435

1464-
PPCMCExpr::Specifier Spec;
1436+
auto Spec = PPCMCExpr::VK_None;
14651437
const MCExpr *E = extractSpecifier(EVal, Spec);
1466-
if (E)
1438+
if (Spec != PPCMCExpr::VK_None)
14671439
EVal = PPCMCExpr::create(Spec, E, getParser().getContext());
14681440

14691441
return false;

llvm/test/MC/PowerPC/ppc64-fixups.s

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# RUN: llvm-mc -triple powerpc64-unknown-unknown --show-encoding %s | FileCheck -check-prefix=CHECK-BE %s
32
# RUN: llvm-mc -triple powerpc64le-unknown-unknown --show-encoding %s | FileCheck -check-prefix=CHECK-LE %s
43

@@ -7,6 +6,8 @@
76
# RUN: llvm-mc -triple powerpc64le-unknown-unknown -filetype=obj %s | \
87
# RUN: llvm-readobj -r - | FileCheck %s -check-prefix=CHECK-LE-REL
98

9+
# RUN: not llvm-mc -filetype=obj -triple powerpc64 --defsym ERR=1 %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
10+
1011
# CHECK-BE: b target # encoding: [0b010010AA,A,A,0bAAAAAA00]
1112
# CHECK-LE: b target # encoding: [0bAAAAAA00,A,A,0b010010AA]
1213
# CHECK-BE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_br24
@@ -771,3 +772,16 @@ base:
771772
# CHECK-LE-REL: 0x{{[0-9A-F]*[08]}} R_PPC64_DTPREL64 target 0x0
772773
.quad target@dtprel
773774

775+
.ifdef ERR
776+
# ERR: [[#@LINE+1]]:15: error: cannot contain more than one relocation specifier
777+
ori 1, 2, x@l+x@l
778+
779+
# ERR: [[#@LINE+1]]:17: error: cannot contain more than one relocation specifier
780+
ori 1, 2, -(x@l+x@l)
781+
782+
# ERR: [[#@LINE+1]]:11: error: cannot contain more than one relocation specifier
783+
ori 1, 2, x@l+3@l
784+
785+
# ERR: [[#@LINE+1]]:12: error: cannot contain more than one relocation specifier
786+
ori 1, 2, (x@l+3)@l
787+
.endif

0 commit comments

Comments
 (0)