Calling conventions for K&R functions

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Calling conventions for K&R functions

Ken Dyck
I'm working on a Clang/LLVM backend for a DSP architecture and I'm a
little confused about calling conventions with callee functions declared
using K&R-style declarations in C.

Take this code, for example:

  int kr_callee(x) { return x; }
  int caller(int x) { return kr_callee(x); }

Clang (at least my aging one based on rev 108154) generates this LLVM IR
for it:

  target triple = "i686-pc-mingw32"

  define i32 @kr_callee(i32 %x) nounwind {
  entry:
    %x.addr = alloca i32, align 4                   ; <i32*> [#uses=2]
    store i32 %x, i32* %x.addr
    %tmp = load i32* %x.addr                        ; <i32> [#uses=1]
    ret i32 %tmp
  }

  define i32 @caller(i32 %x) nounwind {
  entry:
    %x.addr = alloca i32, align 4                   ; <i32*> [#uses=2]
    store i32 %x, i32* %x.addr
    %tmp = load i32* %x.addr                        ; <i32> [#uses=1]
    %call = call i32 (...)* bitcast (i32 (i32)* @kr_callee to i32
(...)*)(i32 %tmp) ; <i32> [#uses=1]
    ret i32 %call
  }

There seems to be a potential mismatch between the caller and the callee
here. The caller(), with its bitcast to i32(...)*, calls kr_callee()
with var-arg conventions. The definition of kr_callee() expects
fixed-arg conventions.

Is this intentional? Does a backend need to design its calling
conventions so that any fixed-arg function can be correctly called with
var-arg conventions?

-Ken

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Calling conventions for K&R functions

Chris Lattner

On Sep 19, 2010, at 2:56 AM, Ken Dyck wrote:

> I'm working on a Clang/LLVM backend for a DSP architecture and I'm a
> little confused about calling conventions with callee functions declared
> using K&R-style declarations in C.
>
> Take this code, for example:
>
>  int kr_callee(x) { return x; }
>  int caller(int x) { return kr_callee(x); }
>
> Clang (at least my aging one based on rev 108154) generates this LLVM IR
> for it:
>
>  target triple = "i686-pc-mingw32"
>
>  define i32 @kr_callee(i32 %x) nounwind {
>  entry:
>    %x.addr = alloca i32, align 4                   ; <i32*> [#uses=2]
>    store i32 %x, i32* %x.addr
>    %tmp = load i32* %x.addr                        ; <i32> [#uses=1]
>    ret i32 %tmp
>  }
>
>  define i32 @caller(i32 %x) nounwind {
>  entry:
>    %x.addr = alloca i32, align 4                   ; <i32*> [#uses=2]
>    store i32 %x, i32* %x.addr
>    %tmp = load i32* %x.addr                        ; <i32> [#uses=1]
>    %call = call i32 (...)* bitcast (i32 (i32)* @kr_callee to i32
> (...)*)(i32 %tmp) ; <i32> [#uses=1]
>    ret i32 %call
>  }
>
> There seems to be a potential mismatch between the caller and the callee
> here. The caller(), with its bitcast to i32(...)*, calls kr_callee()
> with var-arg conventions. The definition of kr_callee() expects
> fixed-arg conventions.
>
> Is this intentional? Does a backend need to design its calling
> conventions so that any fixed-arg function can be correctly called with
> var-arg conventions?

This is just how K&R C works.  The platform ABI should be designed to make both work: the varargs and fixed arg convention should overlap.  This is one of the reasons that ABI development is so tricky, and C is so evil :)

If you don't do this, then code like this won't work (at least with -fno-builtin):

int main() { printf("hello world %f\n", 1.0); }

because there is no prototype for printf, so it gets a fully vararg prototype by default.

-Chris
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev