Skip to content

Commit 5774883

Browse files
committed
Generate bindings for defines for variables
1 parent 7b0bccb commit 5774883

File tree

15 files changed

+155
-18
lines changed

15 files changed

+155
-18
lines changed

bindgen/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ add_executable(bindgen
4848
ir/Define.cpp
4949
ir/LiteralDefine.cpp
5050
ir/LiteralDefine.h
51-
)
51+
ir/VarDefine.cpp
52+
ir/VarDefine.h)
5253

5354
set_target_properties(bindgen
5455
PROPERTIES

bindgen/defines/DefineFinder.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ void DefineFinder::MacroDefined(const clang::Token &macroNameTok,
4242
std::string literal(stringToken.getLiteralData(),
4343
stringToken.getLength());
4444
ir.addLiteralDefine(macroName, "c" + literal, "native.CString");
45+
} else if (tokens->size() == 1 &&
46+
(*tokens)[0].getKind() == clang::tok::identifier) {
47+
// token might be a variable
48+
std::string varName = (*tokens)[0].getIdentifierInfo()->getName();
49+
ir.addPossibleVarDefine(macroName, varName);
4550
}
4651
std::free(tokens);
4752
}

bindgen/ir/Define.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
Define::Define(std::string name) : name(std::move(name)) {}
44

5-
std::string Define::getName() { return name; }
5+
std::string Define::getName() const { return name; }

bindgen/ir/Define.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class Define {
77
public:
88
explicit Define(std::string name);
99

10-
std::string getName();
10+
std::string getName() const;
1111

1212
protected:
1313
std::string name;

bindgen/ir/IR.cpp

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,19 @@ void IR::addLiteralDefine(std::string name, std::string literal,
3838
std::move(type));
3939
}
4040

41+
void IR::addPossibleVarDefine(const std::string &macroName,
42+
const std::string &varName) {
43+
possibleVarDefines.emplace_back(macroName, varName, "");
44+
}
45+
46+
void IR::addVarDefine(const std::string &macroName, const std::string &varName,
47+
const std::string &type) {
48+
varDefines.emplace_back(macroName, varName, type);
49+
}
50+
4151
bool IR::libObjEmpty() const {
4252
return functions.empty() && typeDefs.empty() && structs.empty() &&
43-
unions.empty();
53+
unions.empty() && varDefines.empty();
4454
}
4555

4656
llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
@@ -69,6 +79,12 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
6979
s << typeDef;
7080
}
7181

82+
for (const auto &varDefine : ir.varDefines) {
83+
s << " @name(\"" << varDefine.getVarName() << "\")\n"
84+
<< " def " << varDefine.getName() << ": " << varDefine.getType()
85+
<< " = native.extern\n";
86+
}
87+
7288
for (const auto &func : ir.functions) {
7389
s << func;
7490
}
@@ -166,9 +182,9 @@ void IR::filterDeclarations(const std::string &excludePrefix) {
166182

167183
filterTypeDefs(excludePrefix);
168184

169-
filter(functions, excludePrefix);
185+
filterByPrefix(functions, excludePrefix);
170186

171-
filter(literalDefines, excludePrefix);
187+
filterByPrefix(literalDefines, excludePrefix);
172188
}
173189

