[LLVMdev] GHC, aliases, and LLVM HEAD

Rafael EspĂ­ndola rafael.espindola at gmail.com
Mon May 26 14:56:12 PDT 2014


>> On 25 May 2014 21:29, Ben Gamari <bgamari.foss at gmail.com> wrote:
>>>
>>> For a while now LLVM has started rejecting aliases referring to things
>>> other than definitions[1].
>>
>> We started checking for it. Aliases are just another label in an
>> object file. The linker itself doesn't know they exist and therefore
>> there is no way to represent an alias from foo to bar if bar is
>> undefined.
>>
> Sure. I think the only reason our use of aliases worked previously was
> that the optimizer elided them long before they could make it into an
> object file.

If that is the case, you should be able to just directly replace alias
with aliasee, no? In general you should not depend on an optimization
being run to produce correct code.

>>>   2. As place-holders for local symbols. All symbol references in
>>>      emitted functions are replaced with references to aliases.  This is
>>>      done so that the compiler can emit LLVM IR definitions for
>>>      functions without waiting for symbols they reference to become
>>>      available (as our internal representation, Core, allows references
>>>      in any order without forward declarations). This theoretically
>>>      offers a performance improvement and somewhat simplifies the code
>>>      generator. Here we emit aliases like,
>>>
>>>          @SWn_srt$alias = alias private i8* bitcast (%SWn_srt_struct* @SWn_srt to i8*)
>>>
>>>      again, using the `$alias` in all references,
>>
>> That should also work in llvm IR. You can create a function without a
>> body or a GlobalVariable without an initializer and add it afterwards.
>>
> I'm not sure I follow. If I attempt to compile,
>
>     declare i32 @main()
>     define i32 @main() {
>         ret i32 0
>     }
>
> It fails with,
>
>     llc: test.ll:3:12: error: invalid redefinition of function 'main'
>     define i32 @main() {

There are no redeclarations in LLVM IR. You can just put  top level
entities in any order:

define void @f() {
  call void @g()
  call void @h()
  ret void
}
declare void @g()
define void @h() {
  ret void
}

> The problem here is that we don't know the type of the symbol at the
> point of use so I need to assume it is something (e.g. i8*). Take for
> instance the following example,
>
>
>     define i32 @main() {
>         // We don't know the type of f a priori, thus we assume
>         // it is i8*
>         %f = bitcast i8* f$alias to i32 ()*
>         call i32 %f()
>         ret i32 0
>     }

Instead of having an f$alias, you could just have produced a

declare void f()

since you know the type it is being called with.

> Say then later in GHC's Core representation, we get a definition for
> `f`. We have two ways of dealing with this,
>
>     1. Declare it as @f and create an alias as we currently do,
>
>            define i32 @f() {
>                ret i32 0
>            }
>            @f$alias = alias private i8* @f
>
>        but then we fail with recent LLVMs
>
>
>     2. Declare it as @f$alias directly as I think you might be suggesting
>
>            define i32 @f$alias() {
>                ret i32 0
>            }
>
>        but then we get a type mismatch at the point of usage as we claim
>        that @f$alias is of type i8*.
>
>

No, the idea is to not have f$alias at all. Once you find that f has
to be defined, you just set its body (which turns it into a
definition).

I guess a better example might have been clang compiling:

void f(void);
void g(void) {
  f();
}
void f(void) {
}

In here f will be converted from a declaration to a definition.

Cheers,
Rafael



More information about the llvm-dev mailing list