[LLVMbugs] [Bug 3163] New: llvm-gcc generates incorrect LLVM IR for weakref

bugzilla-daemon at cs.uiuc.edu bugzilla-daemon at cs.uiuc.edu
Wed Dec 3 13:33:02 PST 2008


http://llvm.org/bugs/show_bug.cgi?id=3163

           Summary: llvm-gcc generates incorrect LLVM IR for weakref
           Product: tools
           Version: 2.4
          Platform: PC
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: llvm-gcc
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: jasandov at rice.edu
                CC: llvmbugs at cs.uiuc.edu


Created an attachment (id=2263)
 --> (http://llvm.org/bugs/attachment.cgi?id=2263)
proposed patch

llvm-gcc generates incorrect LLVM IR for certain cases that use weakref
(weakref is described here: 
http://people.redhat.com/aoliva/writeups/weakref/weakref.txt).  Consider the
two c programs:

/* weakref_noref.c: */
extern void foo(void);
static void foo_alias(void) __attribute__ ((weakref("foo")));
int main() {
  if (foo_alias) foo_alias();
  return 0;
}


/* weakref_ref.c: */
extern void foo(void);
static void foo_alias(void) __attribute__ ((weakref("foo")));
int main() {
  if (foo_alias) foo_alias();
  foo();
  return 0;
}


foo is declared as an external function, and foo_alias is defined as a weakref
to foo.  In the first example, foo is never referenced in the file, so the
semantics of weakref dictate that foo (the target of the weakref) should be
changed to an external weak symbol.  In the second example, foo is referenced
so it should remain unchanged by the weakref definition.  In both cases, the
uses of foo_alias should be replaced with foo (since foo_alias is an internal
symbol, all uses are known).

Compiling these files with llvm-gcc results in a correct object file, but the
LLVM IR is incorrect.  The assembly output from the native code generator is
not technically correct, but it still seems to result in correct object file. 
The problem really appears in the CBE, as discovered in bug #3059.

The output from the standard gcc installation uses the .weakref directive in
the assembly output:
$ gcc -S weakref_noref.c weakref_ref.c 
$ grep foo weakref_noref.s weakref_ref.s
weakref_noref.s:        movl    $foo_alias, %eax
weakref_noref.s:        call    foo_alias
weakref_noref.s:        .weakref        foo_alias,foo
weakref_ref.s:  movl    $foo_alias, %eax
weakref_ref.s:  call    foo_alias
weakref_ref.s:  call    foo
weakref_ref.s:  .weakref        foo_alias,foo

The output from llvm-gcc with the x86-64 backend uses the .weak directive,
incorrectly specifying the foo_alias as weak:

$ llvm-gcc -S weakref_noref.c weakref_ref.c 
$ grep foo weakref_noref.s weakref_ref.s
weakref_noref.s:        leaq    foo_alias, %rax
weakref_noref.s:        call    foo_alias
weakref_noref.s:        .weak   foo_alias
weakref_noref.s:        .set     foo_alias, foo
weakref_noref.s:        .weak   foo
weakref_ref.s:  leaq    foo_alias, %rax
weakref_ref.s:  call    foo_alias
weakref_ref.s:  call    foo
weakref_ref.s:  .weak   foo_alias
weakref_ref.s:  .set     foo_alias, foo

The LLVM IR output confirms the incorrect definition for the alias:

$ llvm-gcc -S -emit-llvm weakref_noref.c weakref_ref.c
$ grep foo weakref_noref.s weakref_ref.s
weakref_noref.s:@foo_alias = alias weak void ()* @foo           ; <void ()*>
[#uses=2]
weakref_noref.s:        br i1 icmp ne (void ()* @foo_alias, void ()* null),
label %bb, label %bb1
weakref_noref.s:        call void @foo_alias() nounwind
weakref_noref.s:declare extern_weak void @foo()
weakref_ref.s:@foo_alias = alias weak void ()* @foo             ; <void ()*>
[#uses=2]
weakref_ref.s:  br i1 icmp ne (void ()* @foo_alias, void ()* null), label %bb,
label %bb1
weakref_ref.s:  call void @foo_alias() nounwind
weakref_ref.s:  call void @foo() nounwind
weakref_ref.s:declare void @foo()


The declaration of foo appears correct, since it is an extern_weak declaration
for the case where foo is not referenced (other than through weakref) and it is
a normal (strong) declaration for the case in which foo is referenced. 
However, the definition of foo_alias is incorrect -- it is defined as a weak
alias, but it should be an internal alias (since the definition in the c source
code is static).  The alias itself (from a weakref) should not be weak.

Since LLVM does not currently have the capability to represent a weakref, it
seems easiest to resolve all weakrefs in the llvm-gcc front end before
generating LLVM IR.  In fact, since the weakref is basically an internal alias,
we can eliminate the alias and replace all uses with the aliasee.  Essentially,
this is what the assembler does for the .weakref directive
(http://people.redhat.com/aoliva/writeups/weakref/weakref.txt).  I have
attached a proposed patch to do this.

Using my patched version of llvm-gcc, I now get the following output:

$ llvm-gcc -S weakref_noref.c weakref_ref.c
$ grep foo weakref_noref.s weakref_ref.s
weakref_noref.s:        leaq    foo, %rax
weakref_noref.s:        call    foo
weakref_noref.s:        .weak   foo
weakref_ref.s:  call    foo
weakref_ref.s:  call    foo

$ llvm-gcc -S -emit-llvm weakref_noref.c weakref_ref.c
$ grep foo weakref_noref.s weakref_ref.s
weakref_noref.s:        br i1 icmp ne (void ()* @foo, void ()* null), label
%bb, label %bb1
weakref_noref.s:        call void @foo() nounwind
weakref_noref.s:declare extern_weak void @foo()
weakref_ref.s:  call void @foo() nounwind
weakref_ref.s:  call void @foo() nounwind
weakref_ref.s:declare void @foo()

As shown, all uses of foo_alias are replaced with the target of the weakref
(foo).  The declaration for foo is correct for both cases (it is extern_weak
when foo is only referenced through weakref, and it is extern when foo is
referenced directly).  The x86-64 native code generator now generates correct
assembly code and the CBE generates correct code (since there is no alias to
deal with anymore).  This patch should also resolve the problem in bug #3059.

Could somebody more knowledgeable about the guts of llvm-gcc take a look at the
patch and provide some feedback?  It works for this case, but that definitely
doesn't mean it's correct.  Thanks!


-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list