随笔-341  评论-2670  文章-0  trackbacks-0
    为了让编译成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

评论:
# re: JIT脚本引擎:成员对齐详解 2009-03-09 21:00 | jiong
囧o(╯□╰)o  回复  更多评论
  
# re: JIT脚本引擎:成员对齐详解 2009-03-10 03:36 | 123
强啊!  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理