[llvm-commits] patch: teach deadargelim to work on externally visible functions!

Rafael Espindola espindola at google.com
Mon Jan 11 10:01:50 PST 2010


>> *) Generate that linkage on ELF if the visibility is not hidden or protected
>> *) Add the "strong but overridable" linkage you proposed.
>
> Sounds good.  How is it different than our current "weak" linkage?

It is a dynamic x static linker issue. The static linker will flag an
error if two files define the same function for example.

>> *) As an extension, add a
>> protected-and-dont-care-about-pointer-compare that would be similar to
>> the current state but drop the @PLT
>
> This is something that would be a useful extension in any case.  Right now we may miscompile this code in some cases:
>
> static const char x[] = "foo";
> static const char y[] = "foo";
> int test() { return x == y; }
>
> Because we (incorrectly) merge the x and y decls.  We don't want to merge user variables if they have their "address taken", but we do want to merge things like C string literals (char *X = "foo").

your idea is that we would lower

static const char x[] = "foo";

to

@x = internal constant [4 x i8] c"foo\00", align 1

and

const char *x = "foo";

to

@.str = private constant [4 x i8] c"foo\00", ***mergeable****
@x = global i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), align 8


Having a "mergeable" flag is probably useful, but mostly orthogonal to
this issue I think. With a overridable and extern_overridable linkage
type we could lower

void __attribute__((visibility ("default"))) f(void);
void __attribute__((visibility ("default"))) g(void) {
  f();
}

to

define overridable void @g() nounwind {
entry:
  tail call void @f() nounwind
  ret void
}

declare extern_overridable void @f()

The mergeble flag would be useful to mark functions that we know don't
have the address taken so that we can merge them, but that is a
different issue.

A design question:
  Should we really add a new linkage type? We already have visibility
in the IL. We could change mayBeOverridden to return true for the
default visibility and lower to protected (or a new
protected-and-don't-care-about-pointer-compare) by default. Another
option is to go the other way and merge visibility into the linkage
type.

>> How does this work on Darwin btw? Function pointers are not guaranteed
>> to compare when crossing shared library boundaries?
>
> On darwin you're not allowed to redefined something in a different dylib unless it is attribute(weak).  Darwin uses a "two level namespace".  This causes the static linker to resolve and remember which dylib a "use" comes from.  If a third dylib starts defining that symbol, the use will still get the correct definition from the original defining dylib.  This also makes dynamic symbol resolution more efficient at process start time.

Very interesting design!

> -Chris

Cheers,
-- 
Rafael Ávila de Espíndola




More information about the llvm-commits mailing list