[LLVMdev] Structure memory layout

Jin Gu Kang jaykang10 at imrc.kist.re.kr
Tue Oct 19 04:59:17 PDT 2010


Hi Renato,

Firstly, I have been removing target specific information from struct type on bitcode.
Target specific information are type size, type alignment, merged bitfields and so on.

For example

  1 struct test {
  2   char a:3;
  3   char b:4;
  4   char c:3;
  5   char d:2;
  6 };
  7
  8 struct test vm = {1, 2, 3, 1};
  9
 10 int main(void)
 11 {
 12   int a;
 13   vm.d = 1;
 14 }
 
Above source code is compiled using cross arm-llvm-gcc as following.

  1 ; ModuleID = './temp2.c'
  2 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
  3 target triple = "armv5-none-linux-gnueabi"
  4
  5 %0 = type { i8, i8 }
  6 %struct.test = type <{ i8, i8 }>
  7
  8 @vm = global %0 { i8 17, i8 11 }                  ; <%0*> [#uses=1]
  9
 10 define arm_aapcscc i32 @main() nounwind {
 11 entry:
 12   %retval = alloca i32                            ; <i32*> [#uses=1]
 13   %a = alloca i32                                 ; <i32*> [#uses=0]
 14   %"alloca point" = bitcast i32 0 to i32          ; <i32> [#uses=0]
 15   %0 = load i8* getelementptr inbounds (%struct.test* bitcast (%0* @vm to %struct.test*), i32 0, i32 1), align 1 ; <i8> [#uses=1]
 16   %1 = and i8 %0, -25                             ; <i8> [#uses=1]
 17   %2 = or i8 %1, 8                                ; <i8> [#uses=1]
 18   store i8 %2, i8* getelementptr inbounds (%struct.test* bitcast (%0* @vm to %struct.test*), i32 0, i32 1), align 1
 19   br label %return
 20
 21 return:                                           ; preds = %entry
 22   %retval1 = load i32* %retval                    ; <i32> [#uses=1]
 23   ret i32 %retval1
 24 }

In line5-6, bitfields for struct type is merged.
Merging bitfields is affected by type alignment and type size.
(type alignment  and type size are target dependent information.)
I have been convert above bitcode to more target independent bitcode as following.

  1 ; ModuleID = './temp2.c'
  2 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
  3 target triple = "armv5-none-linux-gnueabi"
  4
  5 %0 = type { i3, i4, i3, i2 }
  6 %struct.test = type <{ i3, i4, i3, i2 }>
  7
  8 @vm = global %0 { i3 1, i4 2, i3 3, i2 1 }        ; <%0*> [#uses=1]
  9
 10 define arm_aapcscc i32 @main() nounwind {
 11 entry:
 12   %retval = alloca i32                            ; <i32*> [#uses=1]
 13   %a = alloca i32                                 ; <i32*> [#uses=0]
 14   %"alloca point" = bitcast i32 0 to i32          ; <i32> [#uses=0]
 15   call void @llvm.setelement.i2(i8* bitcast (i4* getelementptr (%struct.test* bitcast (%0* @vm to %struct.test*), i32 1, i32 1) to i8*), i2 1)
 16   br label %return
 17
 18 return:                                           ; preds = %entry
 19   %retval1 = load i32* %retval                    ; <i32> [#uses=1]
 20   ret i32 %retval1
 21 }
 22
 23 declare void @llvm.setelement.i2(i8*, i2) nounwind

I have been trying to maintain shape of struct type within original source code on bitcode.
This type become concrete according to each target on llc pass
and above "setelement" intrinsic function is also concrete on llc pass.
(Until now, I have been considering compilation pass from llvm-gcc to llc.
Currently, I am working on llc pass.)

As you can see above, I have been trying to make more target independent struct type, not completely.

Secondly, I also finded union type's target dependent problems through long double type on core-utils package.

File isnan.c
 28 # define DOUBLE long double
...
 66 #define NWORDS \
 67   ((sizeof (DOUBLE) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
 68 typedef union { DOUBLE value; unsigned int word[NWORDS]; } memory_double;

Because floating point data type isn't allowed to have bitwise operation,
above isnan function converts long double type to unsigned int array whether or not to know "not a number".

I think that both above statements and refered union types problems on your answer are source codes which don't consider portability for multi-platform.
I have been focusing on target independent bitcode about source codes which consider portability for multi-platform, not above statements.
(Target dependent memory layout  for struct type is generated on source codes which consider portability for multi-platform,)

My subject in my team makes more target independent bitcode, not completely.
In addition to memory layout for struct type, I have been considering several target dependent inforamtion on current bitcode.
If I have a chance, I would like to discuss the information with llvm developers. :)

I really appreciate your answer.

Thanks,
Jin-Gu Kang



More information about the llvm-dev mailing list