MC: Label definitions are permitted after .set directives
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 24 Dec 2014 10:27:50 +0000 (10:27 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 24 Dec 2014 10:27:50 +0000 (10:27 +0000)
.set directives may be overridden by other .set directives as well as
label definitions.

This fixes PR22019.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224811 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCSymbol.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/MC/MCParser/AsmParser.cpp
test/CodeGen/X86/pr22019.ll [new file with mode: 0644]
test/MC/ELF/alias.s

index 0b3c3ceb210f28b12e1162926e21232e8f569b61..47a8789d463b7f99acb1b9e25114944f9a460b97 100644 (file)
@@ -53,6 +53,9 @@ namespace llvm {
     /// "Lfoo" or ".foo".
     unsigned IsTemporary : 1;
 
+    /// \brief True if this symbol can be redefined.
+    unsigned IsRedefinable : 1;
+
     /// IsUsed - True if this symbol has been used.
     mutable unsigned IsUsed : 1;
 
@@ -61,7 +64,7 @@ namespace llvm {
     friend class MCContext;
     MCSymbol(StringRef name, bool isTemporary)
       : Name(name), Section(nullptr), Value(nullptr),
-        IsTemporary(isTemporary), IsUsed(false) {}
+        IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {}
 
     MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION;
     void operator=(const MCSymbol&) LLVM_DELETED_FUNCTION;
@@ -79,6 +82,19 @@ namespace llvm {
     bool isUsed() const { return IsUsed; }
     void setUsed(bool Value) const { IsUsed = Value; }
 
+    /// \brief Check if this symbol is redefinable.
+    bool isRedefinable() const { return IsRedefinable; }
+    /// \brief Mark this symbol as redefinable.
+    void setRedefinable(bool Value) { IsRedefinable = Value; }
+    /// \brief Prepare this symbol to be redefined.
+    void redefineIfPossible() {
+      if (IsRedefinable) {
+        Value = nullptr;
+        Section = nullptr;
+        IsRedefinable = false;
+      }
+    }
+
     /// @}
     /// @name Associated Sections
     /// @{
index 69e3a5df919d576f8ec6edc33f885fec7e8fd5e5..ec7da6b99c4a1136619e0e81912045f73e859cd7 100644 (file)
@@ -541,6 +541,8 @@ void AsmPrinter::EmitFunctionHeader() {
 /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the
 /// function.  This can be overridden by targets as required to do custom stuff.
 void AsmPrinter::EmitFunctionEntryLabel() {
+  CurrentFnSym->redefineIfPossible();
+
   // The function label could have already been emitted if two symbols end up
   // conflicting due to asm renaming.  Detect this and emit an error.
   if (CurrentFnSym->isUndefined())
index 9becb403d57165982658e5c5b6c312744bc54207..8eff90a9ef7f532a085647bf9ee53f7fdea2d27c 100644 (file)
@@ -1298,6 +1298,9 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
       Sym = getContext().GetOrCreateSymbol(IDVal);
     } else
       Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal);
+
+    Sym->redefineIfPossible();
+
     if (!Sym->isUndefined() || Sym->isVariable())
       return Error(IDLoc, "invalid symbol redefinition");
 
@@ -2217,6 +2220,8 @@ bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
   } else
     Sym = getContext().GetOrCreateSymbol(Name);
 
+  Sym->setRedefinable(allow_redef);
+
   // Do the assignment.
   Out.EmitAssignment(Sym, Value);
   if (NoDeadStrip)
diff --git a/test/CodeGen/X86/pr22019.ll b/test/CodeGen/X86/pr22019.ll
new file mode 100644 (file)
index 0000000..f4a1707
--- /dev/null
@@ -0,0 +1,12 @@
+; RUN: llc < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+module asm "pselect = __pselect"
+; CHECK: pselect = __pselect
+
+; CHECK: pselect:
+; CHECK: retq
+define void @pselect() {
+  ret void
+}
index 2e65ace6ba11df543c813760e0e67eae850bf28e..8e1318230bb8cd9d371eb980e5c7416569131769 100644 (file)
@@ -20,6 +20,10 @@ bar5 = bar4
 
         .long foo2
 
+// Test that bar6 is a function that doesn't have the same value as foo4.
+bar6 = bar5
+bar6:
+
 // CHECK:      Symbols [
 // CHECK-NEXT:   Symbol {
 // CHECK-NEXT:     Name:  (0)
@@ -58,6 +62,15 @@ bar5 = bar4
 // CHECK-NEXT:     Section: .text
 // CHECK-NEXT:   }
 // CHECK-NEXT:   Symbol {
+// CHECK-NEXT:     Name: bar6
+// CHECK-NEXT:     Value: 0x5
+// CHECK-NEXT:     Size: 0
+// CHECK-NEXT:     Binding: Local
+// CHECK-NEXT:     Type: None
+// CHECK-NEXT:     Other: 0
+// CHECK-NEXT:     Section: .text
+// CHECK-NEXT:   }
+// CHECK-NEXT:   Symbol {
 // CHECK-NEXT:     Name: foo
 // CHECK-NEXT:     Value: 0x0
 // CHECK-NEXT:     Size: 0