[LLVMdev] GHC, aliases, and LLVM HEAD

Rafael Espíndola
Mon, 26 May 2014 15:26:06 -0000

On 25 May 2014 21:29, Ben Gamari <bgamari.foss at gmail.com>
wrote:
>
> Peter: Please feel free to correct me if there are any inaccuracies
>        below.
>
> 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.

> This unfortunately breaks GHC's LLVM code
> generator which referes to most symbols through aliases. This is done in
> two situations,
>
>   1. As place-holders for external symbols. As the code generator does
>      not know the type of these symbols until the point of usage (nor
>      does it need to), i8* aliases are defined at the end of the
>      compilation unit,
>
>          @newCAF = external global i8
>          @newCAF$alias = alias private i8* @newCAF
>
>      and functions in the current compilation unit calling `newCAF` invoke
>      it through `@newCAF$alias$`,
>
>          ...
>          %lnYi = bitcast i8* @newCAF$alias to i8* (i8*, i8*)*
>          ...

Sorry, I don't see what this buys you. The types of newFAC and
newCAF$alias are the same.

>   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.
Check for example what llvm-as does when a variable or a function is
used before it is defined. Doesn't that work for you?

>
> Unfortunately, recent LLVMs reject both of these uses. The first is
> rejected as aliases can no longer reference items other than
> definitions, e.g.
>
>     opt: hi.ll:414:36: error: Alias must point to function or variable
>     @SWn_srt$alias = alias private i8* bitcast (%SWn_srt_struct* @SWn_srt
to i8*)
>
> The second is rejected as aliasees must[2] be global objects, which
> bitcasts are not,
>
>     /home/ben/trees/root-llvm-head/bin/opt:
utils/hpc/dist-install/build/HpcParser.ll:44714:37: error: Alias must point to
function or variable
>     @c3rB_str$alias = alias private i8* bitcast (%c3rB_str_struct*
@c3rB_str to i8*)
>                                         ^
>
> Is our (ab)use of aliases reasonable? If so, what options do we have to
> fix this before LLVM 3.5? If not, what other mechanisms are there for
> addressing the use-cases above in GHC?

It looks fairly likely llvm will accept arbitrary expressions as
aliasees again (see thread on llvmdev), but the restrictions inherent
from what alias are at the object level will remain, just be reworded
a bit. For example, we will have something along the lines of "the
aliasee expression cannot contain an undefined GlobalValue".

Cheers,
Rafael