Indirect call generation for other than native targets

Hello everyone,

   I encountered a behavior I don't quite understand in clang release 3.2 and I could not find any responses anywhere, so I would like to ask here.

As an example, I have a simple program such as this one:

void fun();

int main()
{

  fun();

  return 0;
}

No, when i run

clang test.c -emit-llvm -S -o i86_64.ll

i get this LLVM IR code which is what I would expect:

; ModuleID = 'test.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define i32 @main() nounwind uwtable {
entry:
   %retval = alloca i32, align 4
   store i32 0, i32* %retval
   call void (...)* @fun()
   ret i32 0
}

declare void @fun(...)

However, when I run clang like this with i386 target (or mips, or other targets):

clang test.c -target i386 -emit-llvm -S -o i386.ll

The caal to fun is indirect:

; ModuleID = 'test.c'
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-n8:16:32-S128"
target triple = "i386"

define i32 @main() nounwind {
entry:
   %retval = alloca i32, align 4
   store i32 0, i32* %retval
   call void bitcast (void (...)* @fun to void ()*)()
   ret i32 0
}

declare void @fun(...)

Please, what is the reason of this behavior, is it intentional? How can i make the nonnaticve targets generate direct calls?

Thank you
   Adam Husar

I don't understand the question. In both cases, you have a direct call. The only difference is that in the first it is being called as a variadic function with no arguments and in the latter as a non-variadic function of no arguments. In both cases, it's a direct call. Did you look at the assembly generated?

David

Hi David, thank you for your reply.

Here are some more details.
I need to process the code produced by clang later in my opt-like passes and
there, when I process the CallInst and ask for the called function
from this code:

  call void bitcast (void (...)* @fun to void ()*)()

like this:

CallInst* ci = dyn_cast<CallInst>(i);
Function* f = ci->getCalledFunction();

the pointer f is set to NULL and according to the comments for
CallInst::getCalledFunction, the call is indirect:

   /// getCalledFunction - Return the function called, or null if this is an
   /// indirect function invocation.

Also e.g. methods for attribute manipulation alway return zero or do nothing if the call is indirect.

What is strange to me, is that for the target x86_64 clang generates direct call, and
for target i386, there is an indirect call (on 64-bit Fedora 17).

Adam

It's not really an indirect invocation. The problem is that getCalledFunction()
does not look through bitcasts. That's generally for the good, because
otherwise code that uses it would have to be extremely defensive about
type mismatches, but it does complicate things like the definition of a direct call.

clang started inserting the bitcast relatively recently in order to fix some
longstanding problems with variadic calls on some platforms. Specifically,
on MIPS it is invalid to call a non-variadic function as if it were a variadic one
because variadic arguments are always passed on the stack. This makes it
quite important that unprototyped calls not generate an apparently variadic
call (which, in turn, means you cannot call e.g. printf without a prototype, but
that's acceptable platform behavior under the C standard), except on a handful
of platforms (like x86-64) that explicitly specify that unprototyped calls should
follow the variadic conventions. On i386 (and many others) it's a wash, but
I wanted the default behavior to follow the MIPS logic (and maybe generate
slightly less pretty IR) instead of requiring every MIPS-like platform to opt in
to correctness.

John.