Skip to content

Commit 46c79ef

Browse files
committed
Fix PR8565.
This moves most of the isUsed logic to the MCSymbol itself. With this we get a bit more relaxed about allowing definitions after uses: uses that don't evaluate their argument immediately (jmp foo) are accepted. ddunbar, this was the smallest compromise I could think of that lets us accept gcc (and clang!) assembly. llvm-svn: 119144
1 parent 99da11c commit 46c79ef

File tree

4 files changed

+54
-13
lines changed

4 files changed

+54
-13
lines changed

llvm/include/llvm/MC/MCSymbol.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,14 @@ namespace llvm {
5252
/// "Lfoo" or ".foo".
5353
unsigned IsTemporary : 1;
5454

55-
/// IsUsedInExpr - True if this symbol has been used in an expression and
56-
/// cannot be redefined.
57-
unsigned IsUsedInExpr : 1;
55+
/// IsUsed - True if this symbol has been used.
56+
mutable unsigned IsUsed : 1;
5857

5958
private: // MCContext creates and uniques these.
6059
friend class MCContext;
6160
MCSymbol(StringRef name, bool isTemporary)
6261
: Name(name), Section(0), Value(0),
63-
IsTemporary(isTemporary), IsUsedInExpr(false) {}
62+
IsTemporary(isTemporary), IsUsed(false) {}
6463

6564
MCSymbol(const MCSymbol&); // DO NOT IMPLEMENT
6665
void operator=(const MCSymbol&); // DO NOT IMPLEMENT
@@ -74,9 +73,9 @@ namespace llvm {
7473
/// isTemporary - Check if this is an assembler temporary symbol.
7574
bool isTemporary() const { return IsTemporary; }
7675

77-
/// isUsedInExpr - Check if this is an assembler temporary symbol.
78-
bool isUsedInExpr() const { return IsUsedInExpr; }
79-
void setUsedInExpr(bool Value) { IsUsedInExpr = Value; }
76+
/// isUsed - Check if this is used.
77+
bool isUsed() const { return IsUsed; }
78+
void setUsed(bool Value) const { IsUsed = Value; }
8079

8180
/// @}
8281
/// @name Associated Sections
@@ -135,6 +134,7 @@ namespace llvm {
135134
/// getValue() - Get the value for variable symbols.
136135
const MCExpr *getVariableValue() const {
137136
assert(isVariable() && "Invalid accessor!");
137+
IsUsed = true;
138138
return Value;
139139
}
140140

llvm/lib/MC/MCParser/AsmParser.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,6 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
485485
std::pair<StringRef, StringRef> Split = Identifier.split('@');
486486
MCSymbol *Sym = getContext().GetOrCreateSymbol(Split.first);
487487

488-
// Mark the symbol as used in an expression.
489-
Sym->setUsedInExpr(true);
490-
491488
// Lookup the symbol variant if used.
492489
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
493490
if (Split.first.size() != Identifier.size()) {
@@ -1191,6 +1188,25 @@ void AsmParser::HandleMacroExit() {
11911188
ActiveMacros.pop_back();
11921189
}
11931190

1191+
static void MarkUsed(const MCExpr *Value) {
1192+
switch (Value->getKind()) {
1193+
case MCExpr::Binary:
1194+
MarkUsed(static_cast<const MCBinaryExpr*>(Value)->getLHS());
1195+
MarkUsed(static_cast<const MCBinaryExpr*>(Value)->getRHS());
1196+
break;
1197+
case MCExpr::Target:
1198+
case MCExpr::Constant:
1199+
break;
1200+
case MCExpr::SymbolRef: {
1201+
static_cast<const MCSymbolRefExpr*>(Value)->getSymbol().setUsed(true);
1202+
break;
1203+
}
1204+
case MCExpr::Unary:
1205+
MarkUsed(static_cast<const MCUnaryExpr*>(Value)->getSubExpr());
1206+
break;
1207+
}
1208+
}
1209+
11941210
bool AsmParser::ParseAssignment(StringRef Name) {
11951211
// FIXME: Use better location, we should use proper tokens.
11961212
SMLoc EqualLoc = Lexer.getLoc();
@@ -1199,6 +1215,8 @@ bool AsmParser::ParseAssignment(StringRef Name) {
11991215
if (ParseExpression(Value))
12001216
return true;
12011217

1218+
MarkUsed(Value);
1219+
12021220
if (Lexer.isNot(AsmToken::EndOfStatement))
12031221
return TokError("unexpected token in assignment");
12041222

@@ -1213,7 +1231,7 @@ bool AsmParser::ParseAssignment(StringRef Name) {
12131231
//
12141232
// FIXME: Diagnostics. Note the location of the definition as a label.
12151233
// FIXME: Diagnose assignment to protected identifier (e.g., register name).
1216-
if (Sym->isUndefined() && !Sym->isUsedInExpr())
1234+
if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable())
12171235
; // Allow redefinitions of undefined symbols only used in directives.
12181236
else if (!Sym->isUndefined() && !Sym->isAbsolute())
12191237
return Error(EqualLoc, "redefinition of '" + Name + "'");
@@ -1222,13 +1240,14 @@ bool AsmParser::ParseAssignment(StringRef Name) {
12221240
else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
12231241
return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
12241242
Name + "'");
1243+
1244+
// Don't count these checks as uses.
1245+
Sym->setUsed(false);
12251246
} else
12261247
Sym = getContext().GetOrCreateSymbol(Name);
12271248

12281249
// FIXME: Handle '.'.
12291250

1230-
Sym->setUsedInExpr(true);
1231-
12321251
// Do the assignment.
12331252
Out.EmitAssignment(Sym, Value);
12341253

llvm/lib/MC/MCSymbol.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static bool NameNeedsQuoting(StringRef Str) {
4040
}
4141

4242
void MCSymbol::setVariableValue(const MCExpr *Value) {
43+
assert(!IsUsed && "Cannot set a variable that has already been used.");
4344
assert(Value && "Invalid variable value!");
4445
assert((isUndefined() || (isAbsolute() && isa<MCConstantExpr>(Value))) &&
4546
"Invalid redefinition!");

llvm/test/MC/ELF/set.s

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s
2+
3+
// Test that we accept .set of a symbol after it has been used in a statement.
4+
5+
jmp foo
6+
.set foo, bar
7+
8+
// or a .quad
9+
10+
.quad foo2
11+
.set foo2,bar2
12+
13+
// Test that there is an undefined reference to bar
14+
// CHECK: (('st_name', 0x00000001) # 'bar'
15+
// CHECK-NEXT: ('st_bind', 0x00000001)
16+
// CHECK-NEXT: ('st_type', 0x00000000)
17+
// CHECK-NEXT: ('st_other', 0x00000000)
18+
// CHECK-NEXT: ('st_shndx', 0x00000000)
19+
// CHECK-NEXT: ('st_value', 0x00000000)
20+
// CHECK-NEXT: ('st_size', 0x00000000)
21+
// CHECK-NEXT: ),

0 commit comments

Comments
 (0)