comparison ir/irtypestruct.cpp @ 1228:79758fd2f48a

Added Doxygen file. Completely seperated type and symbol generation. Should fix a lot of bugs, but is not yet 100% complete.
author Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
date Wed, 15 Apr 2009 20:06:25 +0200
parents
children 212ec2d9d176
comparison
equal deleted inserted replaced
1215:08f87d8cd101 1228:79758fd2f48a
1 #include "llvm/DerivedTypes.h"
2
3 #include "aggregate.h"
4 #include "declaration.h"
5 #include "mtype.h"
6
7 #include "gen/irstate.h"
8 #include "gen/tollvm.h"
9 #include "gen/logger.h"
10 #include "gen/utils.h"
11 #include "ir/irtypestruct.h"
12
13 //////////////////////////////////////////////////////////////////////////////
14 //////////////////////////////////////////////////////////////////////////////
15 //////////////////////////////////////////////////////////////////////////////
16
17 IrTypeAggr::IrTypeAggr(AggregateDeclaration * ad)
18 : IrType(ad->type, llvm::OpaqueType::get()),
19 aggr(ad)
20 {
21 }
22
23 //////////////////////////////////////////////////////////////////////////////
24 //////////////////////////////////////////////////////////////////////////////
25 //////////////////////////////////////////////////////////////////////////////
26
27 IrTypeStruct::IrTypeStruct(StructDeclaration * sd)
28 : IrTypeAggr(sd),
29 sd(sd),
30 ts((TypeStruct*)sd->type)
31 {
32 }
33
34 //////////////////////////////////////////////////////////////////////////////
35
36 size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff)
37 {
38 size_t n = defaultTypes.size();
39 while (diff)
40 {
41 if (global.params.is64bit && diff % 8 == 0)
42 {
43 defaultTypes.push_back(llvm::Type::Int64Ty);
44 diff -= 8;
45 }
46 else if (diff % 4 == 0)
47 {
48 defaultTypes.push_back(llvm::Type::Int32Ty);
49 diff -= 4;
50 }
51 else if (diff % 2 == 0)
52 {
53 defaultTypes.push_back(llvm::Type::Int16Ty);
54 diff -= 2;
55 }
56 else
57 {
58 defaultTypes.push_back(llvm::Type::Int8Ty);
59 diff -= 1;
60 }
61 }
62 return defaultTypes.size() - n;
63 }
64
65 const llvm::Type* IrTypeStruct::buildType()
66 {
67 IF_LOG Logger::println("Building struct type %s @ %s", sd->toPrettyChars(), sd->locToChars());
68 LOG_SCOPE;
69
70 // find the fields that contribute to the default initializer.
71 // these will define the default type.
72
73 std::vector<const llvm::Type*> defaultTypes;
74 defaultTypes.reserve(16);
75
76 size_t offset = 0;
77 size_t field_index = 0;
78
79 bool packed = (sd->type->alignsize() == 1);
80
81 ArrayIter<VarDeclaration> it(sd->fields);
82 for (; !it.done(); it.next())
83 {
84 VarDeclaration* vd = it.get();
85
86 assert(vd->ir.irField == NULL && "struct inheritance is not allowed, how can this happen?");
87
88 // skip if offset moved backwards
89 if (vd->offset < offset)
90 {
91 IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset);
92 new IrField(vd, 0, vd->offset);
93 continue;
94 }
95
96 IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
97
98 // get next aligned offset for this type
99 size_t alignedoffset = offset;
100 if (!packed)
101 {
102 size_t alignsize = vd->type->alignsize();
103 alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
104 }
105
106 // insert explicit padding?
107 if (alignedoffset < vd->offset)
108 {
109 field_index += add_zeros(defaultTypes, vd->offset - alignedoffset);
110 }
111
112 // add default type
113 defaultTypes.push_back(DtoType(vd->type));
114
115 // advance offset to right past this field
116 offset = vd->offset + vd->type->size();
117
118 // give field index
119 // the IrField creation doesn't really belong here, but it's a trivial operation
120 // and it save yet another of these loops.
121 IF_LOG Logger::println("Field index: %zu", field_index);
122 new IrField(vd, field_index);
123 field_index++;
124 }
125
126 // tail padding?
127 if (offset < sd->structsize)
128 {
129 add_zeros(defaultTypes, sd->structsize - offset);
130 }
131
132 // build the llvm type
133 const llvm::Type* st = llvm::StructType::get(defaultTypes, packed);
134
135 // refine type
136 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(st);
137
138 // name types
139 Type::sir->getState()->module->addTypeName(sd->toPrettyChars(), pa.get());
140
141 #if 0
142 IF_LOG Logger::cout() << "struct type: " << *pa.get() << std::endl;
143 #endif
144
145 return pa.get();
146 }
147
148 //////////////////////////////////////////////////////////////////////////////