Skip to content

Commit c2845fb

Browse files
authored
Merge pull request #143 from kornilova-l/0.3
0.3
2 parents efcdf01 + 3a52cea commit c2845fb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1960
-628
lines changed

bindgen/CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ add_executable(bindgen
3636
defines/DefineFinderActionFactory.h
3737
TypeTranslator.h
3838
TypeTranslator.cpp
39-
CycleDetection.h
4039
Utils.h
4140
ir/IR.h
4241
ir/IR.cpp
@@ -74,6 +73,8 @@ add_executable(bindgen
7473
ir/Location.cpp
7574
ir/LocationManager.h
7675
ir/LocationManager.cpp
76+
ir/LocatableType.cpp
77+
ir/LocatableType.h
7778
)
7879

7980
if (STATIC_LINKING)

bindgen/CycleDetection.h

-61
This file was deleted.

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

+102-40
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() {
@@ -34,19 +34,17 @@ TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir)
3434
}
3535

3636
std::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 &param : 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

6361
std::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

8784
std::shared_ptr<Type>
@@ -109,21 +106,26 @@ TypeTranslator::translateStructOrUnionOrEnum(const clang::QualType &qtpe) {
109106
std::shared_ptr<Type>
110107
TypeTranslator::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

122125
std::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+
}

bindgen/TypeTranslator.h

+16-10
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,25 @@ class TypeTranslator {
1010
/**
1111
* @brief Translate the qualified type from c to a scala type
1212
* @param tpe The type to translate
13-
* @param avoid A type to avoid, useful to avoid cyclic definitions inside
14-
* structs, unions, ...
1513
* @return the type translated or nullptr if type is function type.
1614
*/
17-
std::shared_ptr<Type> translate(const clang::QualType &tpe,
18-
const std::string *avoid = nullptr);
15+
std::shared_ptr<Type> translate(const clang::QualType &tpe);
1916

2017
std::string getTypeFromTypeMap(std::string cType);
2118

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+
2227
private:
2328
clang::ASTContext *ctx;
2429
IR &ir;
30+
int anonymousStructId = 0;
31+
int anonymousUnionId = 0;
2532

2633
/**
2734
* Primitive types
@@ -33,13 +40,12 @@ class TypeTranslator {
3340

3441
std::shared_ptr<Type> translateStructOrUnion(const clang::QualType &qtpe);
3542

36-
std::shared_ptr<Type> translateFunctionPointer(const clang::QualType &qtpe,
37-
const std::string *avoid);
43+
std::shared_ptr<Type> translateFunctionPointer(const clang::QualType &qtpe);
3844

39-
std::shared_ptr<Type> translatePointer(const clang::QualType &pointee,
40-
const std::string *avoid);
45+
std::shared_ptr<Type> translatePointer(const clang::QualType &pointee);
4146

4247
std::shared_ptr<Type>
43-
translateConstantArray(const clang::ConstantArrayType *ar,
44-
const std::string *avoid);
48+
translateConstantArray(const clang::ConstantArrayType *ar);
49+
50+
std::shared_ptr<Type> translateEnum(const clang::QualType &type);
4551
};

0 commit comments

Comments
 (0)