Bugfixer's question about how C calling convention corresponds to platform CC

Hi, I'm lost in the twisty maze of Tools.cpp and Toolchain.cpp in the course
of tracking down some regression test issues on ARM. I can see in
AsmWriter.cpp that an explicit call convention marker, such as ARM_AAPCS
will be emitted in every case except when the calling convention is C.
However, my impression is sometimes the C calling convention _is_ a specific
convention, such as ARM_AAPCS and in that case basic generated function
calls from clang are marked with a C calling convention. However, I'm
haven't been able to find the piece of code that implements this
"knowledge". Could anyone help point it out to me, or is this understanding
wrong? It looks like FileCheck expects CC markers to appear only when
explicitly requested and not that the triple-implied ABI CC marker gets
attached to every generated function: that's what a general user should
expect of clang as well?

(While I'm asking, I gather that configuration "magic" is basically written
in response to need from specific users (rather than attempting the mammoth
task of being complete). In Tools.cpp Clang::AddARMTargetArgs it a "default"
ABIName of "aapcs-linux" is set for the GNUEABI and GNUEABIHF triples from
the environment. Does anyone know what the use-case is that motivates that
is? It'd be useful to know so if the code does get changed I can try to get
it retested on that platform as well as the ones I've got access to.)

Many thanks for any insight,
David

You're looking for ARMABIInfo::computeInfo() in CodeGen/TargetInfo.cpp. ARM has an attribute that looks like __attribute__((pcs("aapcs-vfp"))) that allows you to pick the CC on a per-function basis.

I don't know what "aapcs-linux" is, but it's not one of the CCs from the ARM AAPCS spec last I looked.

Hi David,

(While I'm asking, I gather that configuration "magic" is basically written
in response to need from specific users (rather than attempting the mammoth
task of being complete). In Tools.cpp Clang::AddARMTargetArgs it a "default"
ABIName of "aapcs-linux" is set for the GNUEABI and GNUEABIHF triples from
the environment. Does anyone know what the use-case is that motivates that
is? It'd be useful to know so if the code does get changed I can try to get
it retested on that platform as well as the ones I've got access to.)

  You might need take a look on `svn log` to see who wrote that and ask
him why. Or you can try this

  http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?view=log

Regards,
chenwj

Hi, I'm lost in the twisty maze of Tools.cpp and Toolchain.cpp in the course
of tracking down some regression test issues on ARM. I can see in
AsmWriter.cpp that an explicit call convention marker, such as ARM_AAPCS
will be emitted in every case except when the calling convention is C.
However, my impression is sometimes the C calling convention _is_ a specific
convention, such as ARM_AAPCS and in that case basic generated function
calls from clang are marked with a C calling convention. However, I'm
haven't been able to find the piece of code that implements this
"knowledge". Could anyone help point it out to me, or is this understanding
wrong? It looks like FileCheck expects CC markers to appear only when
explicitly requested and not that the triple-implied ABI CC marker gets
attached to every generated function: that's what a general user should
expect of clang as well?

  What output you want? AFAIK, most test cases only expect to see something like,

    define void @foo

  rather then

    define arm_aapcs_vfpcc void @foo

From AssemblyWriter::printFunction,

  if (F->getCallingConv() != CallingConv::C) {
    PrintCallingConv(F->getCallingConv(), Out);
    Out << " ";
  }

if the function's calling convention is NOT C, then the result is NOT what FileCheck
expect. So do you expect no matter the triple is arm-linux-gnueabihf or arm-linux-gnueabi,
the result should be "define void @foo"? In other word, function's calling convention
should be C? If so, then we need to figure out how to set F->getCallingConv() to
CallingConv::C. Otherwise, those pattern in test cases need some tweaks.

Regards,
chenwj

Wei-Ren wrote

if the function's calling convention is NOT C, then the result is NOT what FileCheck
expect. So do you expect no matter the triple is arm-linux-gnueabihf or arm-linux-gnueabi,
the result should be "define void @foo"? In other word, function's calling convention
should be C? If so, then we need to figure out how to set F->getCallingConv() to
CallingConv::C. Otherwise, those pattern in test cases need some tweaks.

Apologies for the delay replying -- had a couple of days off.

My understanding is that somewhere in the code there should be an equating of the C calling convention with a platform specific convention, and from then on function definitions will automatically be output with the "no marker" form "define @foo". I _think_ what's happening it that this equating isn't occurring, so that when functions are created with the natural platform calling convention LLVM doesn't realise this convention is the same as the C convention, i.e., I don't think it's something that should need doing for each function but is a missing initialisation step.

However, we still need to figure out where this happens. Any insight from anyone appreciated.

Regards,
David Tweed

My understanding is that somewhere in the code there should be an equating of the C calling convention with a platform specific convention, and from then on function definitions will automatically be output with the "no marker" form "define @foo". I _think_ what's happening it that this equating isn't occurring, so that when functions are created with the natural platform calling convention LLVM doesn't realise this convention is the same as the C convention, i.e., I don't think it's something that should need doing for each function but is a missing initialisation step.

However, we still need to figure out where this happens. Any insight from anyone appreciated.

  Do you really think CC_AAPCS or CC_AAPCS_VFP sould be equal to C
calling convention? If so, how about making ClangCallConvToLLVMCallConv
return llvm::CallingConv::C for CC_AAPCS and CC_AAPCS_VFP like this?

--- lib/CodeGen/CGCall.cpp (revision 165477)
+++ lib/CodeGen/CGCall.cpp (working copy)
@@ -39,8 +39,9 @@
   case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
   case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
   case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
- case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS;
- case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP;
+ // CC_AAPCS and CC_AAPCS_VFP should be equal to CallingConv::C
+ case CC_AAPCS: return llvm::CallingConv::C;
+ case CC_AAPCS_VFP: return llvm::CallingConv::C;
   // TODO: add support for CC_X86Pascal to llvm
   }
}

