11#include " TypeTranslator.h"
22#include " Utils.h"
33#include " ir/types/FunctionPointerType.h"
4- #include " ir/types/PointerType .h"
4+ #include " clang/AST/RecordLayout .h"
55
66TypeTranslator::TypeTranslator (clang::ASTContext *ctx_, IR &ir)
77 : ctx(ctx_), ir(ir), typeMap() {
@@ -34,19 +34,17 @@ TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir)
3434}
3535
3636std::shared_ptr<Type>
37- TypeTranslator::translateFunctionPointer (const clang::QualType &qtpe,
38- const std::string *avoid) {
37+ TypeTranslator::translateFunctionPointer (const clang::QualType &qtpe) {
3938 const auto *ptr = qtpe.getTypePtr ()->getAs <clang::PointerType>();
4039 const clang::QualType &inner = ptr->getPointeeType ();
4140
4241 if (inner->isFunctionProtoType ()) {
4342 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;
4745
4846 for (const clang::QualType ¶m : fc->param_types ()) {
49- parametersTypes.push_back (translate (param, avoid ));
47+ parametersTypes.push_back (translate (param));
5048 }
5149
5250 return std::make_shared<FunctionPointerType>(
@@ -61,8 +59,7 @@ TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe,
6159}
6260
6361std::shared_ptr<Type>
64- TypeTranslator::translatePointer (const clang::QualType &pte,
65- const std::string *avoid) {
62+ TypeTranslator::translatePointer (const clang::QualType &pte) {
6663
6764 if (pte->isBuiltinType ()) {
6865 const clang::BuiltinType *as = pte->getAs <clang::BuiltinType>();
@@ -81,7 +78,7 @@ TypeTranslator::translatePointer(const clang::QualType &pte,
8178 }
8279 }
8380
84- return std::make_shared<PointerType>(translate (pte, avoid ));
81+ return std::make_shared<PointerType>(translate (pte));
8582}
8683
8784std::shared_ptr<Type>
@@ -109,21 +106,26 @@ TypeTranslator::translateStructOrUnionOrEnum(const clang::QualType &qtpe) {
109106std::shared_ptr<Type>
110107TypeTranslator::translateStructOrUnion (const clang::QualType &qtpe) {
111108 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 ;
117121 }
118-
119122 return translateStructOrUnionOrEnum (qtpe);
120123}
121124
122125std::shared_ptr<Type>
123- TypeTranslator::translateConstantArray (const clang::ConstantArrayType *ar,
124- const std::string *avoid) {
126+ TypeTranslator::translateConstantArray (const clang::ConstantArrayType *ar) {
125127 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 ());
127129 if (elementType == nullptr ) {
128130 llvm::errs () << " Failed to translate array type "
129131 << ar->getElementType ().getAsString () << " \n " ;
@@ -133,45 +135,31 @@ TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar,
133135 return std::make_shared<ArrayType>(elementType, size);
134136}
135137
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) {
138139
139140 const clang::Type *tpe = qtpe.getTypePtr ();
140141
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-
150142 if (tpe->isFunctionType ()) {
151143 return nullptr ;
152144 }
153145
154146 if (tpe->isFunctionPointerType ()) {
155- return translateFunctionPointer (qtpe, avoid );
147+ return translateFunctionPointer (qtpe);
156148
157149 } else if (tpe->isPointerType ()) {
158150 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 ());
163152
164- } else if (qtpe->isUnionType ()) {
153+ } else if (qtpe->isStructureType () || qtpe-> isUnionType ()) {
165154 return translateStructOrUnion (qtpe);
166155
167156 } else if (qtpe->isEnumeralType ()) {
168- return translateStructOrUnionOrEnum (qtpe);
157+ return translateEnum (qtpe);
169158
170159 } else if (qtpe->isConstantArrayType ()) {
171- return translateConstantArray (ctx->getAsConstantArrayType (qtpe), avoid );
160+ return translateConstantArray (ctx->getAsConstantArrayType (qtpe));
172161 } else if (qtpe->isArrayType ()) {
173- return translatePointer (ctx->getAsArrayType (qtpe)->getElementType (),
174- avoid);
162+ return translatePointer (ctx->getAsArrayType (qtpe)->getElementType ());
175163 } else {
176164
177165 auto found = typeMap.find (qtpe.getUnqualifiedType ().getAsString ());
@@ -191,3 +179,77 @@ std::string TypeTranslator::getTypeFromTypeMap(std::string cType) {
191179 }
192180 return " " ;
193181}
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