Skip to content

Commit 753a512

Browse files
authored
Merge pull request #94 from kornilova-l/opaque-type
Handle opaque types
2 parents e2eab49 + 7d1f079 commit 753a512

20 files changed

+159
-78
lines changed

bindgen/TypeTranslator.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir)
3030
typeMap["char32_t"] = "native.CChar32";
3131
typeMap["float"] = "native.CFloat";
3232
typeMap["double"] = "native.CDouble";
33+
typeMap["long double"] = "native.CDouble";
3334
}
3435

3536
std::shared_ptr<Type>
@@ -86,15 +87,23 @@ TypeTranslator::translatePointer(const clang::QualType &pte,
8687
std::shared_ptr<Type>
8788
TypeTranslator::translateStructOrUnionOrEnum(const clang::QualType &qtpe) {
8889
std::string name = qtpe.getUnqualifiedType().getAsString();
90+
std::string nameWithoutSpace = replaceChar(name, " ", "_");
8991

90-
auto it = aliasesMap.find(name);
91-
if (it != aliasesMap.end()) {
92-
/* name contains space: struct <name>.
93-
* Use type alias instead struct type */
94-
return (*it).second;
92+
/* If the struct was already declared then there is a TypeDef instance
93+
* with appropriate name.
94+
*
95+
* If there is no such TypeDef then the type is opaque and TypeDef with
96+
* nullptr will be generated for the type. */
97+
98+
std::shared_ptr<TypeDef> typeDef = ir.getTypeDefWithName(nameWithoutSpace);
99+
if (typeDef) {
100+
return typeDef;
95101
}
96-
/* type has typedef alias */
97-
return ir.getTypeDefWithName(name);
102+
/* type is not yet defined.
103+
* TypeDef with nullptr will be created.
104+
* nullptr will be replaced by actual type when the type is declared. */
105+
typeDef = ir.addTypeDef(nameWithoutSpace, nullptr);
106+
return typeDef;
98107
}
99108

100109
std::shared_ptr<Type>
@@ -138,6 +147,10 @@ std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe,
138147
std::make_shared<PrimitiveType>("Byte"), sizeInBits / 8);
139148
}
140149

150+
if (tpe->isFunctionType()) {
151+
return nullptr;
152+
}
153+
141154
if (tpe->isFunctionPointerType()) {
142155
return translateFunctionPointer(qtpe, avoid);
143156

@@ -171,10 +184,6 @@ std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe,
171184
}
172185
}
173186

