[LLVMdev] Size of structs & arrays

1,054 views
Skip to first unread message

Fraser Cormack

unread,
Feb 22, 2012, 4:56:53 PM2/22/12
to llv...@cs.uiuc.edu

I'm trying to work out the size of a struct so that I can pass this to the
'llvm.memcpy' intrinsic. It's easy to find out how I'm supposed to do this,
as I keep seeing the following:

%Size = getelementptr %T* null, int 1
%SizeI = cast %T* %Size to uint

But I'm unsure how I actually do this in the C++ API. Is the 'null' here a
llvm::ConstantPointerNull? Any help here would be much appreciated.

Additionally, I was wondering whether I can use this method to find out the
size of variable-length arrays, such as [0 x i32], for example? I've tried
doing this and am obviously doing something wrong.

%Size = getelementptr [0 x i32]* %1, i32* null, i32 1
%SizeI = ptrtoint i32* %Size to i64

This gives entirely the wrong result, and I'm not surprised, as it doesn't
look correct. Should I instead be implementing these arrays with a size
associated with them? Something like { i32, [0 x i32]}, for instance?

Cheers,
Fraser


--
View this message in context: http://old.nabble.com/Size-of-structs---arrays-tp33341964p33341964.html
Sent from the LLVM - Dev mailing list archive at Nabble.com.

_______________________________________________
LLVM Developers mailing list
LLV...@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

Eli Friedman

unread,
Feb 22, 2012, 5:02:46 PM2/22/12
to Fraser Cormack, llv...@cs.uiuc.edu
On Wed, Feb 22, 2012 at 1:56 PM, Fraser Cormack <frase...@gmail.com> wrote:
>
> I'm trying to work out the size of a struct so that I can pass this to the
> 'llvm.memcpy' intrinsic. It's easy to find out how I'm supposed to do this,
> as I keep seeing the following:
>
> %Size = getelementptr %T* null, int 1
> %SizeI = cast %T* %Size to uint
>
> But I'm unsure how I actually do this in the C++ API. Is the 'null' here a
> llvm::ConstantPointerNull? Any help here would be much appreciated.

Try llvm::Constant::getNullValue().

> Additionally, I was wondering whether I can use this method to find out the
> size of variable-length arrays, such as [0 x i32], for example? I've tried
> doing this and am obviously doing something wrong.
>
> %Size = getelementptr [0 x i32]* %1, i32* null, i32 1
> %SizeI = ptrtoint i32* %Size to i64
>
> This gives entirely the wrong result, and I'm not surprised, as it doesn't
> look correct. Should I instead be implementing these arrays with a size
> associated with them? Something like { i32, [0 x i32]}, for instance?

Yes; [0 x i32] isn't really a variable-length array, just a
placeholder for an array of unknown size. You have to track the size
yourself.

-Eli

Fraser Cormack

unread,
Feb 22, 2012, 6:54:18 PM2/22/12
to llv...@cs.uiuc.edu

Eli Friedman-2 wrote:
>
>
> Try llvm::Constant::getNullValue().
>
>

I'm trying this:

llvm::Constant* one =
llvm::Constant::getNullValue(llvm::IntegerType::get(mod->getContext(), 64));
llvm::ConstantInt* two = llvm::ConstantInt::get(mod->getContext(),
llvm::APInt(32, llvm::StringRef("1"), 10));

std::vector<llvm::Value*> indices;
indices.push_back(one); indices.push_back(two);

llvm::Value* size = builder->CreateGEP(struct_ptr, indices);
llvm::Value* size_int = builder->CreatePtrToInt(size,
llvm::IntegerType::get(mod->getContext(), 64))

And I'm getting the assertion error "Invalid GetElementPtrInst indices for
type!"'. 'struct_ptr' is a pointer to the struct I'm trying to size. I've
also tried using getNullValue on the struct's own type.

Sorry to ask so directly, but I'd quite like to get this sorted.

--
View this message in context: http://old.nabble.com/Size-of-structs---arrays-tp33341964p33374459.html


Sent from the LLVM - Dev mailing list archive at Nabble.com.

_______________________________________________

Fraser Cormack

unread,
Feb 22, 2012, 6:54:49 PM2/22/12
to llv...@cs.uiuc.edu

