1
1
#include " TypeTranslator.h"
2
2
#include " Utils.h"
3
3
#include " ir/types/FunctionPointerType.h"
4
- #include " ir/types/PointerType .h"
4
+ #include " clang/AST/RecordLayout .h"
5
5
6
6
TypeTranslator::TypeTranslator (clang::ASTContext *ctx_, IR &ir)
7
7
: ctx(ctx_), ir(ir), typeMap() {
@@ -34,19 +34,17 @@ TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir)
34
34
}
35
35
36
36
std::shared_ptr<Type>
37
- TypeTranslator::translateFunctionPointer (const clang::QualType &qtpe,
38
- const std::string *avoid) {
37
+ TypeTranslator::translateFunctionPointer (const clang::QualType &qtpe) {
39
38
const auto *ptr = qtpe.getTypePtr ()->getAs <clang::PointerType>();
40
39
const clang::QualType &inner = ptr->getPointeeType ();
41
40
42
41
if (inner->isFunctionProtoType ()) {
43
42
const auto *fc = inner->getAs <clang::FunctionProtoType>();
44
- std::shared_ptr<Type> returnType =
45
- translate (fc->getReturnType (), avoid);
46
- std::vector<std::shared_ptr<Type>> parametersTypes;
43
+ std::shared_ptr<Type> returnType = translate (fc->getReturnType ());
44
+ std::vector<std::shared_ptr<const Type>> parametersTypes;
47
45
48
46
for (const clang::QualType ¶m : fc->param_types ()) {
49
- parametersTypes.push_back (translate (param, avoid ));
47
+ parametersTypes.push_back (translate (param));
50
48
}
51
49
52
50
return std::make_shared<FunctionPointerType>(
@@ -61,8 +59,7 @@ TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe,
61
59
}
62
60
63
61
std::shared_ptr<Type>
64
- TypeTranslator::translatePointer (const clang::QualType &pte,
65
- const std::string *avoid) {
62
+ TypeTranslator::translatePointer (const clang::QualType &pte) {
66
63
67
64
if (pte->isBuiltinType ()) {
68
65
const clang::BuiltinType *as = pte->getAs <clang::BuiltinType>();
@@ -81,7 +78,7 @@ TypeTranslator::translatePointer(const clang::QualType &pte,
81
78
}
82
79
}
83
80
84
- return std::make_shared<PointerType>(translate (pte, avoid ));
81
+ return std::make_shared<PointerType>(translate (pte));
85
82
}
86
83
87
84
std::shared_ptr<Type>
@@ -109,21 +106,26 @@ TypeTranslator::translateStructOrUnionOrEnum(const clang::QualType &qtpe) {
109
106
std::shared_ptr<Type>
110
107
TypeTranslator::translateStructOrUnion (const clang::QualType &qtpe) {
111
108
if (qtpe->hasUnnamedOrLocalType ()) {
112
- // TODO: Verify that the local part is not a problem
113
- uint64_t sizeInBits = ctx->getTypeSize (qtpe);
114
- assert (sizeInBits % 8 == 0 );
115
- return std::make_shared<ArrayType>(
116
- std::make_shared<PrimitiveType>(" Byte" ), sizeInBits / 8 );
109
+ if (qtpe->isStructureType ()) {
110
+ std::string name =
111
+ " anonymous_" + std::to_string (anonymousStructId++);
112
+ clang::RecordDecl *record = qtpe->getAsStructureType ()->getDecl ();
113
+ return addStructDefinition (record, name);
114
+ } else if (qtpe->isUnionType ()) {
115
+ std::string name =
116
+ " anonymous_" + std::to_string (anonymousUnionId++);
117
+ clang::RecordDecl *record = qtpe->getAsUnionType ()->getDecl ();
118
+ return addUnionDefinition (record, name);
119
+ }
120
+ return nullptr ;
117
121
}
118
-
119
122
return translateStructOrUnionOrEnum (qtpe);
120
123
}
121
124
122
125
std::shared_ptr<Type>
123
- TypeTranslator::translateConstantArray (const clang::ConstantArrayType *ar,
124
- const std::string *avoid) {
126
+ TypeTranslator::translateConstantArray (const clang::ConstantArrayType *ar) {
125
127
const uint64_t size = ar->getSize ().getZExtValue ();
126
- std::shared_ptr<Type> elementType = translate (ar->getElementType (), avoid );
128
+ std::shared_ptr<Type> elementType = translate (ar->getElementType ());
127
129
if (elementType == nullptr ) {
128
130
llvm::errs () << " Failed to translate array type "
129
131
<< ar->getElementType ().getAsString () << " \n " ;
@@ -133,45 +135,31 @@ TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar,
133
135
return std::make_shared<ArrayType>(elementType, size);
134
136
}
135
137
136
- std::shared_ptr<Type> TypeTranslator::translate (const clang::QualType &qtpe,
137
- const std::string *avoid) {
138
+ std::shared_ptr<Type> TypeTranslator::translate (const clang::QualType &qtpe) {
138
139
139
140
const clang::Type *tpe = qtpe.getTypePtr ();
140
141
141
- if (typeEquals (tpe, avoid)) {
142
- // This is a type that we want to avoid the usage.
143
- // Êxample: A struct that has a pointer to itself
144
- uint64_t sizeInBits = ctx->getTypeSize (tpe);
145
- assert (sizeInBits % 8 == 0 );
146
- return std::make_shared<ArrayType>(
147
- std::make_shared<PrimitiveType>(" Byte" ), sizeInBits / 8 );
148
- }
149
-
150
142
if (tpe->isFunctionType ()) {
151
143
return nullptr ;
152
144
}
153
145
154
146
if (tpe->isFunctionPointerType ()) {
155
- return translateFunctionPointer (qtpe, avoid );
147
+ return translateFunctionPointer (qtpe);
156
148
157
149
} else if (tpe->isPointerType ()) {
158
150
return translatePointer (
159
- tpe->getAs <clang::PointerType>()->getPointeeType (), avoid);
160
-
161
- } else if (qtpe->isStructureType ()) {
162
- return translateStructOrUnion (qtpe);
151
+ tpe->getAs <clang::PointerType>()->getPointeeType ());
163
152
164
- } else if (qtpe->isUnionType ()) {
153
+ } else if (qtpe->isStructureType () || qtpe-> isUnionType ()) {
165
154
return translateStructOrUnion (qtpe);
166
155
167
156
} else if (qtpe->isEnumeralType ()) {
168
- return translateStructOrUnionOrEnum (qtpe);
157
+ return translateEnum (qtpe);
169
158
170
159
} else if (qtpe->isConstantArrayType ()) {
171
- return translateConstantArray (ctx->getAsConstantArrayType (qtpe), avoid );
160
+ return translateConstantArray (ctx->getAsConstantArrayType (qtpe));
172
161
} else if (qtpe->isArrayType ()) {
173
- return translatePointer (ctx->getAsArrayType (qtpe)->getElementType (),
174
- avoid);
162
+ return translatePointer (ctx->getAsArrayType (qtpe)->getElementType ());
175
163
} else {
176
164
177
165
auto found = typeMap.find (qtpe.getUnqualifiedType ().getAsString ());
@@ -191,3 +179,77 @@ std::string TypeTranslator::getTypeFromTypeMap(std::string cType) {
191
179
}
192
180
return " " ;
193
181
}
182
+
183
+ std::shared_ptr<Location> TypeTranslator::getLocation (clang::Decl *decl) {
184
+ clang::SourceManager &sm = ctx->getSourceManager ();
185
+ std::string filename = std::string (sm.getFilename (decl->getLocation ()));
186
+ std::string path = getRealPath (filename.c_str ());
187
+
188
+ unsigned lineNumber = sm.getSpellingLineNumber (decl->getLocation ());
189
+ return std::make_shared<Location>(path, lineNumber);
190
+ }
191
+
192
+ std::shared_ptr<TypeDef>
193
+ TypeTranslator::addUnionDefinition (clang::RecordDecl *record,
194
+ std::string name) {
195
+ std::vector<std::shared_ptr<Field>> fields;
196
+
197
+ for (const clang::FieldDecl *field : record->fields ()) {
198
+ std::string fname = field->getNameAsString ();
199
+ std::shared_ptr<Type> ftype = translate (field->getType ());
200
+
201
+ fields.push_back (std::make_shared<Field>(fname, ftype));
202
+ }
203
+
204
+ uint64_t sizeInBits = ctx->getTypeSize (record->getTypeForDecl ());
205
+ assert (sizeInBits % 8 == 0 );
206
+
207
+ return ir.addUnion (name, std::move (fields), sizeInBits / 8 ,
208
+ getLocation (record));
209
+ }
210
+
211
+ std::shared_ptr<TypeDef>
212
+ TypeTranslator::addStructDefinition (clang::RecordDecl *record,
213
+ std::string name) {
214
+ std::string newName = " struct_" + name;
215
+
216
+ if (record->hasAttr <clang::PackedAttr>()) {
217
+ llvm::errs () << " Warning: struct " << name << " is packed. "
218
+ << " Packed structs are not supported by Scala Native. "
219
+ << " Access to fields will not work correctly.\n " ;
220
+ llvm::errs ().flush ();
221
+ }
222
+
223
+ std::vector<std::shared_ptr<Field>> fields;
224
+ const clang::ASTRecordLayout &recordLayout =
225
+ ctx->getASTRecordLayout (record);
226
+
227
+ bool isBitFieldStruct = false ;
228
+ for (const clang::FieldDecl *field : record->fields ()) {
229
+ if (field->isBitField ()) {
230
+ isBitFieldStruct = true ;
231
+ }
232
+ std::shared_ptr<Type> ftype = translate (field->getType ());
233
+ uint64_t recordOffsetInBits =
234
+ recordLayout.getFieldOffset (field->getFieldIndex ());
235
+ fields.push_back (std::make_shared<Field>(field->getNameAsString (),
236
+ ftype, recordOffsetInBits));
237
+ }
238
+
239
+ uint64_t sizeInBits = ctx->getTypeSize (record->getTypeForDecl ());
240
+ assert (sizeInBits % 8 == 0 );
241
+
242
+ return ir.addStruct (name, std::move (fields), sizeInBits / 8 ,
243
+ getLocation (record),
244
+ record->hasAttr <clang::PackedAttr>(), isBitFieldStruct);
245
+ }
246
+
247
+ std::shared_ptr<Type>
248
+ TypeTranslator::translateEnum (const clang::QualType &type) {
249
+ if (type->hasUnnamedOrLocalType ()) {
250
+ clang::EnumDecl *enumDecl = type->getAs <clang::EnumType>()->getDecl ();
251
+ return std::make_shared<PrimitiveType>(getTypeFromTypeMap (
252
+ enumDecl->getIntegerType ().getUnqualifiedType ().getAsString ()));
253
+ }
254
+ return translateStructOrUnionOrEnum (type);
255
+ }
0 commit comments