[llvm-dev] Creating a global variable for a struct array

Tim Northover via llvm-dev llvm-dev at lists.llvm.org
Wed Sep 30 02:09:08 PDT 2020


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.


More information about the llvm-dev mailing list