Eli Friedman-2 wrote:
>
>
> Try llvm::Constant::getNullValue().
>
>

I'm trying this:

llvm::Constant* one =
llvm::Constant::getNullValue(llvm::IntegerType::get(mod->getContext(), 64));
llvm::ConstantInt* two = llvm::ConstantInt::get(mod->getContext(),
llvm::APInt(32, llvm::StringRef("1"), 10));

std::vector<llvm::Value*> indices;
indices.push_back(one); indices.push_back(two);

llvm::Value* size = builder->CreateGEP(struct_ptr, indices);
llvm::Value* size_int = builder->CreatePtrToInt(size,
llvm::IntegerType::get(mod->getContext(), 64))

And I'm getting the assertion error "Invalid GetElementPtrInst indices for
type!"'. 'struct_ptr' is a pointer to the struct I'm trying to size. I've
also tried using getNullValue on the struct's own type.

Sorry to ask so directly, but I'd quite like to get this sorted.

--
View this message in context: http://old.nabble.com/Size-of-structs---arrays-tp33341964p33374460.html


Sent from the LLVM - Dev mailing list archive at Nabble.com.

_______________________________________________

Eli Friedman

unread,
Feb 22, 2012, 7:41:46 PM2/22/12
to Fraser Cormack, llv...@cs.uiuc.edu
On Wed, Feb 22, 2012 at 3:54 PM, Fraser Cormack <frase...@gmail.com> wrote:
>
>
> Eli Friedman-2 wrote:
>>
>>
>> Try llvm::Constant::getNullValue().
>>
>>
>
> I'm trying this:
>
> llvm::Constant* one =
> llvm::Constant::getNullValue(llvm::IntegerType::get(mod->getContext(), 64));
> llvm::ConstantInt* two = llvm::ConstantInt::get(mod->getContext(),
> llvm::APInt(32, llvm::StringRef("1"), 10));
>
> std::vector<llvm::Value*> indices;
> indices.push_back(one);  indices.push_back(two);
>
> llvm::Value* size = builder->CreateGEP(struct_ptr, indices);
> llvm::Value* size_int = builder->CreatePtrToInt(size,
> llvm::IntegerType::get(mod->getContext(), 64))
>
> And I'm getting the assertion error "Invalid GetElementPtrInst indices for
> type!"'. 'struct_ptr' is a pointer to the struct I'm trying to size. I've
> also tried using getNullValue on the struct's own type.

Try something more like:

llvm::Constant* base = llvm::Constant::getNullValue(struct_ptr->getType());
llvm::Value* size = builder->CreateConstGEP1_32(base, 1);

-Eli

Duncan Sands

unread,
Feb 23, 2012, 2:47:28 AM2/23/12
to llv...@cs.uiuc.edu
Hi Fraser,

> I'm trying to work out the size of a struct so that I can pass this to the
> 'llvm.memcpy' intrinsic. It's easy to find out how I'm supposed to do this,
> as I keep seeing the following:
>
> %Size = getelementptr %T* null, int 1
> %SizeI = cast %T* %Size to uint
>
> But I'm unsure how I actually do this in the C++ API. Is the 'null' here a
> llvm::ConstantPointerNull? Any help here would be much appreciated.

you can use ConstantExpr::getSizeOf.

> Additionally, I was wondering whether I can use this method to find out the
> size of variable-length arrays, such as [0 x i32], for example? I've tried
> doing this and am obviously doing something wrong.
>
> %Size = getelementptr [0 x i32]* %1, i32* null, i32 1
> %SizeI = ptrtoint i32* %Size to i64
>
> This gives entirely the wrong result,

This will return zero, since this array has size zero. It is not a variable
length array, it is an array with length zero.

and I'm not surprised, as it doesn't
> look correct. Should I instead be implementing these arrays with a size
> associated with them? Something like { i32, [0 x i32]}, for instance?

You need to know the length somehow. This is one way.

Ciao, Duncan.

Fraser Cormack

unread,
Feb 23, 2012, 6:11:09 PM2/23/12
to llv...@cs.uiuc.edu

Eli Friedman-2 wrote:
>
>
> Try llvm::Constant::getNullValue().
>
>

Thanks, that's working nicely (so far).


