[LLVMdev] Proposed: first class packed structures

Andrew Lenharth andrewl at lenharth.org
Wed Dec 6 10:44:20 PST 2006


Currently, Structure layout is left to targets, which implement them
according to the ABI of that platform.  While this is fine for most
structures, it makes packed structures very ugly.  All fields in a
packed type must be converted to byte arrays with casts to access
fields, which bloats accesses and obsfucates the types.  First class
support for packed types would clean up the generated code from these
(lowering bytecode sizes) as well as having minimal impact on
optimizations.

Consider:

extern struct { char a;   int x;  int y;  int z; } __attribute((packed)) foos;;
int foo() {  return foos.x + foos.y + foos.z; }
struct { int x; char a;} __attribute((packed)) bara[2];
int bar() { return bara[0].x + bara[1].x;}

which compiles to:
%struct.anon = type { sbyte, [4 x ubyte], [4 x ubyte], [4 x ubyte] }
%foos = external global %struct.anon
%bara = weak global [2 x { [4 x ubyte], sbyte }] zeroinitializer
implementation   ; Functions:
int %foo() {
entry:
	%tmp = load int* bitcast ([4 x ubyte]* getelementptr (%struct.anon*
%foos, int 0, uint 1) to int*)
	%tmp3 = load int* bitcast ([4 x ubyte]* getelementptr (%struct.anon*
%foos, int 0, uint 2) to int*)
	%tmp6 = load int* bitcast ([4 x ubyte]* getelementptr (%struct.anon*
%foos, int 0, uint 3) to int*)
	%tmp4 = add int %tmp3, %tmp
	%tmp7 = add int %tmp4, %tmp6
	ret int %tmp7
}

int %bar() {
entry:
	%tmp = load int* bitcast ([2 x { [4 x ubyte], sbyte }]* %bara to int*)
	%tmp4 = load int* bitcast ([4 x ubyte]* getelementptr ([2 x { [4 x
ubyte], sbyte }]* %bara, int 0, int 1, uint 0) to int*)
	%tmp5 = add int %tmp4, %tmp
	ret int %tmp5
}

Packed structure types would let us say:
%struct.anon = type <{ sbyte, int, int, int }>
%foos = external global %struct.anon
%bara = weak global [2 x <{ int, sbyte }>] zeroinitializer
implementation   ; Functions:
int %foo() {
entry:
	%tmp = load int*  getelementptr (%struct.anon* %foos, int 0, uint 1)
	%tmp3 = load int* getelementptr (%struct.anon* %foos, int 0, uint 2)
	%tmp6 = load int* getelementptr (%struct.anon* %foos, int 0, uint 3)
	%tmp4 = add int %tmp3, %tmp
	%tmp7 = add int %tmp4, %tmp6
	ret int %tmp7
}

int %bar() {
entry:
	%tmp = load int* getelementptr([2 x <{ int, sbyte }>]* %bara, int 0,
int 0, uint 0 )
	%tmp4 = load int* getelementptr ([2 x <{ int, sbyte }>]* %bara, int
0, int 1, uint 0)
	%tmp5 = add int %tmp4, %tmp
	ret int %tmp5
}

The attached patch implements this (with the above syntax).  Let me
know what you all think.
The bytecodes reduce for the above example from 342B -> 325B.  This
also would fix bug 931.

Andrew
-------------- next part --------------
A non-text attachment was scrubbed...
Name: packed.patch.raw
Type: application/octet-stream
Size: 19418 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20061206/5fb8ac2d/attachment.obj>


More information about the llvm-dev mailing list