LLVM should support symbol aliasing (the one, produced via __attribute((alias))__ in gcc). It seems, this is the main reason of PR1006, since compatibility is achieved via symbol aliasing. Aliasing, seems, can be done in some painless way for functions: just clone it or output the "stub", which will call original one. Anyway, this is just cheap workaround. Aliasing should be introduced for GV's also.
Sorry, I was wrong. alias is function attribute (in accordance to http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/gcc/Function-Attributes.html). So, maybe it will be better just to emit stub?
Can you include a link to spec that describes what aliases and weak aliases do, and how they are handled by the linker? Maybe the gas/gnu ld manuals describe them.
The codegen for aliases seems to be higly platform-dependend. However, I've tested it on Linux & mingw32 targets and both resulted to the same code: 1. Input void my_memcpy(void* outp, const void* inp, size_t length) __attribute__((alias("memcpy"), weak)); 2. Output 2.1 Mingw32 (note, there is no "weak" attribute here, since there are no weak symbols here) .globl _my_memcpy .set _my_memcpy,_memcpy 2.1 Linux .weak _my_memcpy .set _my_memcpy,_memcpy In terms of LLVM, my_memcpy gets external weak linkage, since there is no code for it. The documentation for .set is here: http://sourceware.org/binutils/docs-2.17/as/Pseudo-Ops.html#Pseudo-Ops
Well. It was much discussion about symbol aliases in llvm-commits. Let's move here. Terminology: 1. Alias Alias is an external function/variable declaration with extra "alias target". This addendum causes the declaration to be emitted as an alias for another symbol. So, all uses of alias will be substituted by alias target by linker. Examples: - gcc: void foo() __attribute__ ((alias ("bar"))); - LLVM (proposed): declare void @foo() alias "bar" 2. Alias target. The target symbols of an alias. E.g. "bar" in this examples 3. Function/Variable part of an alias. This is alias with target part removed. This part is just external function/variable declaration. Features: Aliases acts as external function/variable declaration. So, they can have linkage (external, external weak), function aliases can have CC.
My last proposal was: 1. Introduce new table in the Module for alias targets. 2. User normal Function's and GV's for aliases. They will be just external function/variable *declarations*. Everything will be ok. 3. Add methods setAliasTarget(), stripAlias() to GV class to add/remove entries to alias target table. +some utility functions to deal with this table during e.g. object destruction/copying/parent change. 4. Let Verifier reject such GV's and Functions, which has initializer/body and entry in the alias target table. 5. AsmParser should reject usage of alias and initializer/body as well. 6. Let Linker "propagate" alias targets, if possible. 7. During codegen query alias target entry for each MO_ExternalSymbol to check, whether there is any alias target. And emit needed code.
Created attachment 792 [details] Proposed solution This patch implements the proposed solution. Linker & Verifier part is still missing, however. Both function aliases and variable aliases are supported. Also it does some ugly code cleanup and formatting cleanup. Hope, this won't make review harder.
Patch also lacks some comments describing methods. They will be added.
Overall, this approach is better than extending function or globalvar with information. However, the bad part of this approach is that it means that things which manipulate the global/function list of the module need to update the mapping. As one example, the dead argument elim pass deletes Functions and then reallocates them (with fewer arguments). With this design, each pass that does similar things would have to say "is there any aliases for this function? If so, move it". What is wrong with having a list of GlobalAlias objects in Module? -Chris
DAE shouldn't touch aliases, because they are external declarations. I don't see the difference between current approach and making new GlobalAliases class. The second approach (GA) is worse, because function aliases and variable aliases differs (For example, function aliases act like Function, so they have e.g. CC, argument list, etc.).
However, I agree, that code should be reviewed about creation of GV "copies".
> DAE shouldn't touch aliases, because they are external declarations. I don't see > the difference between current approach and making new GlobalAliases class. Actually, it makes a huge difference. Consider the following: static void foo(int X) alias 'bar' { no uses of X } void baz() { foo(1); } In this case, DAE will delete the X argument to foo, even though foo is aliased to bar, and external callers could call it, and will pass the argument. Thus, this is an illegal transformation. I propose that you model the code like this: @bar = alias void @foo(i32) define internal void @foo(i32 %X) { ... } define void @bar(... In this design, bar is an instance of the GlobalAlias class. The global alias class is required to have a name (enforced by the verifier) and has a single operand: the global that it is aliased to. If you followed this approach, it would be trivial for the codegen to emit the alias info to the .s file, and the use by the alias would make DAE see that this function is exposed to the outside world (it would treat it as having its address taken, which is the right thing). Also, because the alias uses the global as an operand, things like replacealluseswith would update the alias automatically etc. What is the disadvantage of this approach? -Chris
FWIW, the design Chris just proposed sounds right to me. Its close to what I was trying to get across on the llvm-commits list: just make the Alias class reference the thing it is renaming. Making a GlobalAlias class that derives from GlobalValue sounds like the right thing to me. In some cases, however, it might still be possible to have DAE alter an aliased function. A few things could be done: 1. If the Alias is internal, then DAE could update the calls to all the aliases as well. 2. If the Alias is external, it could create a body for the aliased function (with the arguments being removed) that just calls the modified function.
> 1. If the Alias is internal, then DAE could update the calls to all the > aliases as well. If the alias were internal, some other pass should have RAUW'd it with the target, then deleted it. > 2. If the Alias is external, it could create a body for the aliased function > (with the arguments being removed) that just calls the modified function. In practice, this probably isn't worth it. Even if it were, DAE could do this today for any address- exposed function if it wanted to, aliases aren't a special case here. -Chris
Created attachment 795 [details] New solution This patch implements GlobalAlias class among with all changes in bytecode reading/writing, codegen and asmprinting. Linker, Verifier and GlobalOpt's aliases propagation left for the second step. Example syntax: @foo = external global i32 @bar = external alias i32* @foo declare i32 @foo_f() @bar_f = extern_weak alias i32()* @foo_f define i32 @test() { entry: %tmp = load i32* @foo %tmp2 = call i32 @foo_f() %tmp3 = add i32 %tmp, %tmp2 ret i32 %tmp3 } Unfortunately I had to force linkage for aliases use same syntax as GV's external alias in order not to create additional parser conflicts.
The syntax will be changed to: @foo = external global i32 @bar = alias i32* @foo declare i32 @foo_f() @bar_f = alias weak i32()* @foo_f define i32 @test() { entry: %tmp = load i32* @foo %tmp2 = call i32 @foo_f() %tmp3 = add i32 %tmp, %tmp2 ret i32 %tmp3 } I won't resubmit patch, since this change won't affect the review.
Looks great. Just to check, this is legal too right: call i32 @bar_f() -Chris
Hmm. This seems to be illegal, because aliases are "seen" as externals. So, in order to make a call, extra load will be needed, e.g. something like this: %tmp_f = load %FunTy** @bar_f %tmp4 = call %FunTy* %tmp_f() Should this behaviour be fixed with function aliases?
I thought aliases are "another name for" the global. If so, you should be able to refer to the global or the alias with equivalent effect, no? In other words, the global and the alias should have the same type. -Chris
Yes, definitely. Fixed.
Implemented with: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070423/048406.html http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070423/048407.html http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070423/048408.html ... http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070423/048418.html llvm-gcc part will follow