[LLVMdev] Trouble with inline asm

Eli Friedman eli.friedman at gmail.com
Fri Jun 6 12:29:23 PDT 2008


On Fri, Jun 6, 2008 at 6:32 AM, Tomas Lindquist Olsen
<tomas.l.olsen at gmail.com> wrote:
> Hi all,
>
> I'm having some trouble with inline asm expressions, more specifically
> how to create the right FunctionType for a given constraint set.
> So far it has worked well for inputs, but not for outputs. The inline
> asm support in this language (which is D, LLVMDC[1]) is through asm
> *statements*.
> I never have inline asm *expressions*, and outputs are always via memory.
>
> I D my test looks like this:
>
> extern(C) int printf(char*,...);
> int main()
> {
>    int i = 12;
>    printf("%d\n", i);
>    asm
>    {
>        mov EAX, i;
>        add EAX, EAX;
>        mul EAX, 2;
>        mov i, EAX; // ***
>    }
>    printf("%d\n", i);
>    return 0;
> }

Equivalent C code using gcc inline asm:
int main() {
int i = 12;
printf("%d\n", i);
asm("movl %1, %%eax;add %%eax,%%eax;imull $2, %%eax; movl %%eax, %0":
"=g"(i):
"g"(i):
"%eax");
printf("%d\n", i);
return 0;
}

And the LL llvm-gcc generates:
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 = "i386-pc-linux-gnu"
@.str = internal constant [4 x i8] c"%d\0A\00"		; <[4 x i8]*> [#uses=1]

define i32 @main() nounwind  {
entry:
	%i = alloca i32		; <i32*> [#uses=4]
	store i32 12, i32* %i, align 4
	%tmp2 = call i32 (i8*, ...)* @printf( i8* getelementptr ([4 x i8]*
@.str, i32 0, i32 0), i32 12 ) nounwind 		; <i32> [#uses=0]
	%tmp3 = load i32* %i, align 4		; <i32> [#uses=1]
	call void asm "movl $1, %eax;add %eax,%eax;imull $$2, %eax; movl
%eax, $0", "=*imr,imr,~{dirflag},~{fpsr},~{flags},~{ax}"( i32* %i, i32
%tmp3 ) nounwind
	%tmp4 = load i32* %i, align 4		; <i32> [#uses=1]
	%tmp5 = call i32 (i8*, ...)* @printf( i8* getelementptr ([4 x i8]*
@.str, i32 0, i32 0), i32 %tmp4 ) nounwind 		; <i32> [#uses=0]
	ret i32 0
}

declare i32 @printf(i8*, ...) nounwind

>        call void asm sideeffect "movl $0, %eax", "m,~{eax}"( i32 %tmp2 )
>        call void asm sideeffect "addl %eax, %eax", "~{eax},~{eax}"( )
>        call void asm sideeffect "mull $0", "i,~{eax},~{edx},~{eax}"( i32 2 )

You can't safely split the lines of an asm like that; that's just
inviting trouble because the compiler can't know that eax shouldn't be
modified between the lines of the asm.  You have to map from one asm
block to one asm call.

> Now... No matter what I try I can't figure out what the function
> signature should be for the *** line. I always get the assertion:
>        InlineAsm.cpp:43: llvm::InlineAsm::InlineAsm(const
> llvm::FunctionType*, const std::string&, const std::string&, bool):
> Assertion `Verify(Ty, constraints) && "Function type not legal for
> constraints!"' failed.
>
> The inline expr I try to create is like:
>
>        call void asm sideeffect "movl %eax, $0", "=m" (i32* var)
>
> Any clues would be much appreciated! I'd like to say that I'm very new
> with this format of assembler, constraints etc.

It looks like you're missing the "*"?  The llvm syntax for this stuff
isn't very well documented; I'd suggest looking at llvm-gcc output if
you want to know how to write something in particular.

Good luck doing this; I imagine this is going to be tricky to
implement, especially converting from Intel to AT&T syntax.

-Eli



More information about the llvm-dev mailing list