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.
_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
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.
The type you pass to GlobalVariable's constructor for that variable
should be "[10 x %struct.dlist]" because that's what you want storage
for. Then the GlobalVariable itself will be a Constant of type "[10 x
%struct.dlist]*".
Since that error is coming from the bitcode reader, I suspect you
might have built a version of LLVM without assertions enabled (fixed
with -DLLVM_ENABLE_ASSERTIONS=ON in CMake, or a debug build) so the
crash you'd normally get when actually constructing the constants is
deferred. Hopefully if you turn assertions on it'll point to the exact
line the error is happening on and be much easier to fix.
filenmConst's LLVM type is "[12 x i8]*" (or similar if I've
miscounted), but I assume the slot in the struct is i8*. So you need
either a bitcast or a getelementptr constant expression to convert it.