Skip to content

Commit 436fafb

Browse files
committed
Generate types for anonymous declarations
1 parent 78584f0 commit 436fafb

File tree

14 files changed

+241
-126
lines changed

14 files changed

+241
-126
lines changed

bindgen/Main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ int main(int argc, const char *argv[]) {
5959
objectName = "nativeLib";
6060
}
6161

62-
char *resolved = realpath(op.getSourcePathList()[0].c_str(), nullptr);
62+
std::string resolved = getRealPath(op.getSourcePathList()[0].c_str());
6363
LocationManager locationManager(resolved);
6464

6565
IR ir(libName, linkName, objectName, Package.getValue(), locationManager);

bindgen/TypeTranslator.cpp

+89-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
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

66
TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir)
77
: ctx(ctx_), ir(ir), typeMap() {
@@ -106,13 +106,19 @@ TypeTranslator::translateStructOrUnionOrEnum(const clang::QualType &qtpe) {
106106
std::shared_ptr<Type>
107107
TypeTranslator::translateStructOrUnion(const clang::QualType &qtpe) {
108108
if (qtpe->hasUnnamedOrLocalType()) {
109-
// TODO: Verify that the local part is not a problem
110-
uint64_t sizeInBits = ctx->getTypeSize(qtpe);
111-
assert(sizeInBits % 8 == 0);
112-
return std::make_shared<ArrayType>(
113-
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;
114121
}
115-
116122
return translateStructOrUnionOrEnum(qtpe);
117123
}
118124

@@ -144,14 +150,11 @@ std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe) {
144150
return translatePointer(
145151
tpe->getAs<clang::PointerType>()->getPointeeType());
146152

147-
} else if (qtpe->isStructureType()) {
148-
return translateStructOrUnion(qtpe);
149-
150-
} else if (qtpe->isUnionType()) {
153+
} else if (qtpe->isStructureType() || qtpe->isUnionType()) {
151154
return translateStructOrUnion(qtpe);
152155

153156
} else if (qtpe->isEnumeralType()) {
154-
return translateStructOrUnionOrEnum(qtpe);
157+
return translateEnum(qtpe);
155158

156159
} else if (qtpe->isConstantArrayType()) {
157160
return translateConstantArray(ctx->getAsConstantArrayType(qtpe));
@@ -176,3 +179,77 @@ std::string TypeTranslator::getTypeFromTypeMap(std::string cType) {
176179
}
177180
return "";
178181
}
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+
}

bindgen/TypeTranslator.h

+12
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,19 @@ class TypeTranslator {
1616

1717
std::string getTypeFromTypeMap(std::string cType);
1818

19+
std::shared_ptr<TypeDef> addUnionDefinition(clang::RecordDecl *record,
20+
std::string name);
21+
22+
std::shared_ptr<TypeDef> addStructDefinition(clang::RecordDecl *record,
23+
std::string name);
24+
25+
std::shared_ptr<Location> getLocation(clang::Decl *decl);
26+
1927
private:
2028
clang::ASTContext *ctx;
2129
IR &ir;
30+
int anonymousStructId = 0;
31+
int anonymousUnionId = 0;
2232

2333
/**
2434
* Primitive types
@@ -36,4 +46,6 @@ class TypeTranslator {
3646

3747
std::shared_ptr<Type>
3848
translateConstantArray(const clang::ConstantArrayType *ar);
49+
50+
std::shared_ptr<Type> translateEnum(const clang::QualType &type);
3951
};

bindgen/Utils.h

+13-14
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,6 @@ inline std::string uint64ToScalaNat(uint64_t v, std::string accumulator = "") {
2222
}
2323
}
2424

25-
inline bool typeEquals(const clang::Type *tpe1, const std::string *tpe2) {
26-
if (tpe1 == nullptr && tpe2 == nullptr) {
27-
return true;
28-
}
29-
if (tpe1 == nullptr || tpe2 == nullptr) {
30-
return false;
31-
}
32-
// TODO: What is the proper way ?
33-
if (tpe1->getAsTagDecl()) {
34-
return tpe1->getAsTagDecl()->getNameAsString() == *tpe2;
35-
}
36-
return false;
37-
}
38-
3925
static std::array<std::string, 39> reserved_words = {
4026
{"abstract", "case", "catch", "class", "def", "do",
4127
"else", "extends", "false", "final", "finally", "for",
@@ -119,4 +105,17 @@ static inline bool contains(const Type *type,
119105
return false;
120106
}
121107

108+
static inline std::string getRealPath(const char *filename) {
109+
char *p = realpath(filename, nullptr);
110+
std::string path;
111+
if (p) {
112+
path = p;
113+
delete[] p;
114+
} else {
115+
// TODO: check when it happens
116+
path = "";
117+
}
118+
return path;
119+
}
120+
122121
#endif // UTILS_H

bindgen/ir/IR.cpp

+11-5
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ void IR::addEnum(std::string name, const std::string &type,
3333
}
3434
}
3535

36-
void IR::addStruct(std::string name, std::vector<std::shared_ptr<Field>> fields,
37-
uint64_t typeSize, std::shared_ptr<Location> location,
38-
bool isPacked, bool isBitField) {
36+
std::shared_ptr<TypeDef>
37+
IR::addStruct(std::string name, std::vector<std::shared_ptr<Field>> fields,
38+
uint64_t typeSize, std::shared_ptr<Location> location,
39+
bool isPacked, bool isBitField) {
3940
std::shared_ptr<Struct> s =
4041
std::make_shared<Struct>(name, std::move(fields), typeSize,
4142
std::move(location), isPacked, isBitField);
@@ -44,22 +45,27 @@ void IR::addStruct(std::string name, std::vector<std::shared_ptr<Field>> fields,
4445
if (typeDef) {
4546
/* the struct type used to be opaque type, typeDef contains nullptr */
4647
typeDef.get()->setType(s);
48+
return typeDef;
4749
} else {
4850
typeDefs.push_back(s->generateTypeDef());
51+
return typeDefs.back();
4952
}
5053
}
5154

