llvm instrinsic (memcpy/memset/memmov)and ConstantExpression with cast

Hi All,

I have a question on ConstantExpressions and llvm intrinsic memcpy/memset/memmove. I am using llvm-2.8 release. In one of the C programs that I am compiling using clang frontend, the call to memcpy instrinsic looks like the following

call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp2, i8* bitcast (%struct.ta* @tret to i8*), i64 4, i32 4, i1 false), !dbg !19

The second argument to memcpy is of type “struct ta” and global variable “tret” is defined as follows in the code.

struct ta {

int a;

};

struct ta tret;

Since memcpy takes i8* as its argument, the struct.ta* is bitcasted to i8* in the call to llvm.memcpy. For a pass that I am working on, I would like to know the original type of this pointer. In this example, I would like to know that the second argument is a pointer to type struct.ta, and hence the size of memory allocated to that pointer is 4 bytes.

I understand that the second argument to memcpy intrinsic namely i8* bitcast (%struct.ta* @t1 to i8*) is a ConstantExpression (CE). When I dump CE->getArgument(0), I get the following.

@t1 = global %struct.ta zeroinitializer, align 4

But from here, I am not able to find the relevant class/API to extract the type of CE->getArgument(0) and hence the size of it. When I tried CE->getArgument(0)->getType(), I am getting the type as Pointer and hence the size to be 8 bytes. I would like to get the type as StructTy and size to be 4 bytes. I searched through the llvm code

Any help is appreciated.

Thanks

Sreekumar

Hi All,

I have a question on ConstantExpressions and llvm intrinsic memcpy/memset/memmove. I am using llvm-2.8 release. In one of the C programs that I am compiling using clang frontend, the call to memcpy instrinsic looks like the following

call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp2, i8* bitcast (%struct.ta* @tret to i8*), i64 4, i32 4, i1 false), !dbg !19

The second argument to memcpy is of type “struct ta” and global variable “tret” is defined as follows in the code.

struct ta {

int a;

};

struct ta tret;

Since memcpy takes i8* as its argument, the struct.ta* is bitcasted to i8* in the call to llvm.memcpy. For a pass that I am working on, I would like to know the original type of this pointer. In this example, I would like to know that the second argument is a pointer to type struct.ta, and hence the size of memory allocated to that pointer is 4 bytes.

Thanks for the reply John.

Since memcpy takes i8* as its argument, the struct.ta* is bitcasted to i8* in the call to llvm.memcpy. For a pass that I am working
on, I would like to know the original type of this pointer. >>In this example, I would like to know that the second argument is a pointer
to type struct.ta, and hence the size of memory allocated to that pointer is 4 bytes.

You should be able to use the stripPointerCasts() method of llvm::Value * to strip off the bitcast.

This is a very useful function. Thanks for pointing this out.

When I dump CE->getArgument(0), I get the following.

>>@t1 = global %struct.ta zeroinitializer, align 4

But from here, I am not able to find the relevant class/API to extract the type of CE->getArgument(0) and hence the size of it. When I tried
CE->getArgument(0)->getType(), I am getting the type as Pointer and hence the size to be 8 bytes.

This is because all global variables in LLVM are pointers to the actual data in memory. What you need to do is:

if (GlobalVariable * GV = dyn_cast<GlobalVariable>(CE->getArgument(0)) {
Type * T = GV->getType()->getContainedType();
}

I made a mistake here. It is CE->getOperand(0) instead of CE->getArgument(0). There is also one small modification to getContainedType.
getContainedType takes an unsigned int as a parameter. I gave that to be 0 and got the correct type. Then using TargetData I was able
to get the size of the type. With this I was able to get the desired result.

Thanks again.

Sreekumar