174-
void TypeTranslator::addAlias(std::string cName, std::shared_ptr<Type> type) {
175-
aliasesMap[cName] = type;
176-
}
177-
178187
std::string TypeTranslator::getTypeFromTypeMap(std::string cType) {
179188
auto it = typeMap.find(cType);
180189
if (it != typeMap.end()) {

bindgen/TypeTranslator.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ class TypeTranslator {
1212
* @param tpe The type to translate
1313
* @param avoid A type to avoid, useful to avoid cyclic definitions inside
1414
* structs, unions, ...
15-
* @return the type translated
15+
* @return the type translated or nullptr if type is function type.
1616
*/
1717
std::shared_ptr<Type> translate(const clang::QualType &tpe,
1818
const std::string * = nullptr);
1919

20-
void addAlias(std::string cName, std::shared_ptr<Type> type);
21-
2220
std::string getTypeFromTypeMap(std::string cType);
2321

2422
private:
@@ -30,11 +28,6 @@ class TypeTranslator {
3028
*/
3129
std::map<std::string, std::string> typeMap;
3230

33-
/**
34-
* Maps C struct, union or enum name to Type alias
35-
*/
36-
std::map<std::string, std::shared_ptr<Type>> aliasesMap;
37-
3831
std::shared_ptr<Type>
3932
translateStructOrUnionOrEnum(const clang::QualType &qtpe);
4033

bindgen/Utils.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@ template <typename T, typename PT> static inline bool isInstanceOf(PT *type) {
101101
return p != nullptr;
102102
}
103103

104+
static inline std::string replaceChar(const std::string &str,
105+
const std::string &c1,
106+
const std::string &c2) {
107+
auto f = str.find(c1);
108+
if (f != std::string::npos) {
109+
return std::string(str).replace(f, c1.length(), c2);
110+
}
111+
return std::string(str);
112+
}
113+
104114
/**
105115
* Types may be wrapper in a chain of typedefs.
106116
* @return true if given type is of type T or is an alias for type T.

bindgen/ir/Function.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Parameter::Parameter(std::string name, std::shared_ptr<Type> type)
77
Function::Function(const std::string &name, std::vector<Parameter *> parameters,
88
std::shared_ptr<Type> retType, bool isVariadic)
99
: name(name), scalaName(name), parameters(std::move(parameters)),
10-
retType(retType), isVariadic(isVariadic) {}
10+
retType(std::move(retType)), isVariadic(isVariadic) {}
1111

1212
llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Function &func) {
1313
if (func.scalaName != func.name) {

bindgen/ir/IR.cpp

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ void IR::addFunction(std::string name, std::vector<Parameter *> parameters,
1212
retType, isVariadic));
1313
}
1414

15-
void IR::addTypeDef(std::string name, std::shared_ptr<Type> type) {
15+
std::shared_ptr<TypeDef> IR::addTypeDef(std::string name,
16+
std::shared_ptr<Type> type) {
1617
typeDefs.push_back(std::make_shared<TypeDef>(std::move(name), type));
18+
return typeDefs.back();
1719
}
1820

1921
std::shared_ptr<Type> IR::addEnum(std::string name, const std::string &type,
@@ -28,23 +30,32 @@ std::shared_ptr<Type> IR::addEnum(std::string name, const std::string &type,
2830
return nullptr;
2931
}
3032

31-
std::shared_ptr<Type> IR::addStruct(std::string name,
32-
std::vector<Field *> fields,
33-
uint64_t typeSize) {
33+
void IR::addStruct(std::string name, std::vector<Field *> fields,
34+
uint64_t typeSize) {
3435
std::shared_ptr<Struct> s =
35-
std::make_shared<Struct>(std::move(name), std::move(fields), typeSize);
36+
std::make_shared<Struct>(name, std::move(fields), typeSize);
3637
structs.push_back(s);
37-
typeDefs.push_back(s->generateTypeDef());
38-
return typeDefs.back();
38+
std::shared_ptr<TypeDef> typeDef = getTypeDefWithName("struct_" + name);
39+
if (typeDef) {
40+
/* the struct type used to be opaque type, typeDef contains nullptr */
41+
typeDef.get()->setType(s);
42+
} else {
43+
typeDefs.push_back(s->generateTypeDef());
44+
}
3945
}
4046

41-
std::shared_ptr<Type>
42-
IR::addUnion(std::string name, std::vector<Field *> fields, uint64_t maxSize) {
47+
void IR::addUnion(std::string name, std::vector<Field *> fields,
48+
uint64_t maxSize) {
4349
std::shared_ptr<Union> u =
44-
std::make_shared<Union>(std::move(name), std::move(fields), maxSize);
50+
std::make_shared<Union>(name, std::move(fields), maxSize);
4551
unions.push_back(u);
46-
typeDefs.push_back(u->generateTypeDef());
47-
return typeDefs.back();
52+
std::shared_ptr<TypeDef> typeDef = getTypeDefWithName("union_" + name);
53+
if (typeDef) {
54+
/* the union type used to be opaque type, typeDef contains nullptr */
55+
typeDef.get()->setType(u);
56+
} else {
57+
typeDefs.push_back(u->generateTypeDef());
58+
}
4859
}
4960

5061
void IR::addLiteralDefine(std::string name, std::string literal,
@@ -304,6 +315,11 @@ std::shared_ptr<Variable> IR::addVariable(const std::string &name,
304315
}
305316

306317
std::shared_ptr<TypeDef> IR::getTypeDefWithName(const std::string &name) {
318+
/* nullptr is returned in 2 cases:
319+
* 1. TypeTranslator translates opaque struct/union type for which TypeDef
320+
* was not created.
321+
* 2. TreeVisitor visits struct/union declaration and it checks whether a
322+
* TypeDef already exists for it.*/
307323
return getDeclarationWithName(typeDefs, name);
308324
}
309325

@@ -317,7 +333,6 @@ T IR::getDeclarationWithName(std::vector<T> &declarations,
317333
return declaration;
318334
}
319335
}
320-
llvm::errs() << "Failed to get declaration for " << name << "\n";
321336
return nullptr;
322337
}
323338

@@ -331,4 +346,4 @@ IR::~IR() {
331346
possibleVarDefines.clear();
332347
variables.clear();
333348
varDefines.clear();
334-
}
349+
}

bindgen/ir/IR.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,20 @@ class IR {
2222
void addFunction(std::string name, std::vector<Parameter *> parameters,
2323
std::shared_ptr<Type> retType, bool isVariadic);
2424

25-
void addTypeDef(std::string name, std::shared_ptr<Type> type);
25+
std::shared_ptr<TypeDef> addTypeDef(std::string name,
26+
std::shared_ptr<Type> type);
2627

2728
/**
2829
* @return type alias for the enum
2930
*/
3031
std::shared_ptr<Type> addEnum(std::string name, const std::string &type,
3132
std::vector<Enumerator> enumerators);
3233

33-
/**
34-
* @return type alias for the struct
35-
*/
36-
std::shared_ptr<Type>
37-
addStruct(std::string name, std::vector<Field *> fields, uint64_t typeSize);
34+
void addStruct(std::string name, std::vector<Field *> fields,
35+
uint64_t typeSize);
3836

39-
/**
40-
* @return type alias for the union
41-
*/
42-
std::shared_ptr<Type>
43-
addUnion(std::string name, std::vector<Field *> fields, uint64_t maxSize);
37+
void addUnion(std::string name, std::vector<Field *> fields,
38+
uint64_t maxSize);
4439

4540
void addLiteralDefine(std::string name, std::string literal,
4641
std::shared_ptr<Type> type);
@@ -138,8 +133,6 @@ class IR {
138133
T getDeclarationWithName(std::vector<T> &declarations,
139134
const std::string &name);
140135

141-
template <typename T> void clearVector(std::vector<T> v);
142-
143136
std::string libName; // name of the library
144137
std::string linkName; // name of the library to link with
145138
std::string objectName; // name of Scala object

bindgen/ir/Struct.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include "types/ArrayType.h"
44
#include "types/PrimitiveType.h"
55
#include <sstream>
6-
#include <utility>
76

87
Field::Field(std::string name, std::shared_ptr<Type> type)
98
: TypeAndName(std::move(name), std::move(type)) {}

bindgen/ir/TypeAndName.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include <clang/Tooling/Tooling.h>
33

44
TypeAndName::TypeAndName(std::string name, std::shared_ptr<Type> type)
5-
: name(std::move(name)), type(type) {}
5+
: name(std::move(name)), type(std::move(type)) {}
66

77
std::shared_ptr<Type> TypeAndName::getType() const { return type; }
88

bindgen/ir/TypeDef.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@
22
#include "../Utils.h"
33

44
TypeDef::TypeDef(std::string name, std::shared_ptr<Type> type)
5-
: TypeAndName(std::move(name), type) {}
5+
: TypeAndName(std::move(name), std::move(type)) {}
66

77
llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const TypeDef &typeDef) {
8+
if (!typeDef.getType()) {
9+
llvm::errs() << "Error: type declaration for " << typeDef.getName()
10+
<< " was not found.\n";
11+
llvm::errs().flush();
12+
return s;
13+
}
814
s << " type " + handleReservedWords(typeDef.name) + " = " +
915
typeDef.getType()->str() + "\n";
1016
return s;

bindgen/ir/types/ArrayType.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include "../../Utils.h"
33

44
ArrayType::ArrayType(std::shared_ptr<Type> elementsType, uint64_t size)
5-
: size(size), elementsType(elementsType) {}
5+
: size(size), elementsType(std::move(elementsType)) {}
66

77
std::string ArrayType::str() const {
88
return "native.CArray[" + elementsType->str() + ", " +
@@ -12,5 +12,3 @@ std::string ArrayType::str() const {
1212
bool ArrayType::usesType(std::shared_ptr<Type> type) const {
1313
return this == type.get() || elementsType == type;
1414
}
15-
16-
ArrayType::~ArrayType() {}

bindgen/ir/types/ArrayType.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class ArrayType : public Type {
77
public:
88
ArrayType(std::shared_ptr<Type> elementsType, uint64_t size);
99

10-
~ArrayType() override;
10+
~ArrayType() override = default;
1111

1212
bool usesType(std::shared_ptr<Type> type) const override;
1313

bindgen/ir/types/FunctionPointerType.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
FunctionPointerType::FunctionPointerType(
55
std::shared_ptr<Type> returnType,
66
const std::vector<std::shared_ptr<Type>> &parametersTypes, bool isVariadic)
7-
: returnType(returnType), parametersTypes(parametersTypes),
7+
: returnType(std::move(returnType)), parametersTypes(parametersTypes),
88
isVariadic(isVariadic) {}
99

1010
std::string FunctionPointerType::str() const {
@@ -30,12 +30,10 @@ bool FunctionPointerType::usesType(std::shared_ptr<Type> type) const {
3030
return true;
3131
}
3232

33-
for (auto parameterType : parametersTypes) {
33+
for (const auto &parameterType : parametersTypes) {
3434
if (parameterType == type) {
3535
return true;
3636
}
3737
}
3838
return false;
3939
}
40-
41-
FunctionPointerType::~FunctionPointerType() {}

bindgen/ir/types/FunctionPointerType.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class FunctionPointerType : public Type {
1111
const std::vector<std::shared_ptr<Type>> &parametersTypes,
1212
bool isVariadic);
1313

14-
~FunctionPointerType() override;
14+
~FunctionPointerType() override = default;
1515

1616
bool usesType(std::shared_ptr<Type> type) const override;
1717

bindgen/ir/types/PointerType.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "PointerType.h"
22

3-
PointerType::PointerType(std::shared_ptr<Type> type) : type(type) {}
3+
PointerType::PointerType(std::shared_ptr<Type> type) : type(std::move(type)) {}
44

55
std::string PointerType::str() const {
66
return "native.Ptr[" + type->str() + "]";
@@ -12,5 +12,3 @@ bool PointerType::usesType(std::shared_ptr<Type> type) const {
1212
}
1313
return this->type == type;
1414
}
15-
16-
PointerType::~PointerType() {}

bindgen/ir/types/PointerType.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class PointerType : public Type {
77
public:
88
explicit PointerType(std::shared_ptr<Type> type);
99

10-
~PointerType() override;
10+
~PointerType() override = default;
1111

1212
bool usesType(std::shared_ptr<Type> type) const override;
1313

bindgen/ir/types/Type.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,3 @@
33
std::string Type::str() const { return ""; }
44

55
bool Type::usesType(std::shared_ptr<Type> type) const { return false; }
6-
7-
Type::~Type() = default;

bindgen/ir/types/Type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010
class Type {
1111
public:
12-
virtual ~Type();
12+
virtual ~Type() = default;
1313

1414
virtual std::string str() const;
1515

0 commit comments

Comments
 (0)