52-
void IR::addUnion(std::string name, std::vector<std::shared_ptr<Field>> fields,
53-
uint64_t maxSize, std::shared_ptr<Location> location) {
55+
std::shared_ptr<TypeDef>
56+
IR::addUnion(std::string name, std::vector<std::shared_ptr<Field>> fields,
57+
uint64_t maxSize, std::shared_ptr<Location> location) {
5458
std::shared_ptr<Union> u = std::make_shared<Union>(
5559
name, std::move(fields), maxSize, std::move(location));
5660
unions.push_back(u);
5761
std::shared_ptr<TypeDef> typeDef = getTypeDefWithName("union_" + name);
5862
if (typeDef) {
5963
/* the union type used to be opaque type, typeDef contains nullptr */
6064
typeDef.get()->setType(u);
65+
return typeDef;
6166
} else {
6267
typeDefs.push_back(u->generateTypeDef());
68+
return typeDefs.back();
6369
}
6470
}
6571

bindgen/ir/IR.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ class IR {
3535
std::vector<Enumerator> enumerators,
3636
std::shared_ptr<Location> location);
3737

38-
void addStruct(std::string name, std::vector<std::shared_ptr<Field>> fields,
39-
uint64_t typeSize, std::shared_ptr<Location> location,
40-
bool isPacked, bool isBitField);
41-
42-
void addUnion(std::string name, std::vector<std::shared_ptr<Field>> fields,
43-
uint64_t maxSize, std::shared_ptr<Location> location);
38+
std::shared_ptr<TypeDef>
39+
addStruct(std::string name, std::vector<std::shared_ptr<Field>> fields,
40+
uint64_t typeSize, std::shared_ptr<Location> location,
41+
bool isPacked, bool isBitField);
42+
43+
std::shared_ptr<TypeDef>
44+
addUnion(std::string name, std::vector<std::shared_ptr<Field>> fields,
45+
uint64_t maxSize, std::shared_ptr<Location> location);
4446

4547
void addLiteralDefine(std::string name, std::string literal,
4648
std::shared_ptr<Type> type);

bindgen/visitor/TreeVisitor.cpp

+5-73
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include "TreeVisitor.h"
2-
#include "clang/AST/RecordLayout.h"
32

43
bool TreeVisitor::VisitFunctionDecl(clang::FunctionDecl *func) {
54
if (!astContext->getSourceManager().isInMainFile(func->getLocation())) {
@@ -37,7 +36,7 @@ bool TreeVisitor::VisitTypedefDecl(clang::TypedefDecl *tpdef) {
3736
std::shared_ptr<Type> type =
3837
typeTranslator.translate(tpdef->getUnderlyingType());
3938
if (type) {
40-
ir.addTypeDef(name, type, getLocation(tpdef));
39+
ir.addTypeDef(name, type, typeTranslator.getLocation(tpdef));
4140
}
4241
return true;
4342
}
@@ -59,7 +58,8 @@ bool TreeVisitor::VisitEnumDecl(clang::EnumDecl *enumdecl) {
5958
std::string scalaType = typeTranslator.getTypeFromTypeMap(
6059
enumdecl->getIntegerType().getUnqualifiedType().getAsString());
6160

62-
ir.addEnum(name, scalaType, std::move(enumerators), getLocation(enumdecl));
61+
ir.addEnum(name, scalaType, std::move(enumerators),
62+
typeTranslator.getLocation(enumdecl));
6363

6464
return true;
6565
}
@@ -76,68 +76,17 @@ bool TreeVisitor::VisitRecordDecl(clang::RecordDecl *record) {
7676

7777
if (record->isUnion() && record->isThisDeclarationADefinition() &&
7878
!record->isAnonymousStructOrUnion() && !name.empty()) {
79-
handleUnion(record, name);
79+
typeTranslator.addUnionDefinition(record, name);
8080
return true;
8181

8282
} else if (record->isStruct() && record->isThisDeclarationADefinition() &&
8383
!record->isAnonymousStructOrUnion() && !name.empty()) {
84-
handleStruct(record, name);
84+
typeTranslator.addStructDefinition(record, name);
8585
return true;
8686
}
8787
return false;
8888
}
8989

90-
void TreeVisitor::handleUnion(clang::RecordDecl *record, std::string name) {
91-
std::vector<std::shared_ptr<Field>> fields;
92-
93-
for (const clang::FieldDecl *field : record->fields()) {
94-
std::string fname = field->getNameAsString();
95-
std::shared_ptr<Type> ftype =
96-
typeTranslator.translate(field->getType());
97-
98-
fields.push_back(std::make_shared<Field>(fname, ftype));
99-
}
100-
101-
uint64_t sizeInBits = astContext->getTypeSize(record->getTypeForDecl());
102-
assert(sizeInBits % 8 == 0);
103-
104-
ir.addUnion(name, std::move(fields), sizeInBits / 8, getLocation(record));
105-
}
106-
107-
void TreeVisitor::handleStruct(clang::RecordDecl *record, std::string name) {
108-
std::string newName = "struct_" + name;
109-
110-
if (record->hasAttr<clang::PackedAttr>()) {
111-
llvm::errs() << "Warning: struct " << name << " is packed. "
112-
<< "Packed structs are not supported by Scala Native. "
113-
<< "Access to fields will not work correctly.\n";
114-
llvm::errs().flush();
115-
}
116-
117-
std::vector<std::shared_ptr<Field>> fields;
118-
const clang::ASTRecordLayout &recordLayout =
119-
astContext->getASTRecordLayout(record);
120-
121-
bool isBitFieldStruct = false;
122-
for (const clang::FieldDecl *field : record->fields()) {
123-
if (field->isBitField()) {
124-
isBitFieldStruct = true;
125-
}
126-
std::shared_ptr<Type> ftype =
127-
typeTranslator.translate(field->getType());
128-
uint64_t recordOffsetInBits =
129-
recordLayout.getFieldOffset(field->getFieldIndex());
130-
fields.push_back(std::make_shared<Field>(field->getNameAsString(),
131-
ftype, recordOffsetInBits));
132-
}
133-
134-
uint64_t sizeInBits = astContext->getTypeSize(record->getTypeForDecl());
135-
assert(sizeInBits % 8 == 0);
136-
137-
ir.addStruct(name, std::move(fields), sizeInBits / 8, getLocation(record),
138-
record->hasAttr<clang::PackedAttr>(), isBitFieldStruct);
139-
}
140-
14190
bool TreeVisitor::VisitVarDecl(clang::VarDecl *varDecl) {
14291
if (!astContext->getSourceManager().isInMainFile(varDecl->getLocation())) {
14392
/* include variables only from the original header */
@@ -157,20 +106,3 @@ bool TreeVisitor::VisitVarDecl(clang::VarDecl *varDecl) {
157106
}
158107
return true;
159108
}
160-
161-
std::shared_ptr<Location> TreeVisitor::getLocation(clang::Decl *decl) {
162-
clang::SourceManager &sm = astContext->getSourceManager();
163-
std::string filename = std::string(sm.getFilename(decl->getLocation()));
164-
char *p = realpath(filename.c_str(), nullptr);
165-
std::string path;
166-
if (p) {
167-
path = p;
168-
delete[] p;
169-
} else {
170-
// TODO: check when it happens
171-
path = "";
172-
}
173-
174-
unsigned lineNumber = sm.getSpellingLineNumber(decl->getLocation());
175-
return std::make_shared<Location>(path, lineNumber);
176-
}

bindgen/visitor/TreeVisitor.h

-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ class TreeVisitor : public clang::RecursiveASTVisitor<TreeVisitor> {
1111
TypeTranslator typeTranslator;
1212
IR &ir;
1313

14-
void handleUnion(clang::RecordDecl *record, std::string name);
15-
16-
void handleStruct(clang::RecordDecl *record, std::string name);
17-
18-
std::shared_ptr<Location> getLocation(clang::Decl *decl);
19-
2014
public:
2115
TreeVisitor(clang::CompilerInstance *CI, IR &ir)
2216
: astContext(&(CI->getASTContext())), typeTranslator(astContext, ir),

0 commit comments

Comments
 (0)