为了让编译成x86后的代码可以转换成C++的函数指针,我们也必须处理成员对齐的事情。如果脚本里的结构成员对齐跟C++不一致的话,会造成很多麻烦。下面是成员对齐的计算方法:
一个类型有两种属性,一种是尺寸,另一种是对齐单位,可以分别用sizeof和__alignof来表示。
1:对于基本类型(char、short、double等)T有__alignof(T) == sizeof(T)
2:对于数组类型T[N]有__alignof(T[N]) == __alignof(T),sizeof(T[N]) == sizeof(T)×N
3:对于结构类型T=T1×T2×...×Tn,有__alignof(T) = max(__alignof(Ti)),sizeof(T) = align(offset(Tn)+sizeof(Tn) , __alignof(T))
4:如果一个类型结构T为空,那么sizeof(T) == __alignof(T) == 1
offset(Tn)是第n个成员相对于T起始位置的偏移,而align(S,A)可以用如下代码计算:
1 VInt Align(VInt Offset , VInt Alignment)
2 {
3 if(Alignment==0)
4 {
5 Alignment=1;
6 }
7 return (Offset+Alignment-1)/Alignment*Alignment;
8 }
于是就剩下offset(Tn)了。有了Align之后就可以递归定义offset(Tn):
offset(T1)=0
offset(Ti)=align(offset(Ti-1)+sizeof(Ti-1) , __alignof(Ti))
于是我们可以得到定理:
1:sizeof(T) == 0 (mod __alignof(T))
2:当T=T1×T2×...×Tn中T1==T2==...==Tn的时候,T的结构与T1[n]的结构完全一致
3:对于任意类型集合{T1 T2 ... Tn}有max(__alignof(Ti)) <= max(__alignof(基本类型集合))
以上结论在VC++的缺省设置中有效,如果为一个struct强行指定了pack和__alignof,将使用另外的规则。
为了证明以上式子,我写了一段程序,通过上面的方法计算成员的sizeof、__alignof以及offset,最后跟C++的编译结果互相验证:
1 #include "..\..\..\..\VL++\Library\Platform\VL_Console.h"
2 #include "..\..\..\..\VL++\Library\Script\JIT\Assembler\VL_JIT_MemberAlignment.h"
3
4 using namespace vl;
5 using namespace vl::jit::alignment;
6 using namespace vl::platform;
7
8 struct SubStructForTest
9 {
10 char Char;
11 double Double;
12 short Short;
13 int Int;
14 };
15
16 struct StructForTest
17 {
18 SubStructForTest Sub;
19 double Double[8];
20 SubStructForTest Subs[10];
21 char Char;
22 };
23
24 #define OFFSET_OF(TYPE,MEMBER) (VInt)(&((TYPE*)0)->MEMBER)
25
26 void Main_Alignment()
27 {
28 VL_AutoPtr<VL_AlignStruct> SubStruct=new VL_AlignStruct;
29 SubStruct->AddMember(new VL_AlignBasic(vabtAsciiChar));
30 SubStruct->AddMember(new VL_AlignBasic(vabtDouble));
31 SubStruct->AddMember(new VL_AlignBasic(vabtInt16));
32 SubStruct->AddMember(new VL_AlignBasic(vabtInt32));
33
34 VL_AutoPtr<VL_AlignStruct> Struct=new VL_AlignStruct;
35 Struct->AddMember(SubStruct);
36 Struct->AddMember(new VL_AlignArray(new VL_AlignBasic(vabtDouble),8));
37 Struct->AddMember(new VL_AlignArray(SubStruct,10));
38 Struct->AddMember(new VL_AlignBasic(vabtAsciiChar));
39
40 GetConsole()->Write(VUnicodeString(SubStruct->GetMember(0).GetOffset())+L"\t"+VUnicodeString(OFFSET_OF(SubStructForTest,Char))+L"\r\n");
41 GetConsole()->Write(VUnicodeString(SubStruct->GetMember(1).GetOffset())+L"\t"+VUnicodeString(OFFSET_OF(SubStructForTest,Double))+L"\r\n");
42 GetConsole()->Write(VUnicodeString(SubStruct->GetMember(2).GetOffset())+L"\t"+VUnicodeString(OFFSET_OF(SubStructForTest,Short))+L"\r\n");
43 GetConsole()->Write(VUnicodeString(SubStruct->GetMember(3).GetOffset())+L"\t"+VUnicodeString(OFFSET_OF(SubStructForTest,Int))+L"\r\n");
44 GetConsole()->Write(VUnicodeString(SubStruct->GetSize())+L"\t"+VUnicodeString((VInt)sizeof(SubStructForTest))+L"\r\n");
45 GetConsole()->Write(L"\t\n");
46
47 GetConsole()->Write(VUnicodeString(Struct->GetMember(0).GetOffset())+L"\t"+VUnicodeString(OFFSET_OF(StructForTest,Sub))+L"\r\n");
48 GetConsole()->Write(VUnicodeString(Struct->GetMember(1).GetOffset())+L"\t"+VUnicodeString(OFFSET_OF(StructForTest,Double))+L"\r\n");
49 GetConsole()->Write(VUnicodeString(Struct->GetMember(2).GetOffset())+L"\t"+VUnicodeString(OFFSET_OF(StructForTest,Subs))+L"\r\n");
50 GetConsole()->Write(VUnicodeString(Struct->GetMember(3).GetOffset())+L"\t"+VUnicodeString(OFFSET_OF(StructForTest,Char))+L"\r\n");
51 GetConsole()->Write(VUnicodeString(Struct->GetSize())+L"\t"+VUnicodeString((VInt)sizeof(StructForTest))+L"\r\n");
52 }
最后是结果:
vl::jit::alignment头文件:
1 /*******************************************************************************
2 Vczh Library++ 2.0
3 JIT::成员对齐
4 开发者:陈梓瀚
5
6 接口:
7 类:
8 函数:
9 *******************************************************************************/
10
11 #ifndef VL_JIT_MEMBERALIGNMENT
12 #define VL_JIT_MEMBERALIGNMENT
13
14 #include "..\..\..\Data\Data\VL_Data_Basic.h"
15 #include "..\..\..\Data\Data\VL_Data_List.h"
16
17 namespace vl
18 {
19 namespace jit
20 {
21 namespace alignment
22 {
23 using namespace collection;
24
25 class VL_AlignType : public VL_Base
26 {
27 public:
28 typedef VL_AutoPtr<VL_AlignType> Ptr;
29 typedef VL_AutoPtr<const VL_AlignType> ConstPtr;
30
31 virtual VInt GetSize()const=0;
32 virtual VInt GetAlignment()const=0;
33 };
34
35 class VL_AlignMember : public VL_Base
36 {
37 protected:
38 VL_AlignType::Ptr FType;
39 VInt FMinOffset;
40 public:
41 typedef VL_List<VL_AlignMember , false> List;
42
43 VL_AlignMember();
44
45 VL_AlignType::ConstPtr GetType()const;
46 void SetType(VL_AlignType::Ptr Type);
47 VInt GetOffset()const;
48 void SetMinOffset(VInt MinOffset);
49 };
50
51 class VL_AlignArray : public VL_AlignType
52 {
53 protected:
54 VL_AlignType::Ptr FType;
55 VInt FCount;
56 public:
57 VL_AlignArray(VL_AlignType::Ptr Type , VInt Count);
58
59 VInt GetSize()const;
60 VInt GetAlignment()const;
61 VL_AlignType::ConstPtr GetType()const;
62 VInt GetCount()const;
63 };
64
65 class VL_AlignStruct : public VL_AlignType
66 {
67 protected:
68 mutable VL_AlignMember::List FMembers;
69 mutable VInt FSize;
70 mutable VInt FAlignment;
71 public:
72 VL_AlignStruct();
73
74 VInt GetSize()const;
75 VInt GetAlignment()const;
76 void AddMember(VL_AlignType::Ptr Type);
77 void InsertMember(VInt Index , VL_AlignType::Ptr Type);
78 void DeleteMember(VInt Index);
79 VInt GetMemberCount()const;
80 const VL_AlignMember& GetMember(VInt Index)const;
81 void Refresh()const;
82 };
83
84 enum VLE_AlignBasicType
85 {
86 vabtInt8,
87 vabtInt16,
88 vabtInt32,
89 vabtAsciiChar,
90 vabtWideChar,
91 vabtFloat,
92 vabtDouble
93 };
94 class VL_AlignBasic : public VL_AlignType
95 {
96 protected:
97 VLE_AlignBasicType FType;
98 public:
99 VL_AlignBasic(VLE_AlignBasicType Type);
100
101 VInt GetSize()const;
102 VInt GetAlignment()const;
103 VLE_AlignBasicType GetType()const;
104 };
105 }
106 }
107 }
108
109 #endif
实现文件:
1 #include "VL_JIT_MemberAlignment.h"
2
3 namespace vl
4 {
5 namespace jit
6 {
7 namespace alignment
8 {
9 VInt Align(VInt Offset , VInt Alignment)
10 {
11 if(Alignment==0)
12 {
13 Alignment=1;
14 }
15 return (Offset+Alignment-1)/Alignment*Alignment;
16 }
17
18 /*********************************************************************************************************
19 VL_AlignMember
20 *********************************************************************************************************/
21
22 VL_AlignMember::VL_AlignMember()
23 {
24 FMinOffset=0;
25 }
26
27 VL_AlignType::ConstPtr VL_AlignMember::GetType()const
28 {
29 return FType;
30 }
31
32 void VL_AlignMember::SetType(VL_AlignType::Ptr Type)
33 {
34 FType=Type;
35 }
36
37 VInt VL_AlignMember::GetOffset()const
38 {
39 return Align(FMinOffset,FType->GetAlignment());
40 }
41
42 void VL_AlignMember::SetMinOffset(VInt MinOffset)
43 {
44 FMinOffset=MinOffset;
45 }
46
47 /*********************************************************************************************************
48 VL_AlignArray
49 *********************************************************************************************************/
50
51 VL_AlignArray::VL_AlignArray(VL_AlignType::Ptr Type , VInt Count)
52 {
53 FType=Type;
54 FCount=Count;
55 }
56
57 VInt VL_AlignArray::GetSize()const
58 {
59 return FType->GetSize()*FCount;
60 }
61
62 VInt VL_AlignArray::GetAlignment()const
63 {
64 return FType->GetAlignment();
65 }
66
67 VL_AlignType::ConstPtr VL_AlignArray::GetType()const
68 {
69 return FType;
70 }
71
72 VInt VL_AlignArray::GetCount()const
73 {
74 return FCount;
75 }
76
77 /*********************************************************************************************************
78 VL_AlignStruct
79 *********************************************************************************************************/
80
81 VL_AlignStruct::VL_AlignStruct()
82 {
83 Refresh();
84 }
85
86 VInt VL_AlignStruct::GetSize()const
87 {
88 return FSize;
89 }
90
91 VInt VL_AlignStruct::GetAlignment()const
92 {
93 return FAlignment;
94 }
95
96 void VL_AlignStruct::AddMember(VL_AlignType::Ptr Type)
97 {
98 VL_AlignMember Member;
99 Member.SetType(Type);
100 FMembers.Add(Member);
101 Refresh();
102 }
103
104 void VL_AlignStruct::InsertMember(VInt Index , VL_AlignType::Ptr Type)
105 {
106 VL_AlignMember Member;
107 Member.SetType(Type);
108 FMembers.Insert(Index,Member);
109 Refresh();
110 }
111
112 void VL_AlignStruct::DeleteMember(VInt Index)
113 {
114 FMembers.Delete(Index);
115 Refresh();
116 }
117
118 VInt VL_AlignStruct::GetMemberCount()const
119 {
120 return FMembers.GetCount();
121 }
122
123 const VL_AlignMember& VL_AlignStruct::GetMember(VInt Index)const
124 {
125 return FMembers[Index];
126 }
127
128 void VL_AlignStruct::Refresh()const
129 {
130 FSize=0;
131 FAlignment=0;
132 for(VInt i=0;i<FMembers.GetCount();i++)
133 {
134 if(FAlignment<FMembers[i].GetType()->GetAlignment())
135 {
136 FAlignment=FMembers[i].GetType()->GetAlignment();
137 }
138 FMembers[i].SetMinOffset(FSize);
139 FSize=FMembers[i].GetOffset()+FMembers[i].GetType()->GetSize();
140 }
141 FSize=Align(FSize,FAlignment);
142 if(FSize==0)
143 {
144 FAlignment=1;
145 FSize=1;
146 }
147 }
148
149 /*********************************************************************************************************
150 VL_AlignBasic
151 *********************************************************************************************************/
152
153 VL_AlignBasic::VL_AlignBasic(VLE_AlignBasicType Type)
154 {
155 FType=Type;
156 }
157
158 VInt VL_AlignBasic::GetSize()const
159 {
160 switch(FType)
161 {
162 case vabtInt8: return sizeof(VInt8s);
163 case vabtInt16: return sizeof(VInt16s);
164 case vabtInt32: return sizeof(VInt32s);
165 case vabtAsciiChar: return sizeof(VChar);
166 case vabtWideChar: return sizeof(VWChar);
167 case vabtFloat: return sizeof(VFloat);
168 case vabtDouble: return sizeof(VDouble);
169 default: return 0;
170 }
171 }
172
173 VInt VL_AlignBasic::GetAlignment()const
174 {
175 return GetSize();
176 }
177
178 VLE_AlignBasicType VL_AlignBasic::GetType()const
179 {
180 return FType;
181 }
182 }
183 }
184 }
posted on 2009-03-09 20:46
陈梓瀚(vczh) 阅读(3736)
评论(2) 编辑 收藏 引用 所属分类:
JIT