Niddodi, Chaitra via llvm-dev
2020-Sep-30 00:47 UTC
[llvm-dev] Creating a global variable for a struct array
Let me clarify my question. I have a struct array h1 as follows: dhash h1[10]; I want to get a Constant* to variable h1. It looks like I can use ConstantStruct::get(StructType*, ArrayRef<Constant *>) to do this. My question is how to get the second argument of type ArrayRef<Constant *> from the above variable h1. Thanks, Chaitra ________________________________ From: Tim Northover <t.p.northover at gmail.com> Sent: Wednesday, September 23, 2020 03:04 To: Niddodi, Chaitra Cc: llvm-dev at lists.llvm.org Subject: Re: [llvm-dev] Creating a global variable for a struct array On Tue, 22 Sep 2020 at 23:52, Niddodi, Chaitra via llvm-dev <llvm-dev at lists.llvm.org> wrote:> dhash* h1 = new dhash[10];Note that this "new" expression needs a runtime call to actually allocate the memory on the heap. In LLVM terms this is A GlobalVariable with type PointerType::get(StructTy, ...), initialized to null, together with a global init function (runs when the program starts) that makes the call to new and stores it to that global. My guess is that's not what you intended> I also need to allocate space for: > 1) the field llist in struct dhash which is a pointer to another struct dlist and > 2) the field dptr in struct dlist > > Is there an example that I can refer to for doing this ?I think you should start by writing exactly what you want in C++, and then (when you're happy with the assembly output) using Clang's "-S -emit-llvm" options to see what LLVM IR that produces. That will clear up the question of how things should be allocated, which isn't quite obvious from the questions you're asking, and make translating the IR into LLVM API calls more straightforward.> I tried to create a GlobalVariable using ConstantStruct::get(StructType*, ArrayRef<Constant *>). I'm not sure how to get the second argument of type ArrayRef<Constant *> from the above variable h1.Hopefully it'll be clearer when you have the real IR you want (in textual form) in front of you. Cheers. Tim. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200930/bb9a09b1/attachment.html>
Tim Northover via llvm-dev
2020-Sep-30 09:09 UTC
[llvm-dev] Creating a global variable for a struct array
On Wed, 30 Sep 2020 at 01:47, Niddodi, Chaitra <chaitra at illinois.edu> wrote:> Let me clarify my question.Some C or C++ code showing what you want to do in LLVM would really be most helpful there.> I have a struct array h1 as follows: > dhash h1[10]; > > I want to get a Constant* to variable h1.Do you mean you want to create a GlobalVariable "h1" with a Constant* initializer? If so, we need to know what you want to initialize it to. Writing IR for dhash h1[10] = {0}; would be very different from dlist static_lst = {1, 5, NULL}; dhash h1[10] = {{"myfile.txt", &static_list}, 0 };> It looks like I can use ConstantStruct::get(StructType*, ArrayRef<Constant *>) to do this.It would be involved in the second example above, but because h1 is an array you'd need a whole ContantArray of them.> My question is how to get the second argument of type ArrayRef<Constant *> from the above variable h1.In the second example I gave above you'd write something like // First create a global variable to hold the filename string. Constant *FileNameInit = ConstantDataArray::getString("myfile.txt"); Constant *FileName = new GlobalVariable(Module, FileNameInit->getType(), true, GlobalValue::PrivateLinkage, FileNameInit, ".str"); FileName = ConstantExpr::getBitCast(FileName, Int8PtrTy); // Look up the previously created static_list variable (code to produce it omitted for brevity). GlobalVariable *StaticList = Module->getNamedValue("static_list"); // Create the ConstantStruct that will initialize the first element of the array. Constant *FirstInitArr[] = { FileName, StaticList }; ConstantStruct *FirstInit = ConstantStruct::get(DHashTy, FirstInitArr); // Create an all-zero struct for the rest of the array. Constant *OtherInits = ConstantAggregateZero::get(DHashTy); // Create the global variable. Type *H1Ty = ArrayType::get(DHashTy, 10); Constant *H1InitArr[] = {FirstInit, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits}; Constant *H1Init = ConstantArray::get(H1Ty, H1InitArr); GlobalVariable *H1 = new GlobalVariable(Module, H1Ty, false, GlobalVariable::ExternalLinkage, H1Init, "h1"); which would produce LLVM IR looking like this: @.str = private unnamed_addr constant [11 x i8] c"myfile.txt\00" @h1 = global [10 x %dhash] [%dhash { i8* bitcast([11 x i8]* @.str to i8*), %dlist* @static_list}, %dhash zeroinitializer, %dhash zeroinitializer, ...} I think the critical point that might be missing is that if you have a pointer you want to initialize to something other than NULL (in this case the filename and the dlist pointer), you're going to need a separate global variable that provides real storage for it. You can't create a ConstantStruct and use that directly because a ConstantStruct has %struct type, but your field is %struct*. Or I might have gone off at a wild tangent that has nothing to do with what you're asking. Cheers. Tim.
Niddodi, Chaitra via llvm-dev
2020-Oct-01 03:50 UTC
[llvm-dev] Creating a global variable for a struct array
Thank you very much. The code to initialize h1 to non-zero values was what I was looking for. It's almost working except for a type mismatch wrt dlist* llist field of h1. dlist static_lst[10] = { {1, 5, NULL}, ... }; dhash h1[10] = {{"myfile.txt", static_lst}, ... }; Along the lines of the code you had sent, I created a GlobalVariable* llist of type [10 x %struct.dlist]* for the field dlist* llist in h1. But this results in an LLVM ERROR: Type mismatch in constant table!. How do I fix this error ? Thanks, Chaitra ________________________________ From: Tim Northover <t.p.northover at gmail.com> Sent: Wednesday, September 30, 2020 4:09 AM To: Niddodi, Chaitra <chaitra at illinois.edu> Cc: llvm-dev at lists.llvm.org <llvm-dev at lists.llvm.org> Subject: Re: [llvm-dev] Creating a global variable for a struct array On Wed, 30 Sep 2020 at 01:47, Niddodi, Chaitra <chaitra at illinois.edu> wrote:> Let me clarify my question.Some C or C++ code showing what you want to do in LLVM would really be most helpful there.> I have a struct array h1 as follows: > dhash h1[10]; > > I want to get a Constant* to variable h1.Do you mean you want to create a GlobalVariable "h1" with a Constant* initializer? If so, we need to know what you want to initialize it to. Writing IR for dhash h1[10] = {0}; would be very different from dlist static_lst = {1, 5, NULL}; dhash h1[10] = {{"myfile.txt", &static_list}, 0 };> It looks like I can use ConstantStruct::get(StructType*, ArrayRef<Constant *>) to do this.It would be involved in the second example above, but because h1 is an array you'd need a whole ContantArray of them.> My question is how to get the second argument of type ArrayRef<Constant *> from the above variable h1.In the second example I gave above you'd write something like // First create a global variable to hold the filename string. Constant *FileNameInit = ConstantDataArray::getString("myfile.txt"); Constant *FileName = new GlobalVariable(Module, FileNameInit->getType(), true, GlobalValue::PrivateLinkage, FileNameInit, ".str"); FileName = ConstantExpr::getBitCast(FileName, Int8PtrTy); // Look up the previously created static_list variable (code to produce it omitted for brevity). GlobalVariable *StaticList = Module->getNamedValue("static_list"); // Create the ConstantStruct that will initialize the first element of the array. Constant *FirstInitArr[] = { FileName, StaticList }; ConstantStruct *FirstInit = ConstantStruct::get(DHashTy, FirstInitArr); // Create an all-zero struct for the rest of the array. Constant *OtherInits = ConstantAggregateZero::get(DHashTy); // Create the global variable. Type *H1Ty = ArrayType::get(DHashTy, 10); Constant *H1InitArr[] = {FirstInit, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits, OtherInits}; Constant *H1Init = ConstantArray::get(H1Ty, H1InitArr); GlobalVariable *H1 = new GlobalVariable(Module, H1Ty, false, GlobalVariable::ExternalLinkage, H1Init, "h1"); which would produce LLVM IR looking like this: @.str = private unnamed_addr constant [11 x i8] c"myfile.txt\00" @h1 = global [10 x %dhash] [%dhash { i8* bitcast([11 x i8]* @.str to i8*), %dlist* @static_list}, %dhash zeroinitializer, %dhash zeroinitializer, ...} I think the critical point that might be missing is that if you have a pointer you want to initialize to something other than NULL (in this case the filename and the dlist pointer), you're going to need a separate global variable that provides real storage for it. You can't create a ConstantStruct and use that directly because a ConstantStruct has %struct type, but your field is %struct*. Or I might have gone off at a wild tangent that has nothing to do with what you're asking. Cheers. Tim. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201001/9f959c9f/attachment.html>