Skip to content

Commit

Permalink
Fix detection of cyclic structs and unions
Browse files Browse the repository at this point in the history
Break cycle only in one place.
Support breaking cycles on complex types.
Remove `avoid` parameter in TypeTranslator methods.
  • Loading branch information
kornilova203 committed Jul 31, 2018
1 parent 7f1ebd4 commit e698e7f
Show file tree
Hide file tree
Showing 31 changed files with 921 additions and 248 deletions.
1 change: 0 additions & 1 deletion bindgen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ add_executable(bindgen
defines/DefineFinderActionFactory.h
TypeTranslator.h
TypeTranslator.cpp
CycleDetection.h
Utils.h
ir/IR.h
ir/IR.cpp
Expand Down
61 changes: 0 additions & 61 deletions bindgen/CycleDetection.h

This file was deleted.

39 changes: 12 additions & 27 deletions bindgen/TypeTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,17 @@ TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir)
}

std::shared_ptr<Type>
TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe,
const std::string *avoid) {
TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe) {
const auto *ptr = qtpe.getTypePtr()->getAs<clang::PointerType>();
const clang::QualType &inner = ptr->getPointeeType();

if (inner->isFunctionProtoType()) {
const auto *fc = inner->getAs<clang::FunctionProtoType>();
std::shared_ptr<Type> returnType =
translate(fc->getReturnType(), avoid);
std::shared_ptr<Type> returnType = translate(fc->getReturnType());
std::vector<std::shared_ptr<const Type>> parametersTypes;

for (const clang::QualType &param : fc->param_types()) {
parametersTypes.push_back(translate(param, avoid));
parametersTypes.push_back(translate(param));
}

return std::make_shared<FunctionPointerType>(
Expand All @@ -61,8 +59,7 @@ TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe,
}

std::shared_ptr<Type>
TypeTranslator::translatePointer(const clang::QualType &pte,
const std::string *avoid) {
TypeTranslator::translatePointer(const clang::QualType &pte) {

if (pte->isBuiltinType()) {
const clang::BuiltinType *as = pte->getAs<clang::BuiltinType>();
Expand All @@ -81,7 +78,7 @@ TypeTranslator::translatePointer(const clang::QualType &pte,
}
}

return std::make_shared<PointerType>(translate(pte, avoid));
return std::make_shared<PointerType>(translate(pte));
}

std::shared_ptr<Type>
Expand Down Expand Up @@ -120,10 +117,9 @@ TypeTranslator::translateStructOrUnion(const clang::QualType &qtpe) {
}

std::shared_ptr<Type>
TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar,
const std::string *avoid) {
TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar) {
const uint64_t size = ar->getSize().getZExtValue();
std::shared_ptr<Type> elementType = translate(ar->getElementType(), avoid);
std::shared_ptr<Type> elementType = translate(ar->getElementType());
if (elementType == nullptr) {
llvm::errs() << "Failed to translate array type "
<< ar->getElementType().getAsString() << "\n";
Expand All @@ -133,30 +129,20 @@ TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar,
return std::make_shared<ArrayType>(elementType, size);
}

std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe,
const std::string *avoid) {
std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe) {

const clang::Type *tpe = qtpe.getTypePtr();

if (typeEquals(tpe, avoid)) {
// This is a type that we want to avoid the usage.
// Êxample: A struct that has a pointer to itself
uint64_t sizeInBits = ctx->getTypeSize(tpe);
assert(sizeInBits % 8 == 0);
return std::make_shared<ArrayType>(
std::make_shared<PrimitiveType>("Byte"), sizeInBits / 8);
}

if (tpe->isFunctionType()) {
return nullptr;
}

if (tpe->isFunctionPointerType()) {
return translateFunctionPointer(qtpe, avoid);
return translateFunctionPointer(qtpe);

} else if (tpe->isPointerType()) {
return translatePointer(
tpe->getAs<clang::PointerType>()->getPointeeType(), avoid);
tpe->getAs<clang::PointerType>()->getPointeeType());

} else if (qtpe->isStructureType()) {
return translateStructOrUnion(qtpe);
Expand All @@ -168,10 +154,9 @@ std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe,
return translateStructOrUnionOrEnum(qtpe);

} else if (qtpe->isConstantArrayType()) {
return translateConstantArray(ctx->getAsConstantArrayType(qtpe), avoid);
return translateConstantArray(ctx->getAsConstantArrayType(qtpe));
} else if (qtpe->isArrayType()) {
return translatePointer(ctx->getAsArrayType(qtpe)->getElementType(),
avoid);
return translatePointer(ctx->getAsArrayType(qtpe)->getElementType());
} else {

auto found = typeMap.find(qtpe.getUnqualifiedType().getAsString());
Expand Down
14 changes: 4 additions & 10 deletions bindgen/TypeTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,9 @@ class TypeTranslator {
/**
* @brief Translate the qualified type from c to a scala type
* @param tpe The type to translate
* @param avoid A type to avoid, useful to avoid cyclic definitions inside
* structs, unions, ...
* @return the type translated or nullptr if type is function type.
*/
std::shared_ptr<Type> translate(const clang::QualType &tpe,
const std::string *avoid = nullptr);
std::shared_ptr<Type> translate(const clang::QualType &tpe);

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

Expand All @@ -33,13 +30,10 @@ class TypeTranslator {

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

std::shared_ptr<Type> translateFunctionPointer(const clang::QualType &qtpe,
const std::string *avoid);
std::shared_ptr<Type> translateFunctionPointer(const clang::QualType &qtpe);

std::shared_ptr<Type> translatePointer(const clang::QualType &pointee,
const std::string *avoid);
std::shared_ptr<Type> translatePointer(const clang::QualType &pointee);

std::shared_ptr<Type>
translateConstantArray(const clang::ConstantArrayType *ar,
const std::string *avoid);
translateConstantArray(const clang::ConstantArrayType *ar);
};
10 changes: 10 additions & 0 deletions bindgen/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,14 @@ static inline bool isAliasForOpaqueType(const Type *type) {
return false;
}

static inline bool contains(const Type *type,
std::vector<std::shared_ptr<const Type>> &types) {
for (const auto &t : types) {
if (*type == *t) {
return true;
}
}
return false;
}

#endif // UTILS_H
13 changes: 9 additions & 4 deletions bindgen/ir/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,19 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Function &func) {
return s;
}

bool Function::usesType(std::shared_ptr<const Type> type,
bool stopOnTypeDefs) const {
if (*retType == *type || retType->usesType(type, stopOnTypeDefs)) {
bool Function::usesType(
std::shared_ptr<const Type> type, bool stopOnTypeDefs,
std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
visitedTypes.clear();
if (*retType == *type ||
retType.get()->usesType(type, stopOnTypeDefs, visitedTypes)) {
return true;
}
for (const auto &parameter : parameters) {
visitedTypes.clear();
if (*parameter->getType() == *type ||
parameter->getType()->usesType(type, stopOnTypeDefs)) {
parameter->getType().get()->usesType(type, stopOnTypeDefs,
visitedTypes)) {
return true;
}
}
Expand Down
3 changes: 2 additions & 1 deletion bindgen/ir/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class Function {
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &s,
const Function &func);

bool usesType(std::shared_ptr<const Type> type, bool stopOnTypeDefs) const;
bool usesType(std::shared_ptr<const Type> type, bool stopOnTypeDefs,
std::vector<std::shared_ptr<const Type>> &visitedTypes) const;

std::string getName() const;

Expand Down
Loading

0 comments on commit e698e7f

Please sign in to comment.