Eli Friedman-2 wrote:
>
>
> Yes; [0 x i32] isn't really a variable-length array, just a
> placeholder for an array of unknown size. You have to track the size
> yourself.
>
>

This is working, too, however I'm getting a segmentation fault at runtime.

%MainClass = type { { i32, [0 x i32] } }

%this = alloca %MainClass*
%0 = alloca { i32, [5 x i32] }

... Here, I store 5 into %0[0] and a constant array into %0[1]. This runs
without error.

%7 = load %MainClass** %this
%8 = getelementptr inbounds %MainClass* %7, i32 0, i32 0
%9 = getelementptr inbounds { i32, [0 x i32] }* %8, i32 0, i32 0
%10 = getelementptr inbounds { i32, [5 x i32] }* %0, i32 0, i32 0
%11 = load i32* %10
store i32 %11, i32* %9
%12 = getelementptr inbounds { i32, [0 x i32] }* %8, i32 0, i32 1
%13 = getelementptr inbounds { i32, [5 x i32] }* %0, i32 0, i32 1
%14 = bitcast [0 x i32]* %12 to i8*
%15 = bitcast [5 x i32]* %13 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %14, i8* %15, i64 20, i32 4, i1
false)
ret void

I can't see anything wrong with this bytecode (except for being verbose),
and I don't blame you if you don't want to debug it yourself, but I thought
I'd post it anyway.

If I access a value of MainClass's array after the transfer, and print it
out, then it does so successfully, then continues to segfault. So it looks
like it's copied the memory okay, but I've corrupted something in the
process..
--
View this message in context: http://old.nabble.com/Size-of-structs---arrays-tp33341964p33381946.html


Sent from the LLVM - Dev mailing list archive at Nabble.com.

_______________________________________________

Fraser Cormack

unread,
Feb 25, 2012, 3:13:00 PM2/25/12
to llv...@cs.uiuc.edu

Fraser Cormack wrote:
>
>
> This is working, too, however I'm getting a segmentation fault at runtime.
>
>

Okay so I've delved a bit deeper, and run this program with lli
--force-interpreter and it gets this result:

LLVM ERROR: Tried to execute an unknown external function: memcpy

I've read that one has to install libffi then re-configure and reinstall
llvm, however this hasn't worked for me. Perhaps I need to link it somehow,
but anyway.

I've also run the program with lli -debug and this is the end result:

********** EMITTING LIVE DEBUG VARIABLES **********
********** Stack Slot Coloring **********
********** Function: java/lang/Object::<init>()
******** Post-regalloc Machine LICM: java/lang/Object::<init>() ********
Machine Function
********** EXPANDING POST-RA PSEUDO INSTRS **********
********** Function: java/lang/Object::<init>()
JITTing function 'java/lang/Object::<init>()'
JIT: Starting CodeGen of Function java/lang/Object::<init>()
JIT: Emitting BB0 at [0x7f09970c8140]
RET
JIT: Finished CodeGen of [0x7f09970c8140] Function:
java/lang/Object::<init>(): 1 bytes of text, 0 relocations
JIT: Binary code:
JIT: 0: 195
SectionIdx: 0, Name: , Size: 0, Offset: 0, SectionData Size: 0
SectionIdx: 1, Name: .text, Size: 1, Offset: 64, SectionData Size: 1
SectionIdx: 2, Name: .eh_frame, Size: 64, Offset: 65, SectionData Size: 64
SectionIdx: 3, Name: .data, Size: 0, Offset: 129, SectionData Size: 0
SectionIdx: 4, Name: .bss, Size: 0, Offset: 129, SectionData Size: 0
SectionIdx: 5, Name: .strtab, Size: 52, Offset: 129, SectionData Size: 52
SectionIdx: 6, Name: .symtab, Size: 168, Offset: 184, SectionData Size: 168
SectionIdx: 7, Name: .shstrtab, Size: 54, Offset: 352, SectionData Size: 54
Segmentation fault

So this information doesn't really help or mean much to me. Any help is, of
course, much appreciated :)

Cheers,
Fraser
--
View this message in context: http://old.nabble.com/Size-of-structs---arrays-tp33341964p33392056.html

Reply all
Reply to author
Forward
0 new messages