Skip to content

Commit 4d30963

Browse files
authored
Merge pull request #68 from kornilova-l/store-types-in-ir
Store types in ir
2 parents 15a89db + 5ae0664 commit 4d30963

40 files changed

+766
-432
lines changed

bindgen/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ add_executable(bindgen
5454
ir/Variable.h
5555
ir/PossibleVarDefine.cpp
5656
ir/PossibleVarDefine.h
57+
ir/types/Type.cpp
58+
ir/types/Type.h
59+
ir/types/PrimitiveType.cpp
60+
ir/types/PrimitiveType.h
61+
ir/types/PointerType.cpp
62+
ir/types/PointerType.h
63+
ir/types/FunctionPointerType.cpp
64+
ir/types/FunctionPointerType.h
65+
ir/types/ArrayType.cpp
66+
ir/types/ArrayType.h
5767
)
5868

5969
set_target_properties(bindgen

bindgen/CycleDetection.h

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,35 @@ class CycleDetection {
1010
private:
1111
TypeTranslator &tpeTransl;
1212

13-
bool contains(std::string &k) { return !!dependencies.count(k); }
13+
bool contains(const std::string &k) const {
14+
return dependencies.count(k) != 0;
15+
}
1416

1517
public:
1618
std::map<std::string, std::set<std::string>> dependencies;
17-
CycleDetection(TypeTranslator &tpeTransl_)
19+
20+
explicit CycleDetection(TypeTranslator &tpeTransl_)
1821
: tpeTransl(tpeTransl_), dependencies{} {}
1922

20-
void AddDependcy(std::string name, const clang::QualType &qtpe) {
23+
void AddDependency(const std::string &name, const clang::QualType &qtpe) {
2124

22-
// TODO: function pointer
25+
if (qtpe->isFunctionPointerType()) {
26+
// TODO: function pointer
27+
/* type translator cannot translate function type */
28+
return;
29+
}
2330

2431
if (qtpe->isPointerType()) {
25-
const clang::PointerType *ptr =
26-
qtpe.getTypePtr()->getAs<clang::PointerType>();
27-
AddDependcy(name, ptr->getPointeeType());
32+
const auto *ptr = qtpe.getTypePtr()->getAs<clang::PointerType>();
33+
AddDependency(name, ptr->getPointeeType());
2834
return;
2935
}
3036

31-
std::string qtpeString = tpeTransl.Translate(qtpe);
37+
Type *type = tpeTransl.translate(qtpe);
38+
std::string qtpeString = type->str();
39+
if (type->canBeDeallocated()) {
40+
delete type;
41+
}
3242

3343
// Add the dependence of qtpe
3444
if (contains(qtpeString)) {
@@ -39,7 +49,7 @@ class CycleDetection {
3949
dependencies[name].insert(qtpeString);
4050
}
4151

42-
bool isCyclic(std::string &name) {
52+
bool isCyclic(const std::string &name) {
4353
if (contains(name)) {
4454
if (dependencies[name].count(name) != 0) {
4555
return true;

bindgen/TypeTranslator.cpp

Lines changed: 65 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#include "TypeTranslator.h"
22
#include "Utils.h"
3+
#include "ir/types/FunctionPointerType.h"
4+
#include "ir/types/PointerType.h"
35

4-
TypeTranslator::TypeTranslator(clang::ASTContext *ctx_) : ctx(ctx_), typeMap() {
6+
TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir)
7+
: ctx(ctx_), ir(ir), typeMap() {
58

69
// Native Types
710
typeMap["void"] = "Unit";
@@ -27,38 +30,24 @@ TypeTranslator::TypeTranslator(clang::ASTContext *ctx_) : ctx(ctx_), typeMap() {
2730
typeMap["char32_t"] = "native.CChar32";
2831
typeMap["float"] = "native.CFloat";
2932
typeMap["double"] = "native.CDouble";
30-
typeMap["void*"] = "native.Ptr[Byte]";
3133
}
3234

33-
std::string
34-
TypeTranslator::TranslateFunctionPointer(const clang::QualType &qtpe,
35-
const std::string *avoid) {
36-
const clang::PointerType *ptr =
37-
qtpe.getTypePtr()->getAs<clang::PointerType>();
35+
Type *TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe,
36+
const std::string *avoid) {
37+
const auto *ptr = qtpe.getTypePtr()->getAs<clang::PointerType>();
3838
const clang::QualType &inner = ptr->getPointeeType();
3939

4040
if (inner->isFunctionProtoType()) {
41-
const clang::FunctionProtoType *fc =
42-
inner->getAs<clang::FunctionProtoType>();
43-
std::string ret = Translate(fc->getReturnType(), avoid);
44-
std::string params = "";
45-
int counter = 0;
41+
const auto *fc = inner->getAs<clang::FunctionProtoType>();
42+
Type *returnType = translate(fc->getReturnType(), avoid);
43+
std::vector<Type *> parametersTypes;
4644

4745
for (const clang::QualType &param : fc->param_types()) {
48-
params += Translate(param, avoid);
49-
params += ", ";
50-
counter++;
46+
parametersTypes.push_back(translate(param, avoid));
5147
}
5248

53-
std::string variad = "";
54-
55-
if (fc->isVariadic()) {
56-
counter++;
57-
variad = "native.CVararg, ";
58-
}
59-
60-
return std::string("native.CFunctionPtr") + std::to_string(counter) +
61-
"[" + params + variad + ret + "]";
49+
return new FunctionPointerType(returnType, parametersTypes,
50+
fc->isVariadic());
6251

6352
} else {
6453
llvm::errs() << "Unsupported function pointer type: "
@@ -68,111 +57,111 @@ TypeTranslator::TranslateFunctionPointer(const clang::QualType &qtpe,
6857
}
6958
}
7059

71-
std::string TypeTranslator::TranslatePointer(const clang::QualType &pte,
72-
const std::string *avoid) {
60+
Type *TypeTranslator::translatePointer(const clang::QualType &pte,
61+
const std::string *avoid) {
7362

7463
if (pte->isBuiltinType()) {
7564
const clang::BuiltinType *as = pte->getAs<clang::BuiltinType>();
7665

7766
// Take care of void*
7867
if (as->getKind() == clang::BuiltinType::Void) {
79-
return "native.Ptr[Byte]";
68+
return new PointerType(new PrimitiveType("Byte"));
8069
}
8170

8271
// Take care of char*
8372
if (as->getKind() == clang::BuiltinType::Char_S ||
8473
as->getKind() == clang::BuiltinType::SChar) {
85-
return "native.CString";
74+
// TODO: new PointerType(new PrimitiveType("native.CChar"))
75+
return new PrimitiveType("native.CString");
8676
}
8777
}
8878

89-
return std::string("native.Ptr[") + Translate(pte, avoid) +
90-
std::string("]");
79+
return new PointerType(translate(pte, avoid));
9180
}
9281

93-
std::string
94-
TypeTranslator::TranslateStructOrUnion(const clang::QualType &qtpe) {
95-
if (qtpe->hasUnnamedOrLocalType()) {
96-
// TODO: Verify that the local part is not a problem
97-
uint64_t size = ctx->getTypeSize(qtpe);
98-
return "native.CArray[Byte, " + uint64ToScalaNat(size) + "]";
99-
}
100-
82+
Type *
83+
TypeTranslator::translateStructOrUnionOrEnum(const clang::QualType &qtpe) {
10184
std::string name = qtpe.getUnqualifiedType().getAsString();
10285

103-
// TODO: do it properly
104-
size_t f = name.find(std::string("struct __dirstream"));
105-
if (f != std::string::npos) {
106-
return std::string("native.CArray[Byte, Digit[_3, Digit[_2, _0]]]");
107-
}
108-
109-
f = name.find(" ");
110-
if (f != std::string::npos) {
111-
return name.replace(f, std::string(" ").length(), "_");
86+
auto it = aliasesMap.find(name);
87+
if (it != aliasesMap.end()) {
88+
/* name contains space: struct <name>.
89+
* Use type alias instead struct type */
90+
return (*it).second;
11291
}
113-
return name;
92+
/* type has typedef alias */
93+
return ir.getTypeDefWithName(name);
11494
}
11595

116-
std::string TypeTranslator::TranslateEnum(const clang::QualType &qtpe) {
117-
std::string name = qtpe.getUnqualifiedType().getAsString();
118-
size_t f = name.find(" ");
119-
if (f != std::string::npos) {
120-
return name.replace(f, std::string(" ").length(), "_");
96+
Type *TypeTranslator::translateStructOrUnion(const clang::QualType &qtpe) {
97+
if (qtpe->hasUnnamedOrLocalType()) {
98+
// TODO: Verify that the local part is not a problem
99+
uint64_t size = ctx->getTypeSize(qtpe);
100+
return new ArrayType(new PrimitiveType("Byte"), size);
121101
}
122-
return name;
102+
103+
return translateStructOrUnionOrEnum(qtpe);
123104
}
124105

125-
std::string
126-
TypeTranslator::TranslateConstantArray(const clang::ConstantArrayType *ar,
127-
const std::string *avoid) {
106+
Type *TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar,
107+
const std::string *avoid) {
128108
const uint64_t size = ar->getSize().getZExtValue();
129-
const std::string nat = uint64ToScalaNat(size);
130-
return "native.CArray[" + Translate(ar->getElementType(), avoid) + ", " +
131-
nat + "]";
109+
return new ArrayType(translate(ar->getElementType(), avoid), size);
132110
}
133111

134-
std::string TypeTranslator::Translate(const clang::QualType &qtpe,
135-
const std::string *avoid) {
112+
Type *TypeTranslator::translate(const clang::QualType &qtpe,
113+
const std::string *avoid) {
136114

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

139117
if (typeEquals(tpe, avoid)) {
140118
// This is a type that we want to avoid the usage.
141-
//Êxample: A struct that has a pointer to itself
119+
// Êxample: A struct that has a pointer to itself
142120
uint64_t size = ctx->getTypeSize(tpe);
143-
return "native.CArray[Byte, " + uint64ToScalaNat(size) + "]";
121+
return new ArrayType(new PrimitiveType("Byte"), size);
144122
}
145123

146124
if (tpe->isFunctionPointerType()) {
147-
return TranslateFunctionPointer(qtpe, avoid);
125+
return translateFunctionPointer(qtpe, avoid);
148126

149127
} else if (tpe->isPointerType()) {
150-
return TranslatePointer(
128+
return translatePointer(
151129
tpe->getAs<clang::PointerType>()->getPointeeType(), avoid);
152130

153-
} else if (qtpe->isStructureType() || qtpe->isUnionType()) {
154-
return handleReservedWords(TranslateStructOrUnion(qtpe));
131+
} else if (qtpe->isStructureType()) {
132+
return translateStructOrUnion(qtpe);
133+
134+
} else if (qtpe->isUnionType()) {
135+
return translateStructOrUnion(qtpe);
155136

156137
} else if (qtpe->isEnumeralType()) {
157-
return TranslateEnum(qtpe);
138+
return translateStructOrUnionOrEnum(qtpe);
158139

159140
} else if (qtpe->isConstantArrayType()) {
160-
return TranslateConstantArray(ctx->getAsConstantArrayType(qtpe), avoid);
141+
return translateConstantArray(ctx->getAsConstantArrayType(qtpe), avoid);
161142
} else if (qtpe->isArrayType()) {
162-
return TranslatePointer(ctx->getAsArrayType(qtpe)->getElementType(),
143+
return translatePointer(ctx->getAsArrayType(qtpe)->getElementType(),
163144
avoid);
164145
} else {
165146

166147
auto found = typeMap.find(qtpe.getUnqualifiedType().getAsString());
167148
if (found != typeMap.end()) {
168-
return handleReservedWords(found->second);
149+
return new PrimitiveType(found->second);
169150
} else {
170-
// TODO: Properly handle non-default types
171-
return handleReservedWords(qtpe.getUnqualifiedType().getAsString());
151+
return ir.getTypeDefWithName(
152+
qtpe.getUnqualifiedType().getAsString());
172153
}
173154
}
174155
}
175156

176-
void TypeTranslator::AddTranslation(std::string from, std::string to) {
177-
typeMap[from] = to;
157+
void TypeTranslator::addAlias(std::string cName, Type *type) {
158+
aliasesMap[cName] = type;
159+
}
160+
161+
std::string TypeTranslator::getTypeFromTypeMap(std::string cType) {
162+
auto it = typeMap.find(cType);
163+
if (it != typeMap.end()) {
164+
return (*it).second;
165+
}
166+
return "";
178167
}

bindgen/TypeTranslator.h

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
#pragma once
22

3-
#include <clang/AST/AST.h>
4-
#include <clang/AST/ASTContext.h>
3+
#include "ir/IR.h"
54
#include <clang/Tooling/Tooling.h>
65

76
class TypeTranslator {
8-
private:
9-
clang::ASTContext *ctx;
10-
std::map<std::string, std::string> typeMap;
11-
127
public:
13-
explicit TypeTranslator(clang::ASTContext *ctx);
14-
void AddTranslation(std::string from, std::string to);
8+
TypeTranslator(clang::ASTContext *ctx, IR &ir);
159

1610
/**
1711
* @brief Translate the qualified type from c to a scala type
@@ -20,14 +14,36 @@ class TypeTranslator {
2014
* structs, unions, ...
2115
* @return the type translated
2216
*/
23-
std::string Translate(const clang::QualType &tpe,
24-
const std::string * = nullptr);
25-
std::string TranslateFunctionPointer(const clang::QualType &qtpe,
26-
const std::string *avoid);
27-
std::string TranslatePointer(const clang::QualType &pointee,
17+
Type *translate(const clang::QualType &tpe, const std::string * = nullptr);
18+
19+
void addAlias(std::string cName, Type *type);
20+
21+
std::string getTypeFromTypeMap(std::string cType);
22+
23+
private:
24+
clang::ASTContext *ctx;
25+
IR &ir;
26+
27+
/**
28+
* Primitive types
29+
*/
30+
std::map<std::string, std::string> typeMap;
31+
32+
/**
33+
* Maps C struct, union or enum name to Type alias
34+
*/
35+
std::map<std::string, Type *> aliasesMap;
36+
37+
Type *translateStructOrUnionOrEnum(const clang::QualType &qtpe);
38+
39+
Type *translateStructOrUnion(const clang::QualType &qtpe);
40+
41+
Type *translateFunctionPointer(const clang::QualType &qtpe,
42+
const std::string *avoid);
43+
44+
Type *translatePointer(const clang::QualType &pointee,
45+
const std::string *avoid);
46+
47+
Type *translateConstantArray(const clang::ConstantArrayType *ar,
2848
const std::string *avoid);
29-
std::string TranslateStructOrUnion(const clang::QualType &qtpe);
30-
std::string TranslateEnum(const clang::QualType &qtpe);
31-
std::string TranslateConstantArray(const clang::ConstantArrayType *ar,
32-
const std::string *avoid);
3349
};

bindgen/Utils.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <clang/AST/AST.h>
55

6+
#include "ir/types/Type.h"
67
#include <algorithm>
78
#include <cctype>
89
#include <cinttypes>
@@ -94,15 +95,4 @@ static inline bool startsWith(const std::string &str,
9495
return str.substr(0, prefix.size()) == prefix;
9596
}
9697

97-
/**
98-
* @return true if checkedType uses type
99-
* example: checkedType = native.Ptr[struct_A], type = struct_A
100-
*/
101-
static inline bool typeUsesOtherType(const std::string &checkedType,
102-
const std::string &type) {
103-
// TODO: find better way to check it
104-
return checkedType == type || checkedType == "native.Ptr[" + type + "]" ||
105-
startsWith(checkedType, "native.CArray[" + type + ", ");
106-
}
107-
10898
#endif // UTILS_H

0 commit comments

Comments
 (0)