[LLVMdev] Newbie question: LLVM IR, printf, and varargs

Sean Silva chisophugis at gmail.com
Tue Dec 3 16:42:43 PST 2013


On Tue, Dec 3, 2013 at 6:10 PM, Mikael Lyngvig <mikael at lyngvig.org> wrote:

> Whoops...  Seems I forgot the asterisk (*) after the cast.  Or something.
>  Because I did insert the cast and it didn't work.  But NOW it works.
>  Thank you for spending some time on this - and also for presenting the
> solution.
>

It's not a "cast" for any meaning of cast in the language. It's just that
there's a hack, which is that if the type in front of the call is a
function pointer type, then that is used *as the type of the thing being
called*, while if it's not, then it is used *as the return type*, and the
type of the call is inferred from the arguments present on the instruction.
See this chunk of code in lib/AsmParser/LLParser.cpp:

  // If RetType is a non-function pointer type, then this is the short
syntax
  // for the call, which means that RetType is just the return type.  Infer
the
  // rest of the function argument types from the arguments that are
present.
  PointerType *PFTy = 0;
  FunctionType *Ty = 0;
  if (!(PFTy = dyn_cast<PointerType>(RetType)) ||
      !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
    // Pull out the types of all of the arguments...
    std::vector<Type*> ParamTypes;
    for (unsigned i = 0, e = ArgList.size(); i != e; ++i)
      ParamTypes.push_back(ArgList[i].V->getType());

    if (!FunctionType::isValidReturnType(RetType))
      return Error(RetTypeLoc, "Invalid result type for LLVM function");

    Ty = FunctionType::get(RetType, ParamTypes, false);
    PFTy = PointerType::getUnqual(Ty);
  }


-- Sean Silva


>
>
> -- Mikael
>
>
> 2013/12/4 Eli Bendersky <eliben at google.com>
>
>> This code:
>>
>> declare i32 @printf(i8* nocapture readonly, ...) nounwind
>>
>> define i32 @bar(i8* %c, i32 %i) #0 {
>> entry:
>>   %call = tail call i32 (i8*, ...)* @printf(i8* %c, i8* %c)
>>   ret i32 %call
>> }
>>
>> Is accepted without complaints by close-to-trunk llc on my Ubuntu machine.
>>
>> Eli
>>
>>
>> On Tue, Dec 3, 2013 at 2:58 PM, Mikael Lyngvig <mikael at lyngvig.org>wrote:
>>
>>> I just tried adding the cast but it didn't help.  I have the feeling
>>> that I am overlooking something very obvious, but I can't seem to figure
>>> out what it is.  Thanks for your suggestion, though.
>>>
>>>
>>> -- Mikael
>>>
>>>
>>>
>>> 2013/12/3 Eli Bendersky <eliben at google.com>
>>>
>>>>
>>>>
>>>>
>>>> On Tue, Dec 3, 2013 at 2:29 PM, Mikael Lyngvig <mikael at lyngvig.org>wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> I am trying to print two strings using printf.  I have tried various
>>>>> things, but keep getting this error:
>>>>>
>>>>>     llc: printf.ll:4:11: error: '@printf' defined with type 'i32 (i8*,
>>>>> ...)*'
>>>>>         %1 = call i32 @printf(i8* null, i8*, i8* null)
>>>>>
>>>>> The code is:
>>>>>
>>>>>    declare i32 @printf(i8* nocapture readonly, ...) nounwind
>>>>>
>>>>>    define i32 @main() nounwind {
>>>>>       %1 = call i32 @printf(i8* null, i8* null)
>>>>>       ret i32 0
>>>>>   }
>>>>>
>>>>> I am aware that the call will core dump, but I am initially only
>>>>> trying to figure out why LLC won't accept the call itself.  I started out
>>>>> trying with real values and then reduced it to the above to see if I could
>>>>> make it work.  Comparing with the output of Clang didn't help; it does the
>>>>> same - passes in two i8* pointers and declares @printf in the same way (and
>>>>> LLC accepts the Clang output as valid input).  The Clang code goes as
>>>>> follows (edited snippet):
>>>>>
>>>>> @.str = private unnamed_addr constant [11 x i8] c"Error: %s\0A\00",
>>>>> align 1
>>>>> @.str1 = private unnamed_addr constant [5 x i8] c"Test\00", align 1
>>>>>
>>>>> define i32 @main() nounwind {
>>>>>   %1 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
>>>>> ([11 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8]*
>>>>> @.str1, i32 0, i32 0)) nounwind
>>>>>   ret i32 0
>>>>> }
>>>>>
>>>>> declare i32 @printf(i8* nocapture readonly, ...) nounwind
>>>>>
>>>>> A good thing about this question is that the answer will find its way
>>>>> into the Mapping Highlevel doc, which is why I am asking it in the first
>>>>> place.
>>>>>
>>>>> This is on Windows using a 32-bit version of LLVM llc v3.4 (built
>>>>> about a week ago).
>>>>>
>>>>> I searched the LR, the FAQ, and Google but found nothing of relevance.
>>>>>
>>>>>
>>>> You're missing the cast, IMHO. The cast appeases the LLVM type checker
>>>> w.r.t. mismatching function type
>>>>
>>>> Eli
>>>>
>>>>
>>>
>>>
>>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131203/4f8f43eb/attachment.html>


More information about the llvm-dev mailing list