174190
void IR::filterTypeDefs(const std::string &excludePrefix) {
@@ -236,24 +252,41 @@ bool IR::existsFunctionWithName(std::string functionName) {
236252
}
237253

238254
void IR::removeDefine(const std::string &name) {
239-
for (auto it = literalDefines.begin(), end = literalDefines.end();
240-
it != end; ++it) {
241-
if ((*it).getName() == name) {
242-
literalDefines.erase(it);
243-
return;
255+
filterByName(literalDefines, name);
256+
filterByName(possibleVarDefines, name);
257+
filterByName(varDefines, name);
258+
}
259+
260+
template <typename T>
261+
void IR::filterByPrefix(std::vector<T> &declarations,
262+
const std::string &excludePrefix) {
263+
for (auto it = declarations.begin(); it != declarations.end();) {
264+
auto &declaration = *it;
265+
if (startsWith(declaration.getName(), excludePrefix)) {
266+
it = declarations.erase(it);
267+
} else {
268+
it++;
244269
}
245270
}
246271
}
247272

248273
template <typename T>
249-
void IR::filter(std::vector<T> &declarations,
250-
const std::string &excludePrefix) {
274+
void IR::filterByName(std::vector<T> &declarations, const std::string &name) {
251275
for (auto it = declarations.begin(); it != declarations.end();) {
252276
auto &declaration = *it;
253-
if (startsWith(declaration.getName(), excludePrefix)) {
277+
if (declaration.getName() == name) {
254278
it = declarations.erase(it);
255279
} else {
256280
it++;
257281
}
258282
}
259283
}
284+
285+
std::string IR::getDefineForVar(const std::string &varName) const {
286+
for (const auto &varDefine : possibleVarDefines) {
287+
if (varDefine.getVarName() == varName) {
288+
return varDefine.getName();
289+
}
290+
}
291+
return "";
292+
}

bindgen/ir/IR.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "LiteralDefine.h"
77
#include "Struct.h"
88
#include "TypeDef.h"
9+
#include "VarDefine.h"
910

1011
/**
1112
* Intermediate representation
@@ -32,6 +33,12 @@ class IR {
3233
void addLiteralDefine(std::string name, std::string literal,
3334
std::string type);
3435

36+
void addPossibleVarDefine(const std::string &macroName,
37+
const std::string &varName);
38+
39+
void addVarDefine(const std::string &macroName, const std::string &varName,
40+
const std::string &type);
41+
3542
/**
3643
* @return true if there are no functions, types,
3744
* structs and unions
@@ -46,6 +53,12 @@ class IR {
4653

4754
void removeDefine(const std::string &name);
4855

56+
/**
57+
* @return macro name if there is a macro for the variable.
58+
* otherwise return empty string
59+
*/
60+
std::string getDefineForVar(const std::string &varName) const;
61+
4962
private:
5063
/**
5164
* Generates type defs for enums, structs and unions
@@ -106,7 +119,11 @@ class IR {
106119
bool existsFunctionWithName(std::string functionName);
107120

108121
template <typename T>
109-
void filter(std::vector<T> &declarations, const std::string &excludePrefix);
122+
void filterByPrefix(std::vector<T> &declarations,
123+
const std::string &excludePrefix);
124+
125+
template <typename T>
126+
void filterByName(std::vector<T> &declarations, const std::string &name);
110127

111128
std::string libName; // name of the library
112129
std::string linkName; // name of the library to link with
@@ -117,6 +134,8 @@ class IR {
117134
std::vector<Union> unions;
118135
std::vector<Enum> enums;
119136
std::vector<LiteralDefine> literalDefines;
137+
std::vector<VarDefine> possibleVarDefines;
138+
std::vector<VarDefine> varDefines;
120139
bool generated = false; // generate type defs only once
121140
std::string packageName;
122141
};

bindgen/ir/VarDefine.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "VarDefine.h"
2+
3+
VarDefine::VarDefine(std::string name, std::string varName, std::string type)
4+
: Define(std::move(name)), varName(std::move(varName)),
5+
type(std::move(type)) {}
6+
7+
std::string VarDefine::getVarName() const { return varName; }
8+
9+
std::string VarDefine::getType() const { return type; }

bindgen/ir/VarDefine.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef SCALA_NATIVE_BINDGEN_VARDEFINE_H
2+
#define SCALA_NATIVE_BINDGEN_VARDEFINE_H
3+
4+
#include "Define.h"
5+
6+
class VarDefine : public Define {
7+
public:
8+
VarDefine(std::string name, std::string varName, std::string type);
9+
10+
std::string getVarName() const;
11+
12+
std::string getType() const;
13+
14+
private:
15+
std::string varName;
16+
std::string type;
17+
};
18+
19+
#endif // SCALA_NATIVE_BINDGEN_VARDEFINE_H

bindgen/visitor/TreeVisitor.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,18 @@ void TreeVisitor::handleStruct(clang::RecordDecl *record, std::string name) {
159159
ir.addStruct(name, fields,
160160
astContext->getTypeSize(record->getTypeForDecl()));
161161
}
162+
163+
bool TreeVisitor::VisitVarDecl(clang::VarDecl *varDecl) {
164+
if (!varDecl->isThisDeclarationADefinition()) {
165+
/* check if there is a macro for the variable.
166+
* Macros were saved by DefineFinder */
167+
std::string varName = varDecl->getName().str();
168+
std::string macroName = ir.getDefineForVar(varName);
169+
if (!macroName.empty()) {
170+
std::string type = handleReservedWords(
171+
typeTranslator.Translate(varDecl->getType()));
172+
ir.addVarDefine(macroName, varName, type);
173+
}
174+
}
175+
return true;
176+
}

bindgen/visitor/TreeVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ class TreeVisitor : public clang::RecursiveASTVisitor<TreeVisitor> {
3737
virtual bool VisitTypedefDecl(clang::TypedefDecl *tpdef);
3838
virtual bool VisitEnumDecl(clang::EnumDecl *enumdecl);
3939
virtual bool VisitRecordDecl(clang::RecordDecl *record);
40+
virtual bool VisitVarDecl(clang::VarDecl *VD);
4041
};

tests/samples/LiteralDefine.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
#define NEW_INT INT
2020
#define NEG_INT -INT
2121

22-
extern int a;
23-
#define MY_A a // unsupported
24-
2522
#define __PRIVATE 1
2623

2724
#define wait_for_it(cond) \

tests/samples/VarDefine.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "VarDefine.h"
2+
3+
int a = 23;
4+
5+
int getA() { return a; }

tests/samples/VarDefine.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
extern int a;
2+
#define A a
3+
4+
#define B b // ignored because there is no such variable
5+
6+
extern int c;
7+
#define C c
8+
#undef C // removed
9+
10+
int getA();

tests/samples/VarDefine.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.scalanative.bindgen.samples
2+
3+
import scala.scalanative._
4+
import scala.scalanative.native._
5+
6+
@native.link("bindgentests")
7+
@native.extern
8+
object VarDefine {
9+
@name("a")
10+
def A: native.CInt = native.extern
11+
def getA(): native.CInt = native.extern
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.scalanative.bindgen.samples
2+
3+
import utest._
4+
5+
object VarDefineTests extends TestSuite {
6+
val tests = Tests {
7+
'getA - {
8+
assert(VarDefine.getA() == 23)
9+
}
10+
}
11+
}

0 commit comments

Comments
 (0)