Mikael Lyngvig
2013-Dec-03 23:10 UTC
[LLVMdev] Newbie question: LLVM IR, printf, and varargs
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. -- 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 >>> >>> >> >> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131204/f94e03db/attachment.html>
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>
Mikael Lyngvig
2013-Dec-04 00:56 UTC
[LLVMdev] Newbie question: LLVM IR, printf, and varargs
That explains why I didn't need two times "i32": call i32 i32(i8*, ...)* @printf (I actually tried that at one point). But I sort of sensed that I was heading for deep water when I decided to use printf; in all other samples I've stuck with puts because of the expected difficulties with varargs functions. Anyways, it is now documented. I do need to rephrase the documentation after this clarification, though. -- Mikael 2013/12/4 Sean Silva <chisophugis at gmail.com>> > > > 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/20131204/6859d895/attachment.html>
Maybe Matching Threads
- [LLVMdev] Newbie question: LLVM IR, printf, and varargs
- [LLVMdev] Newbie question: LLVM IR, printf, and varargs
- [LLVMdev] Newbie question: LLVM IR, printf, and varargs
- [LLVMdev] Newbie question: LLVM IR, printf, and varargs
- [LLVMdev] Newbie question: LLVM IR, printf, and varargs