From 5f1958d9b4d1bbba57bb8e73fd57f4fe3bb59f53 Mon Sep 17 00:00:00 2001 From: kornilova-l Date: Mon, 2 Jul 2018 13:50:58 +0400 Subject: [PATCH 1/4] Create TypeDef with nullptr for types that are not yet defined --- bindgen/TypeTranslator.cpp | 17 +++++++-- bindgen/TypeTranslator.h | 2 +- bindgen/Utils.h | 9 +++++ bindgen/ir/Function.cpp | 2 +- bindgen/ir/IR.cpp | 23 ++++++++++-- bindgen/ir/IR.h | 17 +++++++-- bindgen/ir/Struct.cpp | 1 - bindgen/ir/TypeAndName.cpp | 2 +- bindgen/ir/TypeDef.cpp | 8 ++++- bindgen/ir/types/ArrayType.cpp | 4 +-- bindgen/ir/types/ArrayType.h | 2 +- bindgen/ir/types/FunctionPointerType.cpp | 6 ++-- bindgen/ir/types/FunctionPointerType.h | 2 +- bindgen/ir/types/PointerType.cpp | 4 +-- bindgen/ir/types/PointerType.h | 2 +- bindgen/ir/types/Type.cpp | 2 -- bindgen/ir/types/Type.h | 2 +- bindgen/visitor/TreeVisitor.cpp | 31 ++++++++++++---- tests/samples/OpaqueTypes.h | 22 ++++++++++++ tests/samples/OpaqueTypes.scala | 46 ++++++++++++++++++++++++ 20 files changed, 169 insertions(+), 35 deletions(-) create mode 100644 tests/samples/OpaqueTypes.h create mode 100644 tests/samples/OpaqueTypes.scala diff --git a/bindgen/TypeTranslator.cpp b/bindgen/TypeTranslator.cpp index df569cc..753205c 100644 --- a/bindgen/TypeTranslator.cpp +++ b/bindgen/TypeTranslator.cpp @@ -30,6 +30,7 @@ TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir) typeMap["char32_t"] = "native.CChar32"; typeMap["float"] = "native.CFloat"; typeMap["double"] = "native.CDouble"; + typeMap["long double"] = "native.CDouble"; } std::shared_ptr @@ -93,8 +94,16 @@ TypeTranslator::translateStructOrUnionOrEnum(const clang::QualType &qtpe) { * Use type alias instead struct type */ return (*it).second; } - /* type has typedef alias */ - return ir.getTypeDefWithName(name); + std::shared_ptr typeDef = ir.getTypeDefWithName(name); + if (typeDef) { + /* type has typedef alias */ + return typeDef; + } + /* type is not yet defined. + * nullptr will be replaced by actual type */ + typeDef = ir.addTypeDef(replaceChar(name, " ", "_"), nullptr); + addAlias(name, typeDef); + return typeDef; } std::shared_ptr @@ -138,6 +147,10 @@ std::shared_ptr TypeTranslator::translate(const clang::QualType &qtpe, std::make_shared("Byte"), sizeInBits / 8); } + if (tpe->isFunctionType()) { + return nullptr; + } + if (tpe->isFunctionPointerType()) { return translateFunctionPointer(qtpe, avoid); diff --git a/bindgen/TypeTranslator.h b/bindgen/TypeTranslator.h index 68c15fc..7e5c4e4 100644 --- a/bindgen/TypeTranslator.h +++ b/bindgen/TypeTranslator.h @@ -12,7 +12,7 @@ class TypeTranslator { * @param tpe The type to translate * @param avoid A type to avoid, useful to avoid cyclic definitions inside * structs, unions, ... - * @return the type translated + * @return the type translated or nullptr if type is function type. */ std::shared_ptr translate(const clang::QualType &tpe, const std::string * = nullptr); diff --git a/bindgen/Utils.h b/bindgen/Utils.h index 25af2b7..8c74b19 100644 --- a/bindgen/Utils.h +++ b/bindgen/Utils.h @@ -100,4 +100,13 @@ template static inline bool isInstanceOf(PT *type) { return p != nullptr; } +static inline std::string replaceChar(std::string str, const std::string &c1, + const std::string &c2) { + auto f = str.find(c1); + if (f != std::string::npos) { + return str.replace(f, c1.length(), c2); + } + return str; +} + #endif // UTILS_H diff --git a/bindgen/ir/Function.cpp b/bindgen/ir/Function.cpp index c09cce1..1e94437 100644 --- a/bindgen/ir/Function.cpp +++ b/bindgen/ir/Function.cpp @@ -7,7 +7,7 @@ Parameter::Parameter(std::string name, std::shared_ptr type) Function::Function(const std::string &name, std::vector parameters, std::shared_ptr retType, bool isVariadic) : name(name), scalaName(name), parameters(std::move(parameters)), - retType(retType), isVariadic(isVariadic) {} + retType(std::move(retType)), isVariadic(isVariadic) {} llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Function &func) { if (func.scalaName != func.name) { diff --git a/bindgen/ir/IR.cpp b/bindgen/ir/IR.cpp index 170de1c..dc3444b 100644 --- a/bindgen/ir/IR.cpp +++ b/bindgen/ir/IR.cpp @@ -12,8 +12,10 @@ void IR::addFunction(std::string name, std::vector parameters, retType, isVariadic)); } -void IR::addTypeDef(std::string name, std::shared_ptr type) { +std::shared_ptr IR::addTypeDef(std::string name, + std::shared_ptr type) { typeDefs.push_back(std::make_shared(std::move(name), type)); + return typeDefs.back(); } std::shared_ptr IR::addEnum(std::string name, const std::string &type, @@ -38,6 +40,14 @@ std::shared_ptr IR::addStruct(std::string name, return typeDefs.back(); } +void IR::addStruct(std::string name, std::vector fields, + uint64_t typeSize, const std::shared_ptr &typeDef) { + std::shared_ptr s = + std::make_shared(std::move(name), std::move(fields), typeSize); + structs.push_back(s); + typeDef.get()->setType(s); +} + std::shared_ptr IR::addUnion(std::string name, std::vector fields, uint64_t maxSize) { std::shared_ptr u = @@ -47,6 +57,14 @@ IR::addUnion(std::string name, std::vector fields, uint64_t maxSize) { return typeDefs.back(); } +void IR::addUnion(std::string name, std::vector fields, + uint64_t maxSize, const std::shared_ptr &typeDef) { + std::shared_ptr u = + std::make_shared(std::move(name), std::move(fields), maxSize); + unions.push_back(u); + typeDef.get()->setType(u); +} + void IR::addLiteralDefine(std::string name, std::string literal, std::shared_ptr type) { literalDefines.push_back(std::make_shared( @@ -317,7 +335,6 @@ T IR::getDeclarationWithName(std::vector &declarations, return declaration; } } - llvm::errs() << "Failed to get declaration for " << name << "\n"; return nullptr; } @@ -331,4 +348,4 @@ IR::~IR() { possibleVarDefines.clear(); variables.clear(); varDefines.clear(); -} \ No newline at end of file +} diff --git a/bindgen/ir/IR.h b/bindgen/ir/IR.h index 1861a48..3ec85ab 100644 --- a/bindgen/ir/IR.h +++ b/bindgen/ir/IR.h @@ -22,7 +22,8 @@ class IR { void addFunction(std::string name, std::vector parameters, std::shared_ptr retType, bool isVariadic); - void addTypeDef(std::string name, std::shared_ptr type); + std::shared_ptr addTypeDef(std::string name, + std::shared_ptr type); /** * @return type alias for the enum @@ -36,12 +37,24 @@ class IR { std::shared_ptr addStruct(std::string name, std::vector fields, uint64_t typeSize); + /** + * Add struct for which TypeDef already exists + */ + void addStruct(std::string name, std::vector fields, + uint64_t typeSize, const std::shared_ptr &typeDef); + /** * @return type alias for the union */ std::shared_ptr addUnion(std::string name, std::vector fields, uint64_t maxSize); + /** + * Add union for which TypeDef already exists + */ + void addUnion(std::string name, std::vector fields, + uint64_t maxSize, const std::shared_ptr &typeDef); + void addLiteralDefine(std::string name, std::string literal, std::shared_ptr type); @@ -138,8 +151,6 @@ class IR { T getDeclarationWithName(std::vector &declarations, const std::string &name); - template void clearVector(std::vector v); - std::string libName; // name of the library std::string linkName; // name of the library to link with std::string objectName; // name of Scala object diff --git a/bindgen/ir/Struct.cpp b/bindgen/ir/Struct.cpp index c850efe..ab09e8c 100644 --- a/bindgen/ir/Struct.cpp +++ b/bindgen/ir/Struct.cpp @@ -3,7 +3,6 @@ #include "types/ArrayType.h" #include "types/PrimitiveType.h" #include -#include Field::Field(std::string name, std::shared_ptr type) : TypeAndName(std::move(name), std::move(type)) {} diff --git a/bindgen/ir/TypeAndName.cpp b/bindgen/ir/TypeAndName.cpp index 9cd84ff..0a02d33 100644 --- a/bindgen/ir/TypeAndName.cpp +++ b/bindgen/ir/TypeAndName.cpp @@ -2,7 +2,7 @@ #include TypeAndName::TypeAndName(std::string name, std::shared_ptr type) - : name(std::move(name)), type(type) {} + : name(std::move(name)), type(std::move(type)) {} std::shared_ptr TypeAndName::getType() const { return type; } diff --git a/bindgen/ir/TypeDef.cpp b/bindgen/ir/TypeDef.cpp index b92b26f..dc3eef3 100644 --- a/bindgen/ir/TypeDef.cpp +++ b/bindgen/ir/TypeDef.cpp @@ -2,9 +2,15 @@ #include "../Utils.h" TypeDef::TypeDef(std::string name, std::shared_ptr type) - : TypeAndName(std::move(name), type) {} + : TypeAndName(std::move(name), std::move(type)) {} llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const TypeDef &typeDef) { + if (!typeDef.getType()) { + llvm::errs() << "Error: type declaration for " << typeDef.getName() + << " was not found.\n"; + llvm::errs().flush(); + return s; + } s << " type " + handleReservedWords(typeDef.name) + " = " + typeDef.getType()->str() + "\n"; return s; diff --git a/bindgen/ir/types/ArrayType.cpp b/bindgen/ir/types/ArrayType.cpp index ee3bf5f..2577e83 100644 --- a/bindgen/ir/types/ArrayType.cpp +++ b/bindgen/ir/types/ArrayType.cpp @@ -2,7 +2,7 @@ #include "../../Utils.h" ArrayType::ArrayType(std::shared_ptr elementsType, uint64_t size) - : size(size), elementsType(elementsType) {} + : size(size), elementsType(std::move(elementsType)) {} std::string ArrayType::str() const { return "native.CArray[" + elementsType->str() + ", " + @@ -12,5 +12,3 @@ std::string ArrayType::str() const { bool ArrayType::usesType(std::shared_ptr type) const { return this == type.get() || elementsType == type; } - -ArrayType::~ArrayType() {} diff --git a/bindgen/ir/types/ArrayType.h b/bindgen/ir/types/ArrayType.h index ba43557..8859a5d 100644 --- a/bindgen/ir/types/ArrayType.h +++ b/bindgen/ir/types/ArrayType.h @@ -7,7 +7,7 @@ class ArrayType : public Type { public: ArrayType(std::shared_ptr elementsType, uint64_t size); - ~ArrayType() override; + ~ArrayType() override = default; bool usesType(std::shared_ptr type) const override; diff --git a/bindgen/ir/types/FunctionPointerType.cpp b/bindgen/ir/types/FunctionPointerType.cpp index 8e0f0b5..26c9524 100644 --- a/bindgen/ir/types/FunctionPointerType.cpp +++ b/bindgen/ir/types/FunctionPointerType.cpp @@ -4,7 +4,7 @@ FunctionPointerType::FunctionPointerType( std::shared_ptr returnType, const std::vector> ¶metersTypes, bool isVariadic) - : returnType(returnType), parametersTypes(parametersTypes), + : returnType(std::move(returnType)), parametersTypes(parametersTypes), isVariadic(isVariadic) {} std::string FunctionPointerType::str() const { @@ -30,12 +30,10 @@ bool FunctionPointerType::usesType(std::shared_ptr type) const { return true; } - for (auto parameterType : parametersTypes) { + for (const auto ¶meterType : parametersTypes) { if (parameterType == type) { return true; } } return false; } - -FunctionPointerType::~FunctionPointerType() {} diff --git a/bindgen/ir/types/FunctionPointerType.h b/bindgen/ir/types/FunctionPointerType.h index 1dd9859..36863ba 100644 --- a/bindgen/ir/types/FunctionPointerType.h +++ b/bindgen/ir/types/FunctionPointerType.h @@ -11,7 +11,7 @@ class FunctionPointerType : public Type { const std::vector> ¶metersTypes, bool isVariadic); - ~FunctionPointerType() override; + ~FunctionPointerType() override = default; bool usesType(std::shared_ptr type) const override; diff --git a/bindgen/ir/types/PointerType.cpp b/bindgen/ir/types/PointerType.cpp index a0d9349..2116f91 100644 --- a/bindgen/ir/types/PointerType.cpp +++ b/bindgen/ir/types/PointerType.cpp @@ -1,6 +1,6 @@ #include "PointerType.h" -PointerType::PointerType(std::shared_ptr type) : type(type) {} +PointerType::PointerType(std::shared_ptr type) : type(std::move(type)) {} std::string PointerType::str() const { return "native.Ptr[" + type->str() + "]"; @@ -12,5 +12,3 @@ bool PointerType::usesType(std::shared_ptr type) const { } return this->type == type; } - -PointerType::~PointerType() {} diff --git a/bindgen/ir/types/PointerType.h b/bindgen/ir/types/PointerType.h index 194d651..0eda2e2 100644 --- a/bindgen/ir/types/PointerType.h +++ b/bindgen/ir/types/PointerType.h @@ -7,7 +7,7 @@ class PointerType : public Type { public: explicit PointerType(std::shared_ptr type); - ~PointerType() override; + ~PointerType() override = default; bool usesType(std::shared_ptr type) const override; diff --git a/bindgen/ir/types/Type.cpp b/bindgen/ir/types/Type.cpp index e668a76..376f35b 100644 --- a/bindgen/ir/types/Type.cpp +++ b/bindgen/ir/types/Type.cpp @@ -3,5 +3,3 @@ std::string Type::str() const { return ""; } bool Type::usesType(std::shared_ptr type) const { return false; } - -Type::~Type() = default; diff --git a/bindgen/ir/types/Type.h b/bindgen/ir/types/Type.h index 24eff8c..6ac4058 100644 --- a/bindgen/ir/types/Type.h +++ b/bindgen/ir/types/Type.h @@ -9,7 +9,7 @@ */ class Type { public: - virtual ~Type(); + virtual ~Type() = default; virtual std::string str() const; diff --git a/bindgen/visitor/TreeVisitor.cpp b/bindgen/visitor/TreeVisitor.cpp index 8c8ce95..983b784 100644 --- a/bindgen/visitor/TreeVisitor.cpp +++ b/bindgen/visitor/TreeVisitor.cpp @@ -46,7 +46,9 @@ bool TreeVisitor::VisitTypedefDecl(clang::TypedefDecl *tpdef) { std::shared_ptr type = typeTranslator.translate(tpdef->getUnderlyingType()); - ir.addTypeDef(name, type); + if (type) { + ir.addTypeDef(name, type); + } return true; } @@ -86,8 +88,8 @@ bool TreeVisitor::VisitRecordDecl(clang::RecordDecl *record) { name = record->getTypedefNameForAnonDecl()->getNameAsString(); } - if (record->isUnion() && !record->isAnonymousStructOrUnion() && - !name.empty()) { + if (record->isUnion() && record->isThisDeclarationADefinition() && + !record->isAnonymousStructOrUnion() && !name.empty()) { handleUnion(record, name); return true; @@ -115,7 +117,16 @@ void TreeVisitor::handleUnion(clang::RecordDecl *record, std::string name) { fields.push_back(new Field(fname, ftype)); } - std::shared_ptr alias = ir.addUnion(name, std::move(fields), maxSize); + std::shared_ptr alias = nullptr; + + std::shared_ptr typeDef = ir.getTypeDefWithName("union_" + name); + if (typeDef) { + /* typedef for this union already exists */ + ir.addUnion(name, std::move(fields), maxSize, typeDef); + alias = typeDef; + } else { + alias = ir.addUnion(name, std::move(fields), maxSize); + } typeTranslator.addAlias("union " + name, alias); } @@ -155,8 +166,16 @@ void TreeVisitor::handleStruct(clang::RecordDecl *record, std::string name) { uint64_t sizeInBits = astContext->getTypeSize(record->getTypeForDecl()); assert(sizeInBits % 8 == 0); - std::shared_ptr alias = - ir.addStruct(name, std::move(fields), sizeInBits / 8); + std::shared_ptr alias = nullptr; + + std::shared_ptr typeDef = ir.getTypeDefWithName(newName); + if (typeDef) { + /* typedef for this struct already exists */ + alias = typeDef; + ir.addStruct(name, std::move(fields), sizeInBits / 8, typeDef); + } else { + alias = ir.addStruct(name, std::move(fields), sizeInBits / 8); + } typeTranslator.addAlias("struct " + name, alias); } diff --git a/tests/samples/OpaqueTypes.h b/tests/samples/OpaqueTypes.h new file mode 100644 index 0000000..c01cff2 --- /dev/null +++ b/tests/samples/OpaqueTypes.h @@ -0,0 +1,22 @@ +struct point; +struct point *move(struct point *point, int x, int y); + +typedef struct points points; +typedef union u u; + +union u *processPoints(points *p); + +union u { + int i; + float f; +}; + +struct points { + struct point *point1; + struct point *point2; +}; + +struct point { + int x; + int y; +}; diff --git a/tests/samples/OpaqueTypes.scala b/tests/samples/OpaqueTypes.scala new file mode 100644 index 0000000..3a570a5 --- /dev/null +++ b/tests/samples/OpaqueTypes.scala @@ -0,0 +1,46 @@ +package org.scalanative.bindgen.samples + +import scala.scalanative._ +import scala.scalanative.native._ + +@native.link("bindgentests") +@native.extern +object OpaqueTypes { + type struct_point = native.CStruct2[native.CInt, native.CInt] + type struct_points = native.CStruct2[native.Ptr[struct_point], native.Ptr[struct_point]] + type points = struct_points + type union_u = native.CArray[Byte, native.Nat._4] + type u = union_u + def move(point: native.Ptr[struct_point], x: native.CInt, y: native.CInt): native.Ptr[struct_point] = native.extern + def processPoints(p: native.Ptr[points]): native.Ptr[union_u] = native.extern +} + +import OpaqueTypes._ + +object OpaqueTypesHelpers { + + implicit class struct_points_ops(val p: native.Ptr[struct_points]) extends AnyVal { + def point1: native.Ptr[struct_point] = !p._1 + def point1_=(value: native.Ptr[struct_point]): Unit = !p._1 = value + def point2: native.Ptr[struct_point] = !p._2 + def point2_=(value: native.Ptr[struct_point]): Unit = !p._2 = value + } + + def struct_points()(implicit z: native.Zone): native.Ptr[struct_points] = native.alloc[struct_points] + + implicit class struct_point_ops(val p: native.Ptr[struct_point]) extends AnyVal { + def x: native.CInt = !p._1 + def x_=(value: native.CInt): Unit = !p._1 = value + def y: native.CInt = !p._2 + def y_=(value: native.CInt): Unit = !p._2 = value + } + + def struct_point()(implicit z: native.Zone): native.Ptr[struct_point] = native.alloc[struct_point] + + implicit class union_u_pos(val p: native.Ptr[union_u]) extends AnyVal { + def i: native.Ptr[native.CInt] = p.cast[native.Ptr[native.CInt]] + def i_=(value: native.CInt): Unit = !p.cast[native.Ptr[native.CInt]] = value + def f: native.Ptr[native.CFloat] = p.cast[native.Ptr[native.CFloat]] + def f_=(value: native.CFloat): Unit = !p.cast[native.Ptr[native.CFloat]] = value + } +} From 9834ee725051da02d932eb024b1aa1415ab28461 Mon Sep 17 00:00:00 2001 From: kornilova-l Date: Tue, 3 Jul 2018 18:35:24 +0400 Subject: [PATCH 2/4] Remove redundant aliasesMap --- bindgen/TypeTranslator.cpp | 26 +++++++++++--------------- bindgen/TypeTranslator.h | 7 ------- bindgen/Utils.h | 7 ++++--- bindgen/ir/IR.cpp | 5 +++++ bindgen/visitor/TreeVisitor.cpp | 7 ------- 5 files changed, 20 insertions(+), 32 deletions(-) diff --git a/bindgen/TypeTranslator.cpp b/bindgen/TypeTranslator.cpp index 753205c..42bf295 100644 --- a/bindgen/TypeTranslator.cpp +++ b/bindgen/TypeTranslator.cpp @@ -87,22 +87,22 @@ TypeTranslator::translatePointer(const clang::QualType &pte, std::shared_ptr TypeTranslator::translateStructOrUnionOrEnum(const clang::QualType &qtpe) { std::string name = qtpe.getUnqualifiedType().getAsString(); + std::string nameWithoutSpace = replaceChar(name, " ", "_"); - auto it = aliasesMap.find(name); - if (it != aliasesMap.end()) { - /* name contains space: struct . - * Use type alias instead struct type */ - return (*it).second; - } - std::shared_ptr typeDef = ir.getTypeDefWithName(name); + /* If the struct was already declared then there is a TypeDef instance + * with appropriate name. + * + * If there is no such TypeDef then the type is opaque and TypeDef with + * nullptr will be generated for the type. */ + + std::shared_ptr typeDef = ir.getTypeDefWithName(nameWithoutSpace); if (typeDef) { - /* type has typedef alias */ return typeDef; } /* type is not yet defined. - * nullptr will be replaced by actual type */ - typeDef = ir.addTypeDef(replaceChar(name, " ", "_"), nullptr); - addAlias(name, typeDef); + * TypeDef with nullptr will be created. + * nullptr will be replaced by actual type when the type is declared. */ + typeDef = ir.addTypeDef(nameWithoutSpace, nullptr); return typeDef; } @@ -184,10 +184,6 @@ std::shared_ptr TypeTranslator::translate(const clang::QualType &qtpe, } } -void TypeTranslator::addAlias(std::string cName, std::shared_ptr type) { - aliasesMap[cName] = type; -} - std::string TypeTranslator::getTypeFromTypeMap(std::string cType) { auto it = typeMap.find(cType); if (it != typeMap.end()) { diff --git a/bindgen/TypeTranslator.h b/bindgen/TypeTranslator.h index 7e5c4e4..0955b08 100644 --- a/bindgen/TypeTranslator.h +++ b/bindgen/TypeTranslator.h @@ -17,8 +17,6 @@ class TypeTranslator { std::shared_ptr translate(const clang::QualType &tpe, const std::string * = nullptr); - void addAlias(std::string cName, std::shared_ptr type); - std::string getTypeFromTypeMap(std::string cType); private: @@ -30,11 +28,6 @@ class TypeTranslator { */ std::map typeMap; - /** - * Maps C struct, union or enum name to Type alias - */ - std::map> aliasesMap; - std::shared_ptr translateStructOrUnionOrEnum(const clang::QualType &qtpe); diff --git a/bindgen/Utils.h b/bindgen/Utils.h index 8c74b19..c666e12 100644 --- a/bindgen/Utils.h +++ b/bindgen/Utils.h @@ -100,13 +100,14 @@ template static inline bool isInstanceOf(PT *type) { return p != nullptr; } -static inline std::string replaceChar(std::string str, const std::string &c1, +static inline std::string replaceChar(const std::string &str, + const std::string &c1, const std::string &c2) { auto f = str.find(c1); if (f != std::string::npos) { - return str.replace(f, c1.length(), c2); + return std::string(str).replace(f, c1.length(), c2); } - return str; + return std::string(str); } #endif // UTILS_H diff --git a/bindgen/ir/IR.cpp b/bindgen/ir/IR.cpp index dc3444b..4c6ba42 100644 --- a/bindgen/ir/IR.cpp +++ b/bindgen/ir/IR.cpp @@ -322,6 +322,11 @@ std::shared_ptr IR::addVariable(const std::string &name, } std::shared_ptr IR::getTypeDefWithName(const std::string &name) { + /* nullptr is returned in 2 cases: + * 1. TypeTranslator translates opaque struct/union type for which TypeDef + * was not created. + * 2. TreeVisitor visits struct/union declaration and it checks whether a + * TypeDef already exists for it.*/ return getDeclarationWithName(typeDefs, name); } diff --git a/bindgen/visitor/TreeVisitor.cpp b/bindgen/visitor/TreeVisitor.cpp index 983b784..16f0376 100644 --- a/bindgen/visitor/TreeVisitor.cpp +++ b/bindgen/visitor/TreeVisitor.cpp @@ -71,9 +71,6 @@ bool TreeVisitor::VisitEnumDecl(clang::EnumDecl *enumdecl) { std::shared_ptr alias = ir.addEnum(name, scalaType, std::move(enumerators)); - if (alias != nullptr) { - typeTranslator.addAlias("enum " + name, alias); - } return true; } @@ -127,8 +124,6 @@ void TreeVisitor::handleUnion(clang::RecordDecl *record, std::string name) { } else { alias = ir.addUnion(name, std::move(fields), maxSize); } - - typeTranslator.addAlias("union " + name, alias); } void TreeVisitor::handleStruct(clang::RecordDecl *record, std::string name) { @@ -176,8 +171,6 @@ void TreeVisitor::handleStruct(clang::RecordDecl *record, std::string name) { } else { alias = ir.addStruct(name, std::move(fields), sizeInBits / 8); } - - typeTranslator.addAlias("struct " + name, alias); } bool TreeVisitor::VisitVarDecl(clang::VarDecl *varDecl) { From c244c88320d4d72bba66d7833567878e2af0eddb Mon Sep 17 00:00:00 2001 From: kornilova-l Date: Tue, 3 Jul 2018 19:17:19 +0400 Subject: [PATCH 3/4] Check if TypeDef already exists in addStruct and addUnion methods --- bindgen/ir/IR.cpp | 43 ++++++++++++++------------------- bindgen/ir/IR.h | 22 ++--------------- bindgen/visitor/TreeVisitor.cpp | 23 +++--------------- tests/samples/OpaqueTypes.h | 3 ++- tests/samples/OpaqueTypes.scala | 2 +- 5 files changed, 26 insertions(+), 67 deletions(-) diff --git a/bindgen/ir/IR.cpp b/bindgen/ir/IR.cpp index 4c6ba42..a6bc287 100644 --- a/bindgen/ir/IR.cpp +++ b/bindgen/ir/IR.cpp @@ -30,39 +30,32 @@ std::shared_ptr IR::addEnum(std::string name, const std::string &type, return nullptr; } -std::shared_ptr IR::addStruct(std::string name, - std::vector fields, - uint64_t typeSize) { - std::shared_ptr s = - std::make_shared(std::move(name), std::move(fields), typeSize); - structs.push_back(s); - typeDefs.push_back(s->generateTypeDef()); - return typeDefs.back(); -} - void IR::addStruct(std::string name, std::vector fields, - uint64_t typeSize, const std::shared_ptr &typeDef) { + uint64_t typeSize) { std::shared_ptr s = - std::make_shared(std::move(name), std::move(fields), typeSize); + std::make_shared(name, std::move(fields), typeSize); structs.push_back(s); - typeDef.get()->setType(s); -} - -std::shared_ptr -IR::addUnion(std::string name, std::vector fields, uint64_t maxSize) { - std::shared_ptr u = - std::make_shared(std::move(name), std::move(fields), maxSize); - unions.push_back(u); - typeDefs.push_back(u->generateTypeDef()); - return typeDefs.back(); + std::shared_ptr typeDef = getTypeDefWithName("struct_" + name); + if (typeDef) { + /* the struct type used to be opaque type, typeDef contains nullptr */ + typeDef.get()->setType(s); + } else { + typeDefs.push_back(s->generateTypeDef()); + } } void IR::addUnion(std::string name, std::vector fields, - uint64_t maxSize, const std::shared_ptr &typeDef) { + uint64_t maxSize) { std::shared_ptr u = - std::make_shared(std::move(name), std::move(fields), maxSize); + std::make_shared(name, std::move(fields), maxSize); unions.push_back(u); - typeDef.get()->setType(u); + std::shared_ptr typeDef = getTypeDefWithName("union_" + name); + if (typeDef) { + /* the union type used to be opaque type, typeDef contains nullptr */ + typeDef.get()->setType(u); + } else { + typeDefs.push_back(u->generateTypeDef()); + } } void IR::addLiteralDefine(std::string name, std::string literal, diff --git a/bindgen/ir/IR.h b/bindgen/ir/IR.h index 3ec85ab..ee0a375 100644 --- a/bindgen/ir/IR.h +++ b/bindgen/ir/IR.h @@ -31,29 +31,11 @@ class IR { std::shared_ptr addEnum(std::string name, const std::string &type, std::vector enumerators); - /** - * @return type alias for the struct - */ - std::shared_ptr - addStruct(std::string name, std::vector fields, uint64_t typeSize); - - /** - * Add struct for which TypeDef already exists - */ void addStruct(std::string name, std::vector fields, - uint64_t typeSize, const std::shared_ptr &typeDef); + uint64_t typeSize); - /** - * @return type alias for the union - */ - std::shared_ptr - addUnion(std::string name, std::vector fields, uint64_t maxSize); - - /** - * Add union for which TypeDef already exists - */ void addUnion(std::string name, std::vector fields, - uint64_t maxSize, const std::shared_ptr &typeDef); + uint64_t maxSize); void addLiteralDefine(std::string name, std::string literal, std::shared_ptr type); diff --git a/bindgen/visitor/TreeVisitor.cpp b/bindgen/visitor/TreeVisitor.cpp index 16f0376..500c398 100644 --- a/bindgen/visitor/TreeVisitor.cpp +++ b/bindgen/visitor/TreeVisitor.cpp @@ -114,16 +114,7 @@ void TreeVisitor::handleUnion(clang::RecordDecl *record, std::string name) { fields.push_back(new Field(fname, ftype)); } - std::shared_ptr alias = nullptr; - - std::shared_ptr typeDef = ir.getTypeDefWithName("union_" + name); - if (typeDef) { - /* typedef for this union already exists */ - ir.addUnion(name, std::move(fields), maxSize, typeDef); - alias = typeDef; - } else { - alias = ir.addUnion(name, std::move(fields), maxSize); - } + ir.addUnion(name, std::move(fields), maxSize); } void TreeVisitor::handleStruct(clang::RecordDecl *record, std::string name) { @@ -161,16 +152,8 @@ void TreeVisitor::handleStruct(clang::RecordDecl *record, std::string name) { uint64_t sizeInBits = astContext->getTypeSize(record->getTypeForDecl()); assert(sizeInBits % 8 == 0); - std::shared_ptr alias = nullptr; - - std::shared_ptr typeDef = ir.getTypeDefWithName(newName); - if (typeDef) { - /* typedef for this struct already exists */ - alias = typeDef; - ir.addStruct(name, std::move(fields), sizeInBits / 8, typeDef); - } else { - alias = ir.addStruct(name, std::move(fields), sizeInBits / 8); - } + + ir.addStruct(name, std::move(fields), sizeInBits / 8); } bool TreeVisitor::VisitVarDecl(clang::VarDecl *varDecl) { diff --git a/tests/samples/OpaqueTypes.h b/tests/samples/OpaqueTypes.h index c01cff2..4264fe7 100644 --- a/tests/samples/OpaqueTypes.h +++ b/tests/samples/OpaqueTypes.h @@ -1,7 +1,8 @@ +typedef struct points points; + struct point; struct point *move(struct point *point, int x, int y); -typedef struct points points; typedef union u u; union u *processPoints(points *p); diff --git a/tests/samples/OpaqueTypes.scala b/tests/samples/OpaqueTypes.scala index 3a570a5..b5a32b0 100644 --- a/tests/samples/OpaqueTypes.scala +++ b/tests/samples/OpaqueTypes.scala @@ -6,9 +6,9 @@ import scala.scalanative.native._ @native.link("bindgentests") @native.extern object OpaqueTypes { - type struct_point = native.CStruct2[native.CInt, native.CInt] type struct_points = native.CStruct2[native.Ptr[struct_point], native.Ptr[struct_point]] type points = struct_points + type struct_point = native.CStruct2[native.CInt, native.CInt] type union_u = native.CArray[Byte, native.Nat._4] type u = union_u def move(point: native.Ptr[struct_point], x: native.CInt, y: native.CInt): native.Ptr[struct_point] = native.extern From 7d1f079dc1785dff7ce9ee1f8e86fc84e085120e Mon Sep 17 00:00:00 2001 From: kornilova-l Date: Wed, 4 Jul 2018 21:37:14 +0300 Subject: [PATCH 4/4] Fix closing bracket --- bindgen/Utils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/bindgen/Utils.h b/bindgen/Utils.h index 858e31f..00ac8d1 100644 --- a/bindgen/Utils.h +++ b/bindgen/Utils.h @@ -109,6 +109,7 @@ static inline std::string replaceChar(const std::string &str, return std::string(str).replace(f, c1.length(), c2); } return std::string(str); +} /** * Types may be wrapper in a chain of typedefs.