Alberto Barbaro via llvm-dev
2019-Mar-12 18:33 UTC
[llvm-dev] Help with bitcast instruction
Hi Tim, I'm still struggling on the instruction: call void bitcast (void (%struct.png_struct_def.68*, i8*, i8* (%struct.png_struct_def.68*, i64)*, void (%struct.png_struct_def.68*, i8*)*)* @png_set_mem_fn to void (%struct.png_struct_def*, i8*, i8* (%struct.png_struct_def*, i64)*, void (%struct.png_struct_def*, i8*)*)*)(%struct.png_struct_def* %create_struct, i8* %mem_ptr, i8* (%struct.png_struct_def*, i64)* %malloc_fn, void (%struct.png_struct_def*, i8*)* %free_fn) #15 I'm pretty sure that this is a CallInst but when I try to call getCalledFunction() I receive a null pointer and that really surprise me. I would like to understand how to get the function that is called and its parameters. Can you tell me how please? Am i right saying that: (void (%struct.png_struct_def.68*, i8*, i8* (%struct.png_struct_def.68*, i64)*, void (%struct.png_struct_def.68*, i8*)*)* -> "old parameters type" (%struct.png_struct_def*, i8*, i8* (%struct.png_struct_def*, i64)*, void (%struct.png_struct_def*, i8*)*)*) -> "new parameters type" (%struct.png_struct_def* %create_struct, i8* %mem_ptr, i8* (%struct.png_struct_def*, i64)* %malloc_fn, void (%struct.png_struct_def*, i8*)* %free_fn) "the parameters passed to the png_set_mem_fn" As a clarification the function is declared like this: void PNGAPI png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn) Thanks again Il giorno dom 10 mar 2019 alle ore 08:59 Tim Northover < t.p.northover at gmail.com> ha scritto:> Hi Alberto, > > > I would like to understand where bitcast is defined because it is not > defined within libpng. > > It's because the function (@png_set) has been defined to take one kind > of argument, but is being called with another. In this case the > difference seems to be whether it takes pointers to > %struct.png_struct_def or %struct.png_struct_def.68. > > This kind of situation isn't terribly common, but can happen for > example in LTO where two modules are linked together, and one of them > only has an opaque handle for the type to hide the implementation > (e.g. from plain "struct png_struct_def;" in C). When that happens > LLVM can't merge the types, so it adds a numeric tag to one of them, > and then it has to insert bitcasts in the calls like this so that its > own type system works. > > > I also noticed that the @ is not present, what does the missing @ mean? > I guess it must be an LLVM function. > > The @ is only used directly before a global variable (including a > declared/defined function). In this case it's buried, but it is there > (@png_set). In other cases, like when you call a function pointer, it > will be missing entirely. > > Cheers. > > Tim. >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190312/e86792d3/attachment.html>
Alberto Barbaro via llvm-dev
2019-Mar-12 18:43 UTC
[llvm-dev] Help with bitcast instruction
Hi, sorry I forgot to mention, how can I extract the keyword bitcast? I would like to be able to distinguish the function name. Thanks Il giorno mar 12 mar 2019 alle ore 18:33 Alberto Barbaro < barbaro.alberto at gmail.com> ha scritto:> Hi Tim, > I'm still struggling on the instruction: > > call void bitcast (void (%struct.png_struct_def.68*, i8*, i8* > (%struct.png_struct_def.68*, i64)*, void (%struct.png_struct_def.68*, > i8*)*)* @png_set_mem_fn to void (%struct.png_struct_def*, i8*, i8* > (%struct.png_struct_def*, i64)*, void (%struct.png_struct_def*, > i8*)*)*)(%struct.png_struct_def* %create_struct, i8* %mem_ptr, i8* > (%struct.png_struct_def*, i64)* %malloc_fn, void (%struct.png_struct_def*, > i8*)* %free_fn) #15 > > I'm pretty sure that this is a CallInst but when I try to call > getCalledFunction() I receive a null pointer and that really surprise me. > > I would like to understand how to get the function that is called and its > parameters. Can you tell me how please? > > Am i right saying that: > > (void (%struct.png_struct_def.68*, i8*, i8* (%struct.png_struct_def.68*, > i64)*, void (%struct.png_struct_def.68*, i8*)*)* -> "old parameters type" > (%struct.png_struct_def*, i8*, i8* (%struct.png_struct_def*, i64)*, void > (%struct.png_struct_def*, i8*)*)*) -> "new parameters type" > (%struct.png_struct_def* %create_struct, i8* %mem_ptr, i8* > (%struct.png_struct_def*, i64)* %malloc_fn, void (%struct.png_struct_def*, > i8*)* %free_fn) "the parameters passed to the png_set_mem_fn" > > As a clarification the function is declared like this: > > void PNGAPI > png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr > malloc_fn, png_free_ptr free_fn) > > > Thanks again > > > Il giorno dom 10 mar 2019 alle ore 08:59 Tim Northover < > t.p.northover at gmail.com> ha scritto: > >> Hi Alberto, >> >> > I would like to understand where bitcast is defined because it is not >> defined within libpng. >> >> It's because the function (@png_set) has been defined to take one kind >> of argument, but is being called with another. In this case the >> difference seems to be whether it takes pointers to >> %struct.png_struct_def or %struct.png_struct_def.68. >> >> This kind of situation isn't terribly common, but can happen for >> example in LTO where two modules are linked together, and one of them >> only has an opaque handle for the type to hide the implementation >> (e.g. from plain "struct png_struct_def;" in C). When that happens >> LLVM can't merge the types, so it adds a numeric tag to one of them, >> and then it has to insert bitcasts in the calls like this so that its >> own type system works. >> >> > I also noticed that the @ is not present, what does the missing @ mean? >> I guess it must be an LLVM function. >> >> The @ is only used directly before a global variable (including a >> declared/defined function). In this case it's buried, but it is there >> (@png_set). In other cases, like when you call a function pointer, it >> will be missing entirely. >> >> Cheers. >> >> Tim. >> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190312/b5e5e637/attachment.html>
Hi Alberto, On Tue, 12 Mar 2019 at 18:33, Alberto Barbaro <barbaro.alberto at gmail.com> wrote:> call void bitcast (void (%struct.png_struct_def.68*, i8*, i8* (%struct.png_struct_def.68*, i64)*, void (%struct.png_struct_def.68*, i8*)*)* @png_set_mem_fn to void (%struct.png_struct_def*, i8*, i8* (%struct.png_struct_def*, i64)*, void (%struct.png_struct_def*, i8*)*)*)(%struct.png_struct_def* %create_struct, i8* %mem_ptr, i8* (%struct.png_struct_def*, i64)* %malloc_fn, void (%struct.png_struct_def*, i8*)* %free_fn) #15 > > I'm pretty sure that this is a CallInst but when I try to call getCalledFunction() I receive a null pointer and that really surprise me. > > I would like to understand how to get the function that is called and its parameters. Can you tell me how please?The problem is that getCalledFunction is pretty naive, it just takes the getCalleeValue and dyn_cast<Function>s it. Because you've got a cast in the IR itself your situation is a bit more complicated. In this case, you could write a "findCalledFunction" something like: Function *findCalledFunction(CallBase &CI) { Value *Callee = CI.getCalledValue()->stripPointerCasts(); if (auto F = dyn_cast<Function>(Callee)) return F; return nullptr; } Where the "stripPointerCast" is the key extra ingredient that looks through the bitcast. (Someone could certainly argue that's what getCalledFunction should be doing anyway, but there are subtleties on weird targets like GPUs so it's not 100%). It won't catch all callsites (e.g. virtual function calls could still be plain %X values), but pretty much any algorithm has to be robust against an unknown callee anyway.> Am i right saying that: > > (void (%struct.png_struct_def.68*, i8*, i8* (%struct.png_struct_def.68*, i64)*, void (%struct.png_struct_def.68*, i8*)*)* -> "old parameters type" > (%struct.png_struct_def*, i8*, i8* (%struct.png_struct_def*, i64)*, void (%struct.png_struct_def*, i8*)*)*) -> "new parameters type" > (%struct.png_struct_def* %create_struct, i8* %mem_ptr, i8* (%struct.png_struct_def*, i64)* %malloc_fn, void (%struct.png_struct_def*, i8*)* %free_fn) "the parameters passed to the png_set_mem_fn"I think so, from what I understand. The essence of that cast is just changing one pointer type to another, so it doesn't actually affect how parameters are passed at all, and that is definitely the function called. As an aside, we're working towards a world where there's just one "ptr" type in LLVM. I think this whole situation would disappear completely there.> sorry I forgot to mention, how can I extract the keyword bitcast? I would like to be able to distinguish the function name.I think the answer to this question is the "stripPointerCasts" function I mentioned above, though I'm not 100% sure. Cheers. Tim.
Alberto Barbaro via llvm-dev
2019-Mar-16 07:20 UTC
[llvm-dev] Help with bitcast instruction
Thanks you Tim, that solved my problem! Il giorno mar 12 mar 2019 alle ore 18:50 Tim Northover < t.p.northover at gmail.com> ha scritto:> Hi Alberto, > > On Tue, 12 Mar 2019 at 18:33, Alberto Barbaro <barbaro.alberto at gmail.com> > wrote: > > call void bitcast (void (%struct.png_struct_def.68*, i8*, i8* > (%struct.png_struct_def.68*, i64)*, void (%struct.png_struct_def.68*, > i8*)*)* @png_set_mem_fn to void (%struct.png_struct_def*, i8*, i8* > (%struct.png_struct_def*, i64)*, void (%struct.png_struct_def*, > i8*)*)*)(%struct.png_struct_def* %create_struct, i8* %mem_ptr, i8* > (%struct.png_struct_def*, i64)* %malloc_fn, void (%struct.png_struct_def*, > i8*)* %free_fn) #15 > > > > I'm pretty sure that this is a CallInst but when I try to call > getCalledFunction() I receive a null pointer and that really surprise me. > > > > I would like to understand how to get the function that is called and > its parameters. Can you tell me how please? > > The problem is that getCalledFunction is pretty naive, it just takes > the getCalleeValue and dyn_cast<Function>s it. Because you've got a > cast in the IR itself your situation is a bit more complicated. > > In this case, you could write a "findCalledFunction" something like: > > Function *findCalledFunction(CallBase &CI) { > Value *Callee = CI.getCalledValue()->stripPointerCasts(); > if (auto F = dyn_cast<Function>(Callee)) > return F; > return nullptr; > } > > Where the "stripPointerCast" is the key extra ingredient that looks > through the bitcast. (Someone could certainly argue that's what > getCalledFunction should be doing anyway, but there are subtleties on > weird targets like GPUs so it's not 100%). > > It won't catch all callsites (e.g. virtual function calls could still > be plain %X values), but pretty much any algorithm has to be robust > against an unknown callee anyway. > > > Am i right saying that: > > > > (void (%struct.png_struct_def.68*, i8*, i8* (%struct.png_struct_def.68*, > i64)*, void (%struct.png_struct_def.68*, i8*)*)* -> "old parameters type" > > (%struct.png_struct_def*, i8*, i8* (%struct.png_struct_def*, i64)*, void > (%struct.png_struct_def*, i8*)*)*) -> "new parameters type" > > (%struct.png_struct_def* %create_struct, i8* %mem_ptr, i8* > (%struct.png_struct_def*, i64)* %malloc_fn, void (%struct.png_struct_def*, > i8*)* %free_fn) "the parameters passed to the png_set_mem_fn" > > I think so, from what I understand. The essence of that cast is just > changing one pointer type to another, so it doesn't actually affect > how parameters are passed at all, and that is definitely the function > called. > > As an aside, we're working towards a world where there's just one > "ptr" type in LLVM. I think this whole situation would disappear > completely there. > > > sorry I forgot to mention, how can I extract the keyword bitcast? I > would like to be able to distinguish the function name. > > I think the answer to this question is the "stripPointerCasts" > function I mentioned above, though I'm not 100% sure. > > Cheers. > > Tim. >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190316/97fb15fd/attachment.html>