Skip to content

Commit a2b6cb5

Browse files
kornilova203jonas
authored andcommittedJun 7, 2018
Fix #3: Filter private functions and typedefs (#25)
1 parent 86d9bb3 commit a2b6cb5

File tree

16 files changed

+341
-23
lines changed

16 files changed

+341
-23
lines changed
 

‎Main.cpp

+10-9
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22
#include <clang/Tooling/CommonOptionsParser.h>
33

44

5-
static llvm::cl::OptionCategory Category("Binding Generator");
6-
static llvm::cl::extrahelp CommonHelp(clang::tooling::CommonOptionsParser::HelpMessage);
7-
static llvm::cl::extrahelp MoreHelp("\nProduce Bindings for scala native. Please specify lib name wit parameter name\n");
8-
static llvm::cl::opt<std::string> LibName("name", llvm::cl::cat(Category));
9-
static llvm::cl::opt<std::string> StdHeaders("stdHeaders", llvm::cl::cat(Category));
10-
static llvm::cl::opt<bool> PrintHeadersLocation ("location", llvm::cl::cat(Category));
11-
12-
135
int main(int argc, char *argv[]) {
6+
llvm::cl::OptionCategory Category("Binding Generator");
7+
llvm::cl::extrahelp CommonHelp(clang::tooling::CommonOptionsParser::HelpMessage);
8+
llvm::cl::extrahelp MoreHelp("\nProduce Bindings for scala native. Please specify lib name with parameter name\n");
9+
10+
llvm::cl::opt<std::string> LibName("name", llvm::cl::cat(Category));
11+
llvm::cl::opt<std::string> StdHeaders("std-headers", llvm::cl::cat(Category));
12+
llvm::cl::opt<bool> PrintHeadersLocation("location", llvm::cl::cat(Category));
13+
llvm::cl::opt<std::string> ExcludePrefix("exclude-prefix", llvm::cl::cat(Category));
14+
1415
clang::tooling::CommonOptionsParser op(argc, (const char**)argv, Category);
1516
clang::tooling::ClangTool Tool(op.getCompilations(), op.getSourcePathList());
1617

@@ -40,7 +41,7 @@ int main(int argc, char *argv[]) {
4041
llvm::outs() << location.c_str();
4142
}
4243
} else {
43-
ir.generate();
44+
ir.generate(ExcludePrefix.getValue());
4445
llvm::outs() << ir;
4546
}
4647
llvm::outs().flush();

‎Utils.h

+18
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,23 @@ static inline void trim(std::string &s) {
7979
rtrim(s);
8080
}
8181

82+
/**
83+
* @return true if str starts with given prefix
84+
*/
85+
static inline bool startsWith(const std::string &str, const std::string &prefix) {
86+
return str.substr(0, prefix.size()) == prefix;
87+
}
88+
89+
/**
90+
* @return true if checkedType uses type
91+
* example: checkedType = native.Ptr[struct_A], type = struct_A
92+
*/
93+
static inline bool typeUsesOtherType(const std::string &checkedType, const std::string &type) {
94+
// TODO: find better way to check it
95+
return checkedType == type ||
96+
checkedType == "native.Ptr[" + type + "]" ||
97+
startsWith(checkedType, "native.CArray[" + type + ", ");
98+
}
99+
82100

83101
#endif // UTILS_H

‎ir/Function.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,19 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Function &func) {
3030
<< " = native.extern\n";
3131
return s;
3232
}
33+
34+
bool Function::usesType(const std::string &type) const {
35+
if (typeUsesOtherType(retType, type)) {
36+
return true;
37+
}
38+
for (const auto &parameter : parameters) {
39+
if (typeUsesOtherType(parameter.getType(), type)) {
40+
return true;
41+
}
42+
}
43+
return false;
44+
}
45+
46+
std::string Function::getName() const {
47+
return name;
48+
}

‎ir/Function.h

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ class Function {
1919

2020
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Function &func);
2121

22+
bool usesType(const std::string &type) const;
23+
24+
std::string getName() const;
25+
2226
private:
2327
std::string name;
2428
std::vector<Parameter> parameters;

‎ir/IR.cpp

+61-1
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,9 @@ void IR::generateTypeDefs() {
113113
}
114114
}
115115

