[LLVMdev] naked assembler / function written entirely in asm
Tomas Lindquist Olsen
tomas.l.olsen at gmail.com
Fri Jan 9 14:47:36 PST 2009
Hi everybody.
I'm having (yet) another look at trying to get naked functions from D (1)
working in our LLVM D Compiler - LDC (2).
I have this test case:
/// D CODE
///
extern(C) int printf(char*, ...);
ulong retval() {
asm { naked; mov EAX, 0xff; mov EDX, 0xaa; ret; }
}
ulong retval2() {
return (cast(ulong)0xaa << 32) | 0xff;
}
void main() {
printf("%llu\n%llu\n", retval(), retval2());
}
///
///
I've tried out a few things. This currently compiles to:
///
///
target datalayout =
"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
target triple = "i686-pc-linux-gnu"
@.str1 = internal constant [11 x i8] c"%llu\0A%llu\0A\00" ;
<[11 x i8]*> [#uses=1]
declare i32 @printf(i8*, ...)
define x86_stdcallcc i64 @_D3bar6retvalFZm() noinline {
entry:
call void asm sideeffect "movl $0, %eax ; movl $1, %edx ; ret ",
"i,i,~{eax},~{edx}"(i32 255, i32 170)
unreachable
}
define x86_stdcallcc i64 @_D3bar7retval2FZm() {
entry:
ret i64 730144440575
}
define x86_stdcallcc i32 @_Dmain({ i32, { i32, i8* }* } %unnamed) {
entry:
%tmp = call x86_stdcallcc i64 @_D3bar6retvalFZm() ;
<i64> [#uses=1]
%tmp1 = call x86_stdcallcc i64 @_D3bar7retval2FZm() ;
<i64> [#uses=1]
%tmp2 = call i32 (i8*, ...)* @printf(i8* getelementptr ([11 x i8]*
@.str1, i32 0, i32 0), i64 %tmp, i64 %tmp1) ; <i32> [#uses=0]
ret i32 0
}
///
///
When this is linked as an application, without being optimized, it works as
expected.
But when optimized, _Dmain is reduced to:
///
///
define x86_stdcallcc i32 @_Dmain({ i32, { i32, i8* }* } %unnamed) noreturn
nounwind {
entry:
%tmp = call x86_stdcallcc i64 @_D3bar6retvalFZm() ;
<i64> [#uses=0]
unreachable
}
///
///
If the first impl is changed to:
///
///
define x86_stdcallcc i64 @_D3bar6retvalFZm() noinline {
entry:
call void asm sideeffect "movl $0, %eax ; movl $1, %edx ; ret ",
"i,i,~{eax},~{edx}"(i32 255, i32 170)
ret i64 undef ;
}
///
///
It still works when not optimized. However, when optimized, then _Dmain
becomes:
///
///
define x86_stdcallcc i32 @_Dmain({ i32, { i32, i8* }* } %unnamed) {
entry:
%tmp = call x86_stdcallcc i64 @_D3bar6retvalFZm() ;
<i64> [#uses=0]
%tmp1 = call x86_stdcallcc i64 @_D3bar7retval2FZm() ;
<i64> [#uses=0]
%tmp2 = call i32 (i8*, ...)* @printf(i8* getelementptr ([11 x i8]*
@.str1, i32 0, i32 0), i64 undef, i64 730144440575) ; <i32>
[#uses=0]
ret i32 0
}
///
///
which (as expected) prints a bogus value.
I realize I'm entering some undefined/invalid territory here, but I'd really
like to get some ideas for what I could do to make this D code work.
Ideally I would like a naked attribute for a function which would mean that
the entire function is composed of a single asm block.
Module level assembler could probably be used for this, but it would be nice
if we could get away with using a single asm translator in the compiler.
Thanx in advance,
- Tomas Lindquist Olsen
----------------------
(1): http://digitalmars.com/d/1.0/index.html
(2): http://dsource.org/projects/ldc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20090109/e4d76103/attachment.html>
More information about the llvm-dev
mailing list