Skip to content

Commit d08f23d

Browse files
committed
Split main file into cpp and header
1 parent bdb5f9b commit d08f23d

File tree

4 files changed

+207
-196
lines changed

4 files changed

+207
-196
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS support)
22

33
add_clang_executable(scalaBindgen
44
ScalaBindgen.cpp
5+
ScalaBindgen.h
56
TypeTranslator.h
67
TypeTranslator.cpp
78
HeaderManager.h

ScalaBindgen.cpp

Lines changed: 92 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -1,240 +1,133 @@
1-
#include "TypeTranslator.h"
2-
#include "HeaderManager.h"
3-
#include "Utils.h"
4-
5-
#include "clang/Driver/Options.h"
6-
#include "clang/Basic/LangOptions.h"
7-
#include "clang/AST/AST.h"
8-
#include "clang/AST/ASTContext.h"
9-
#include "clang/AST/ASTConsumer.h"
10-
#include "clang/AST/RecursiveASTVisitor.h"
11-
#include "clang/Frontend/ASTConsumers.h"
12-
#include "clang/Frontend/FrontendActions.h"
13-
#include "clang/Frontend/CompilerInstance.h"
14-
#include "clang/Tooling/CommonOptionsParser.h"
15-
#include "clang/Tooling/Tooling.h"
16-
#include "llvm/Support/CommandLine.h"
17-
18-
#include <iostream>
1+
#include "ScalaBindgen.h"
192

203
#define SCALA_NATIVE_MAX_STRUCT_FIELDS 22
214

225
static llvm::cl::OptionCategory Category("Binding Generator");
236
static llvm::cl::extrahelp CommonHelp(clang::tooling::CommonOptionsParser::HelpMessage);
247
static llvm::cl::extrahelp MoreHelp("\nProduce Bindings for scala native. Please specify lib name wit parameter name\n");
258
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+
2611

2712
HeaderManager headerMan;
2813

2914
std::string declarations;
3015
std::string enums;
3116

32-
class TreeVisitor : public clang::RecursiveASTVisitor<TreeVisitor> {
33-
private:
34-
clang::ASTContext* astContext;
35-
TypeTranslator typeTranslator;
36-
37-
public:
38-
explicit TreeVisitor(clang::CompilerInstance *CI) : astContext(&(CI->getASTContext())), typeTranslator(astContext) {}
39-
40-
virtual bool VisitFunctionDecl(clang::FunctionDecl *func) {
41-
std::string funcName = func->getNameInfo().getName().getAsString();
42-
std::string retType = typeTranslator.Translate(func->getReturnType());
43-
std::string params = "";
44-
45-
for (const clang::ParmVarDecl* parm : func->parameters()){
46-
//Handle default values
47-
std::string pname = parm->getNameAsString();
48-
if(pname == ""){
49-
pname = "anonymous";
50-
}
51-
params += pname;
52-
params += ": ";
53-
params += typeTranslator.Translate(parm->getType());
54-
params += ", ";
55-
}
56-
57-
//remove last ,
58-
if(params != ""){
59-
params = params.substr(0, params.size()-2);
60-
}
61-
62-
declarations += "\tdef " + funcName + "(" + params + "): " + retType + " = native.extern\n";
63-
return true;
17+
bool TreeVisitor::VisitFunctionDecl(clang::FunctionDecl *func) {
18+
std::string funcName = func->getNameInfo().getName().getAsString();
19+
std::string retType = typeTranslator.Translate(func->getReturnType());
20+
std::string params = "";
21+
22+
for (const clang::ParmVarDecl* parm : func->parameters()){
23+
//Handle default values
24+
std::string pname = parm->getNameAsString();
25+
if(pname == ""){
26+
pname = "anonymous";
27+
}
28+
params += pname;
29+
params += ": ";
30+
params += typeTranslator.Translate(parm->getType());
31+
params += ", ";
6432
}
6533

66-
virtual bool VisitTypedefDecl(clang::TypedefDecl *tpdef){
67-
std::string name = tpdef->getName();
68-
std::string tpe = typeTranslator.Translate(tpdef->getUnderlyingType());
69-
declarations += "\ttype " + name + " = " + tpe + "\n";
70-
return true;
34+
//remove last ,
35+
if(params != ""){
36+
params = params.substr(0, params.size()-2);
7137
}
7238

73-
virtual bool VisitEnumDecl(clang::EnumDecl *enumdecl){
74-
std::string name = enumdecl->getNameAsString();
39+
declarations += "\tdef " + funcName + "(" + params + "): " + retType + " = native.extern\n";
40+
return true;
41+
}
7542

76-
//Replace "enum x" with enum_x in scala
77-
typeTranslator.AddTranslation("enum " + name, "enum_" + name);
43+
bool TreeVisitor::VisitTypedefDecl(clang::TypedefDecl *tpdef){
44+
std::string name = tpdef->getName();
45+
std::string tpe = typeTranslator.Translate(tpdef->getUnderlyingType());
46+
declarations += "\ttype " + name + " = " + tpe + "\n";
47+
return true;
48+
}
7849

79-
if(name == "" && enumdecl->getTypedefNameForAnonDecl()){
80-
name = enumdecl->getTypedefNameForAnonDecl()->getNameAsString();
81-
}
50+
bool TreeVisitor::VisitEnumDecl(clang::EnumDecl *enumdecl){
51+
std::string name = enumdecl->getNameAsString();
8252

83-
if(name != ""){
84-
declarations += "\ttype enum_" + name + " = native.CInt\n";
85-
}
86-
87-
int i = 0;
88-
for (const clang::EnumConstantDecl* en : enumdecl->enumerators()){
89-
if(name != ""){
90-
enums += "\tfinal val enum_" + name + "_" + en->getNameAsString() + " = " + std::to_string(i++) + "\n";
91-
} else {
92-
enums += "\tfinal val enum_" + en->getNameAsString() + " = " + std::to_string(i++) + "\n";
93-
}
94-
}
53+
//Replace "enum x" with enum_x in scala
54+
typeTranslator.AddTranslation("enum " + name, "enum_" + name);
9555

96-
return true;
56+
if(name == "" && enumdecl->getTypedefNameForAnonDecl()){
57+
name = enumdecl->getTypedefNameForAnonDecl()->getNameAsString();
9758
}
9859

99-
virtual bool VisitRecordDecl(clang::RecordDecl *record){
100-
std::string name = record->getNameAsString();
60+
if(name != ""){
61+
declarations += "\ttype enum_" + name + " = native.CInt\n";
62+
}
10163

102-
//Handle typedef struct {} x; and typedef union {} y; by getting the name from the typedef
103-
if((record->isStruct() || record->isUnion()) && name == "" && record->getTypedefNameForAnonDecl()){
104-
name = record->getTypedefNameForAnonDecl()->getNameAsString();
64+
int i = 0;
65+
for (const clang::EnumConstantDecl* en : enumdecl->enumerators()){
66+
if(name != ""){
67+
enums += "\tfinal val enum_" + name + "_" + en->getNameAsString() + " = " + std::to_string(i++) + "\n";
68+
} else {
69+
enums += "\tfinal val enum_" + en->getNameAsString() + " = " + std::to_string(i++) + "\n";
10570
}
71+
}
10672

107-
if(record->isUnion() && !record->isAnonymousStructOrUnion() && name != ""){
108-
109-
//Replace "union x" with union_x in scala
110-
typeTranslator.AddTranslation("union " + name, "union" + name);
111-
112-
uint64_t maxSize = 0;
73+
return true;
74+
}
11375

114-
for(const clang::FieldDecl* field : record->fields()){
115-
maxSize = std::max(maxSize, astContext->getTypeSize(field->getType()));
116-
}
76+
bool TreeVisitor::VisitRecordDecl(clang::RecordDecl *record){
77+
std::string name = record->getNameAsString();
11778

118-
declarations += "\ttype union_" + name + " = native.CArray[Byte, " + intToScalaNat(maxSize) + "]\n";
79+
//Handle typedef struct {} x; and typedef union {} y; by getting the name from the typedef
80+
if((record->isStruct() || record->isUnion()) && name == "" && record->getTypedefNameForAnonDecl()){
81+
name = record->getTypedefNameForAnonDecl()->getNameAsString();
82+
}
11983

120-
return true;
84+
if(record->isUnion() && !record->isAnonymousStructOrUnion() && name != ""){
12185

122-
} else if (record->isStruct() && record->isThisDeclarationADefinition() && !record->isAnonymousStructOrUnion() && name != ""){
86+
//Replace "union x" with union_x in scala
87+
typeTranslator.AddTranslation("union " + name, "union" + name);
12388

124-
//Replace "struct x" with struct_x in scala
125-
typeTranslator.AddTranslation("struct " + name, "struct_"+name);
89+
uint64_t maxSize = 0;
12690

127-
int counter = 0;
128-
std::string fields = "";
91+
for(const clang::FieldDecl* field : record->fields()){
92+
maxSize = std::max(maxSize, astContext->getTypeSize(field->getType()));
93+
}
12994

130-
for(const clang::FieldDecl* field : record->fields()){
131-
fields += typeTranslator.Translate(field->getType(), &name) + ",";
132-
counter++;
133-
}
95+
declarations += "\ttype union_" + name + " = native.CArray[Byte, " + intToScalaNat(maxSize) + "]\n";
13496

135-
//remove last ,
136-
if(fields != ""){
137-
fields = fields.substr(0, fields.size()-1);
138-
}
97+
return true;
13998

140-
if(counter < SCALA_NATIVE_MAX_STRUCT_FIELDS){
141-
declarations += "\ttype struct_" + name + " = " + "native.CStruct" + std::to_string(counter) + "[" + fields + "]\n";
142-
} else {
143-
//There is no easy way to represent it as a struct in scala native, have to represent it as an array and then
144-
//Add helpers to help with it's manipulation
145-
uint64_t size = astContext->getTypeSize(record->getTypeForDecl());
146-
declarations += "\ttype struct_" + name + " = " + "native.CArray[Byte, " + uint64ToScalaNat(size) + "]\n";
147-
}
99+
} else if (record->isStruct() && record->isThisDeclarationADefinition() && !record->isAnonymousStructOrUnion() && name != ""){
148100

149-
return true;
150-
}
151-
return false;
152-
}
101+
//Replace "struct x" with struct_x in scala
102+
typeTranslator.AddTranslation("struct " + name, "struct_"+name);
153103

154-
};
155-
156-
157-
158-
class TreeConsumer : public clang::ASTConsumer {
159-
private:
160-
TreeVisitor *visitor;
161-
clang::SourceManager& smanager;
162-
163-
public:
164-
165-
std::vector<std::string> stdheaders{"assert.h","complex.h","ctype.h","errno.h","fenv.h","float.h","inttypes.h","iso646.h","limits.h",
166-
"locale.h","math.h","setjmp.h","signal.h","stdalign.h","stdarg.h","stdatomic.h","stdbool.h","stddef.h",
167-
"stdint.h","stdio.h","stdlib.h","stdnoreturn.h","string.h","tgmath.h","threads.h","time.h","uchar.h",
168-
"wchar.h","wctype.h","aio.h","inet.h","assert.h","complex.h","cpio.h","ctype.h","dirent.h","dlfcn.h",
169-
"errno.h","fcntl.h","fenv.h","float.h","fmtmsg.h","fnmatch.h","ftw.h","glob.h","grp.h","iconv.h",
170-
"inttypes.h","iso646.h","langinfo.h","libgen.h","limits.h","locale.h","math.h","monetary.h","mqueue.h",
171-
"ndbm.h","if.h","netdb.h","in.h","tcp.h","nl_types.h","poll.h","pthread.h","pwd.h",
172-
"regex.h","sched.h","search.h","semaphore.h","setjmp.h","signal.h","spawn.h","stdarg.h","stdbool.h",
173-
"stddef.h","stdint.h","stdio.h","stdlib.h","string.h","strings.h","stropts.h","ipc.h","mman.h",
174-
"msg.h","resource.h","select.h","sem.h","shm.h","socket.h","stat.h",
175-
"statvfs.h","time.h","times.h","types.h","uio.h","un.h","utsname.h",
176-
"wait.h","syslog.h","tar.h","termios.h","tgmath.h","time.h","trace.h","ulimit.h","unistd.h",
177-
"utime.h","utmpx.h","wchar.h","wctype.h","wordexp.h",
178-
179-
"siginfo.h", "sigset.h", "sigaction.h", "sigcontext.h", "sigthread.h", "ucontext.h",
180-
"pthreadtypes.h", "libio.h", "__stddef_max_align_t.h", "_G_config.h", "sys_errlist.h",
181-
"sysmacros.h", "xlocale.h", "socket_type.h", "sockaddr.h", "sigstack.h"
182-
};
183-
184-
/* with folders
185-
std::vector<std::string> stdheaders{"assert.h","complex.h","ctype.h","errno.h","fenv.h","float.h","inttypes.h","iso646.h","limits.h",
186-
"locale.h","math.h","setjmp.h","signal.h","stdalign.h","stdarg.h","stdatomic.h","stdbool.h","stddef.h",
187-
"stdint.h","stdio.h","stdlib.h","stdnoreturn.h","string.h","tgmath.h","threads.h","time.h","uchar.h",
188-
"wchar.h","wctype.h","aio.h","arpa/inet.h","assert.h","complex.h","cpio.h","ctype.h","dirent.h","dlfcn.h",
189-
"errno.h","fcntl.h","fenv.h","float.h","fmtmsg.h","fnmatch.h","ftw.h","glob.h","grp.h","iconv.h",
190-
"inttypes.h","iso646.h","langinfo.h","libgen.h","limits.h","locale.h","math.h","monetary.h","mqueue.h",
191-
"ndbm.h","net/if.h","netdb.h","netinet/in.h","netinet/tcp.h","nl_types.h","poll.h","pthread.h","pwd.h",
192-
"regex.h","sched.h","search.h","semaphore.h","setjmp.h","signal.h","spawn.h","stdarg.h","stdbool.h",
193-
"stddef.h","stdint.h","stdio.h","stdlib.h","string.h","strings.h","stropts.h","sys/ipc.h","sys/mman.h",
194-
"sys/msg.h","sys/resource.h","sys/select.h","sys/sem.h","sys/shm.h","sys/socket.h","sys/stat.h",
195-
"sys/statvfs.h","sys/time.h","sys/times.h","sys/types.h","sys/uio.h","sys/un.h","sys/utsname.h",
196-
"sys/wait.h","syslog.h","tar.h","termios.h","tgmath.h","time.h","trace.h","ulimit.h","unistd.h",
197-
"utime.h","utmpx.h","wchar.h","wctype.h","wordexp.h"};
198-
*/
199-
200-
explicit TreeConsumer(clang::CompilerInstance *CI) : visitor(new TreeVisitor(CI)), smanager(CI->getASTContext().getSourceManager()) {}
201-
202-
std::string basename(const std::string& pathname) {
203-
return {std::find_if(pathname.rbegin(), pathname.rend(),
204-
[](char c) { return c == '/'; }).base(),
205-
pathname.end()};
206-
}
104+
int counter = 0;
105+
std::string fields = "";
207106

208-
virtual bool HandleTopLevelDecl(clang::DeclGroupRef DG) {
209-
// a DeclGroupRef may have multiple Decls, so we iterate through each one
210-
for (clang::DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; i++) {
211-
clang::Decl *D = *i;
212-
std::string fpath = smanager.getFilename(D->getLocation()).str();
213-
if(std::find(stdheaders.begin(), stdheaders.end(), basename(fpath)) == stdheaders.end()){
214-
visitor->TraverseDecl(D); // recursively visit each AST node in Decl "D"
215-
}
107+
for(const clang::FieldDecl* field : record->fields()){
108+
fields += typeTranslator.Translate(field->getType(), &name) + ",";
109+
counter++;
216110
}
217-
return true;
218-
}
219-
220-
// this replaces "HandleTopLevelDecl"
221-
// override this to call our ExampleVisitor on the entire source file
222-
/*virtual void HandleTranslationUnit(clang::ASTContext &Context) {
223-
//we can use ASTContext to get the TranslationUnitDecl, which is
224-
//a single Decl that collectively represents the entire source file
225-
visitor->TraverseDecl(Context.getTranslationUnitDecl());
226-
}*/
227-
228-
};
229111

112+
//remove last ,
113+
if(fields != ""){
114+
fields = fields.substr(0, fields.size()-1);
115+
}
230116

117+
if(counter < SCALA_NATIVE_MAX_STRUCT_FIELDS){
118+
declarations += "\ttype struct_" + name + " = " + "native.CStruct" + std::to_string(counter) + "[" + fields + "]\n";
119+
} else {
120+
//There is no easy way to represent it as a struct in scala native, have to represent it as an array and then
121+
//Add helpers to help with it's manipulation
122+
uint64_t size = astContext->getTypeSize(record->getTypeForDecl());
123+
declarations += "\ttype struct_" + name + " = " + "native.CArray[Byte, " + uint64ToScalaNat(size) + "]\n";
124+
}
231125

232-
class ExampleFrontendAction : public clang::ASTFrontendAction {
233-
public:
234-
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &CI, clang::StringRef file) {
235-
return std::unique_ptr<clang::ASTConsumer>(new TreeConsumer(&CI)); // pass CI pointer to ASTConsumer
126+
return true;
236127
}
237-
};
128+
return false;
129+
}
130+
238131

239132

240133
int main(int argc, const char **argv) {
@@ -247,11 +140,14 @@ int main(int argc, const char **argv) {
247140
return -1;
248141
}
249142

143+
auto stdhead = StdHeaders.getValue();
144+
if(stdhead != ""){
145+
headerMan.LoadConfig(stdhead);
146+
}
147+
250148
declarations = "";
251149
enums = "";
252150

253-
headerMan.LoadConfig(std::string("../llvm/tools/clang/tools/extra/scala-bindgen/nativeHeaders.txt"));
254-
255151

256152
int result = Tool.run(clang::tooling::newFrontendActionFactory<ExampleFrontendAction>().get());
257153

0 commit comments

Comments
 (0)