116-
void IR::generate() {
116+
void IR::generate(const std::string &excludePrefix) {
117117
if (!generated) {
118+
filterDeclarations(excludePrefix);
118119
generateTypeDefs();
119120
generated = true;
120121
}
@@ -137,3 +138,62 @@ bool IR::hasHelperMethods() const {
137138
bool IR::hasEnums() const {
138139
return !enums.empty();
139140
}
141+
142+
void IR::filterDeclarations(const std::string &excludePrefix) {
143+
if (excludePrefix.empty()) {
144+
return;
145+
}
146+
147+
filterTypeDefs(excludePrefix);
148+
149+
filterFunctions(excludePrefix);
150+
}
151+
152+
void IR::filterTypeDefs(const std::string &excludePrefix) {
153+
for (auto it = typeDefs.begin(); it != typeDefs.end();) {
154+
TypeDef &typeDef = *it;
155+
if (startsWith(typeDef.getName(), excludePrefix) &&
156+
typeIsUsedOnlyInTypeDefs(typeDef.getName())) {
157+
/* remove this typedef and replace aliases with actual type */
158+
replaceTypeInTypeDefs(typeDef.getName(), typeDef.getType());
159+
it = typeDefs.erase(it);
160+
} else {
161+
++it;
162+
}
163+
}
164+
}
165+
166+
void IR::replaceTypeInTypeDefs(const std::string &oldType, const std::string &newType) {
167+
for (auto &typeDef : typeDefs) {
168+
if (typeDef.getType() == oldType) {
169+
typeDef.setType(newType);
170+
}
171+
}
172+
}
173+
174+
void IR::filterFunctions(const std::string &excludePrefix) {
175+
for (auto it = functions.begin(); it != functions.end();) {
176+
Function &function = *it;
177+
if (startsWith(function.getName(), excludePrefix)) {
178+
it = functions.erase(it);
179+
} else {
180+
it++;
181+
}
182+
}
183+
}
184+
185+
template<typename T>
186+
bool IR::isTypeUsed(const std::vector<T> &declarations, const std::string &type) {
187+
for (const auto &decl : declarations) {
188+
if (decl.usesType(type)) {
189+
return true;
190+
}
191+
}
192+
return false;
193+
}
194+
195+
bool IR::typeIsUsedOnlyInTypeDefs(std::string type) {
196+
return !(isTypeUsed(functions, type) ||
197+
isTypeUsed(structs, type) ||
198+
isTypeUsed(unions, type));
199+
}

‎ir/IR.h

+48-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class IR {
3535

3636
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir);
3737

38-
void generate();
38+
void generate(const std::string &excludePrefix);
3939

4040
private:
4141

@@ -49,6 +49,53 @@ class IR {
4949
*/
5050
bool hasHelperMethods() const;
5151

52+
/**
53+
* Remove functions that start with given prefix.
54+
*
55+
* Replace typedef by underlying type if it starts with given prefix
56+
* and it is used only in other typedefs.
57+
*
58+
* Example:
59+
* @code
60+
* type __int32_t = native.CInt
61+
* type __darwin_pid_t = __int32_t
62+
* type pid_t = __darwin_pid_t
63+
* @endcode
64+
*
65+
* Becomes:
66+
* @code
67+
* type pid_t = native.CInt
68+
* @endcode
69+
*
70+
*/
71+
void filterDeclarations(const std::string &excludePrefix);
72+
73+
/**
74+
* Remove all typedefs that start with given prefix.
75+
*/
76+
void filterTypeDefs(const std::string &excludePrefix);
77+
78+
/**
79+
* Find all typedefs that use oldType and replace it with newType.
80+
*/
81+
void replaceTypeInTypeDefs(const std::string &oldType, const std::string &newType);
82+
83+
/**
84+
* Remove functions with names that start with excludePrefix.
85+
*/
86+
void filterFunctions(const std::string &excludePrefix);
87+
88+
/**
89+
* @return true if given type is used only in typedefs.
90+
*/
91+
bool typeIsUsedOnlyInTypeDefs(std::string type);
92+
93+
/**
94+
* @return true if type is used in one of given declarations.
95+
*/
96+
template<typename T>
97+
bool isTypeUsed(const std::vector<T> &declarations, const std::string &type);
98+
5299
std::string libName;
53100
std::vector<Function> functions;
54101
std::vector<TypeDef> typeDefs;

‎ir/Struct.cpp

+29-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@ Field::Field(std::string name, std::string type)
88
StructOrUnion::StructOrUnion(std::string name, std::vector<Field> fields)
99
: name(std::move(name)), fields(std::move(fields)) {}
1010

11+
std::string StructOrUnion::getName() const {
12+
return name;
13+
}
14+
15+
bool StructOrUnion::usesType(const std::string &type) const {
16+
for (const auto &field : fields) {
17+
if (typeUsesOtherType(field.getType(), type)) {
18+
return true;
19+
}
20+
}
21+
return false;
22+
}
23+
1124
Struct::Struct(std::string name, std::vector<Field> fields, uint64_t typeSize)
1225
: StructOrUnion(std::move(name), std::move(fields)), typeSize(typeSize) {}
1326

@@ -38,8 +51,8 @@ std::string Struct::generateHelperClass() const {
3851
return "";
3952
}
4053
std::stringstream s;
41-
std::string newName = "struct_" + name;
42-
s << " implicit class " << newName << "_ops(val p: native.Ptr[struct_" << name << "])"
54+
std::string type = getType();
55+
s << " implicit class " << type << "_ops(val p: native.Ptr[" << type << "])"
4356
<< " extends AnyVal {\n";
4457
int fieldIndex = 0;
4558
for (const auto &field : fields) {
@@ -56,8 +69,8 @@ std::string Struct::generateHelperClass() const {
5669
s << " }\n\n";
5770

5871
/* makes struct instantiation easier */
59-
s << " def " << newName + "()(implicit z: native.Zone): native.Ptr[" + newName + "]"
60-
<< " = native.alloc[" + newName + "]\n";
72+
s << " def " << type + "()(implicit z: native.Zone): native.Ptr[" + type + "]"
73+
<< " = native.alloc[" + type + "]\n";
6174

6275
return s.str();
6376
}
@@ -66,18 +79,23 @@ bool Struct::hasHelperMethods() const {
6679
return !fields.empty() && fields.size() < SCALA_NATIVE_MAX_STRUCT_FIELDS;
6780
}
6881

82+
std::string Struct::getType() const {
83+
return "struct_" + name;
84+
}
85+
6986
Union::Union(std::string name,
7087
std::vector<Field> members, uint64_t maxSize)
7188
: StructOrUnion(std::move(name), std::move(members)), maxSize(maxSize) {}
7289

7390
TypeDef Union::generateTypeDef() const {
74-
return TypeDef("union_" + name, "native.CArray[Byte, " + uint64ToScalaNat(maxSize) + "]");
91+
return TypeDef(getType(), "native.CArray[Byte, " + uint64ToScalaNat(maxSize) + "]");
7592
}
7693

7794
std::string Union::generateHelperClass() const {
7895
std::stringstream s;
79-
s << " implicit class union_" << name << "_pos"
80-
<< "(val p: native.Ptr[union_" << name << "]) extends AnyVal {\n";
96+
std::string type = getType();
97+
s << " implicit class " << type << "_pos"
98+
<< "(val p: native.Ptr[" << type << "]) extends AnyVal {\n";
8199
for (const auto &field : fields) {
82100
if (!field.getName().empty()) {
83101
std::string getter = handleReservedWords(field.getName());
@@ -93,3 +111,7 @@ std::string Union::generateHelperClass() const {
93111
s << " }\n";
94112
return s.str();
95113
}
114+
115+
std::string Union::getType() const {
116+
return "union_" + name;
117+
}

‎ir/Struct.h

+15-2
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,30 @@ class StructOrUnion {
2121

2222
virtual std::string generateHelperClass() const = 0;
2323

24+
std::string getName() const;
25+
26+
virtual std::string getType() const = 0;
27+
28+
/**
29+
* @return true if at leas one field has given type
30+
*/
31+
bool usesType(const std::string &type) const;
32+
2433
protected:
2534
std::string name; // names of structs and unions are not empty
2635
std::vector<Field> fields;
2736
};
2837

29-
class Struct : StructOrUnion {
38+
class Struct : public StructOrUnion {
3039
public:
3140
Struct(std::string name, std::vector<Field> fields, uint64_t typeSize);
3241

3342
TypeDef generateTypeDef() const override;
3443

3544
std::string generateHelperClass() const override;
3645

46+
std::string getType() const override;
47+
3748
/**
3849
* @return true if helper methods will be generated for this struct
3950
*/
@@ -46,14 +57,16 @@ class Struct : StructOrUnion {
4657
uint64_t typeSize;
4758
};
4859

49-
class Union : StructOrUnion {
60+
class Union : public StructOrUnion {
5061
public:
5162
Union(std::string name, std::vector<Field> members, uint64_t maxSize);
5263

5364
TypeDef generateTypeDef() const override;
5465

5566
std::string generateHelperClass() const override;
5667

68+
std::string getType() const override;
69+
5770
private:
5871
uint64_t maxSize;
5972
};

‎ir/TypeAndName.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ std::string TypeAndName::getType() const {
1010
std::string TypeAndName::getName() const {
1111
return name;
1212
}
13+
14+
void TypeAndName::setType(std::string type) {
15+
this->type = std::move(type);
16+
}

‎ir/TypeAndName.h

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class TypeAndName {
1414

1515
std::string getType() const;
1616

17+
void setType(std::string name);
18+
1719
std::string getName() const;
1820

1921
protected:

‎ir/TypeDef.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const TypeDef &typeDef) {
88
s << " type " + handleReservedWords(typeDef.name) + " = " + typeDef.getType() + "\n";
99
return s;
1010
}
11+
12+
bool TypeDef::usesType(const std::string &type) const {
13+
return typeUsesOtherType(this->type, type);
14+
}

‎ir/TypeDef.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
#include <llvm/Support/raw_ostream.h>
88

99

10-
class TypeDef : TypeAndName {
10+
class TypeDef : public TypeAndName {
1111
public:
1212
TypeDef(std::string name, std::string type);
1313

1414
friend llvm::raw_ostream &operator <<(llvm::raw_ostream &s, const TypeDef &type);
15+
16+
bool usesType(const std::string &type) const;
1517
};
1618

1719

0 commit comments

Comments
 (0)