Regards,
chenwj

Hi,

My understanding is that somewhere in the code there should be an equating of the C calling convention with a platform specific convention, and from then on function definitions will automatically be output with the "no marker" form "define @foo". I _think_ what's happening it that this equating isn't occurring, so that when functions are created with the natural platform calling convention LLVM doesn't realise this convention is the same as the C convention, i.e., I don't think it's something that should need doing for each function but is a missing initialisation step.

However, we still need to figure out where this happens. Any insight from anyone appreciated.

Do you really think CC_AAPCS or CC_AAPCS_VFP sould be equal to C
calling convention? If so, how about making ClangCallConvToLLVMCallConv
return llvm::CallingConv::C for CC_AAPCS and CC_AAPCS_VFP like this?

My understanding is that clang should be generating function calls with the appropriate default convention, and that default ought to be be being set somewhere in Toolchain.cpp or other driver files. I don't think your patch is right: there's a difference between using the default calling convention which happens to be X and explicitly asking, via function attributes, for a specific calling convention X; in the latter case it has to be preserved. (I think it would be legal, although probably insane, to have explicit calls using apcs, aapcs and aapcs_vfp in the same binary as well as whatever default is being used.) I'm still investigating.

Cheers,
Dave

  Do you really think CC_AAPCS or CC_AAPCS_VFP sould be equal to C
calling convention? If so, how about making ClangCallConvToLLVMCallConv
return llvm::CallingConv::C for CC_AAPCS and CC_AAPCS_VFP like this?

No, they should not. There is a possibility for user to override the
calling convention on ARM.

See http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html ('pcs' attribute)

My understanding is that clang should be generating function calls with the appropriate default convention, and that default ought to be be being set somewhere in Toolchain.cpp or other driver files. I don't think your patch is right: there's a difference between using the default calling convention which happens to be X and explicitly asking, via function attributes, for a specific calling convention X; in the latter case it has to be preserved. (I think it would be legal, although probably insane, to have explicit calls using apcs, aapcs and aapcs_vfp in the same binary as well as whatever default is being used.) I'm still investigating.

It's pretty fine to use both aapcs and aapcs_vfp in the same binary.
E.g. aapcs is used for varargs / library calls.

This is definitely incorrect. The user can select an explicit CC and have it used. CallingConv::C is for when none is specified.

Alex