Skip to content

Commit c8c7543

Browse files
committed
Follow simple chain of defines. Small fixes
1 parent 42de8c0 commit c8c7543

File tree

9 files changed

+68
-75
lines changed

9 files changed

+68
-75
lines changed

bindgen/Main.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,13 @@ int main(int argc, char *argv[]) {
7474
IR ir(libName, linkName, objectName, Package.getValue());
7575

7676
DefineFinderActionFactory defineFinderActionFactory(ir);
77-
Tool.run(&defineFinderActionFactory);
77+
int result = Tool.run(&defineFinderActionFactory);
78+
if (result) {
79+
return result;
80+
}
7881

7982
ScalaFrontendActionFactory actionFactory(ir);
80-
int result = Tool.run(&actionFactory);
83+
result = Tool.run(&actionFactory);
8184

8285
auto printLoc = PrintHeadersLocation.getValue();
8386
if (printLoc) {

bindgen/defines/DefineFinder.cpp

Lines changed: 47 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,77 +10,77 @@ DefineFinder::DefineFinder(IR &ir, const clang::CompilerInstance &compiler,
1010
clang::Preprocessor &pp)
1111
: ir(ir), compiler(compiler), pp(pp) {}
1212

13-
void DefineFinder::MacroDefined(const clang::Token &MacroNameTok,
14-
const clang::MacroDirective *MD) {
13+
void DefineFinder::MacroDefined(const clang::Token &macroNameTok,
14+
const clang::MacroDirective *md) {
1515
clang::SourceManager &sm = compiler.getSourceManager();
16-
if (sm.isWrittenInMainFile(MacroNameTok.getLocation()) && MD->isDefined() &&
17-
!MD->getMacroInfo()->isFunctionLike()) {
16+
if (sm.isWrittenInMainFile(macroNameTok.getLocation()) && md->isDefined() &&
17+
!md->getMacroInfo()->isFunctionLike()) {
1818
/* save defines only from the given header.
1919
*
2020
* Ignore function-like definitions because they usually are meaningful
2121
* only inside C functions. */
2222

23-
clang::ArrayRef<clang::Token> tokens = MD->getMacroInfo()->tokens();
24-
if (tokens.size() != 1) {
25-
/* process only simple definitions that contain only 1 token */
23+
const clang::Token *token = expandDefine(*md);
24+
if (!token) {
2625
return;
2726
}
28-
std::string macroName = MacroNameTok.getIdentifierInfo()->getName();
27+
std::string macroName = macroNameTok.getIdentifierInfo()->getName();
2928

30-
clang::Token token = tokens[0];
31-
const clang::Token *finalToken;
32-
if (token.isAnyIdentifier()) {
33-
/* current token might be another definition */
34-
finalToken = getFinalIdentifier(token);
35-
} else {
36-
finalToken = &token;
37-
}
38-
if (!finalToken) {
39-
return;
40-
}
41-
if (finalToken->isLiteral()) {
29+
if (token->isLiteral()) {
4230
/* might be converted directly to Scala code */
43-
std::string literal(finalToken->getLiteralData(),
44-
finalToken->getLength());
45-
if (finalToken->getKind() == clang::tok::numeric_constant) {
46-
addNumericConstantDefine(macroName, literal, finalToken);
47-
} else if (finalToken->getKind() == clang::tok::string_literal) {
31+
std::string literal(token->getLiteralData(), token->getLength());
32+
if (token->getKind() == clang::tok::numeric_constant) {
33+
addNumericConstantDefine(macroName, literal, token);
34+
} else if (token->getKind() == clang::tok::string_literal) {
4835
ir.addLiteralDefine(macroName, "c" + literal, "native.CString");
4936
} else {
50-
llvm::errs() << "Warning: type of literal "
51-
<< finalToken->getName() << " is unsupported\n";
37+
llvm::errs() << "Warning: type of literal " << token->getName()
38+
<< " is unsupported\n";
5239
llvm::errs().flush();
5340
}
54-
} else if (finalToken->isAnyIdentifier()) {
41+
} else if (token->isAnyIdentifier()) {
5542
// TODO: save identifier and get its type in ScalaFrontendAction
5643
}
5744
}
5845
}
5946

47+
/**
48+
* Follows simple chain of defines.
49+
*
50+
* @return token that is not a define
51+
*/
6052
const clang::Token *
61-
DefineFinder::getFinalIdentifier(const clang::Token &token) const {
62-
assert(token.isAnyIdentifier());
63-
if (!token.getIdentifierInfo()->hasMacroDefinition()) {
64-
return &token;
53+
DefineFinder::expandDefine(const clang::MacroDirective &md) {
54+
clang::ArrayRef<clang::Token> tokens = md.getMacroInfo()->tokens();
55+
if (tokens.size() != 1) {
56+
/* process only simple definitions that contain 1 token */
57+
return nullptr;
58+
}
59+
clang::Token token = tokens[0];
60+
if (!(token.isAnyIdentifier() || token.isLiteral())) {
61+
/* unsupported */
62+
return nullptr;
6563
}
66-
// TODO: token is another definition. Find the original value
67-
return nullptr;
64+
if (token.isLiteral() || !token.getIdentifierInfo()->hasMacroDefinition()) {
65+
return &(tokens[0]);
66+
}
67+
return expandDefine(*pp.getLocalMacroDirective(token.getIdentifierInfo()));
6868
}
6969

70-
void DefineFinder::MacroUndefined(const clang::Token &MacroNameTok,
71-
const clang::MacroDefinition &MD) {
70+
void DefineFinder::MacroUndefined(const clang::Token &macroNameTok,
71+
const clang::MacroDefinition &md) {
7272
clang::SourceManager &sm = compiler.getSourceManager();
73-
if (sm.isWrittenInMainFile(MacroNameTok.getLocation()) &&
74-
!MD.getMacroInfo()->isFunctionLike()) {
75-
std::string macroName = MacroNameTok.getIdentifierInfo()->getName();
73+
if (sm.isWrittenInMainFile(macroNameTok.getLocation()) &&
74+
!md.getMacroInfo()->isFunctionLike()) {
75+
std::string macroName = macroNameTok.getIdentifierInfo()->getName();
7676
ir.removeDefine(macroName);
7777
}
7878
}
7979

8080
void DefineFinder::addNumericConstantDefine(const std::string &macroName,
8181
std::string literal,
82-
const clang::Token *finalToken) {
83-
clang::NumericLiteralParser parser(literal, finalToken->getLocation(), pp);
82+
const clang::Token *token) {
83+
clang::NumericLiteralParser parser(literal, token->getLocation(), pp);
8484
std::string type;
8585
if (parser.isIntegerLiteral()) {
8686
std::replace(literal.begin(), literal.end(), 'l', 'L');
@@ -113,28 +113,21 @@ void DefineFinder::addNumericConstantDefine(const std::string &macroName,
113113

114114
/**
115115
* Check if literal without `l` or `ll` ending fits into int or long variable.
116+
* Supports only non-negative numbers
116117
*
117118
* Set `literal` and `type` parameters.
118119
*/
119120
void DefineFinder::getTypeOfIntLiteralWithoutEnding(
120121
clang::NumericLiteralParser parser, std::string &literal,
121122
std::string &type) {
122123

123-
bool isSigned = llvm::APSInt(literal).isSigned();
124-
125-
llvm::APInt intSignedVal(4 * 8, 0, false);
126-
llvm::APInt intUnsignedVal(4 * 8 - 1, 0, false);
127-
/* it does not matter if APInt instance is signed or not
128-
* because when calling GetIntegerValue it will check if unsigned value may
129-
* fit into the full width defined in APInt */
130-
if ((!isSigned && !parser.GetIntegerValue(intUnsignedVal)) ||
131-
(isSigned && !parser.GetIntegerValue(intSignedVal))) {
124+
llvm::APInt intValue(4 * 8 - 1, 0, false);
125+
/* check if abs value fits into 4 * 8 - 1 bits */
126+
if (!parser.GetIntegerValue(intValue)) {
132127
type = "native.CInt";
133128
} else {
134-
llvm::APInt longSignedVal(8 * 8, 0, false);
135-
llvm::APInt longUnsignedVal(8 * 8 - 1, 0, false);
136-
if ((!isSigned && !parser.GetIntegerValue(longUnsignedVal)) ||
137-
(isSigned && !parser.GetIntegerValue(longSignedVal))) {
129+
llvm::APInt longValue(8 * 8 - 1, 0, false);
130+
if (!parser.GetIntegerValue(longValue)) {
138131
type = "native.CLong";
139132
literal = literal + "L";
140133
} else {

bindgen/defines/DefineFinder.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ class DefineFinder : public clang::PPCallbacks {
1212
DefineFinder(IR &ir, const clang::CompilerInstance &compiler,
1313
clang::Preprocessor &pp);
1414

15-
void MacroDefined(const clang::Token &MacroNameTok,
16-
const clang::MacroDirective *MD) override;
15+
void MacroDefined(const clang::Token &macroNameTok,
16+
const clang::MacroDirective *md) override;
1717

18-
void MacroUndefined(const clang::Token &MacroNameTok,
19-
const clang::MacroDefinition &MD);
18+
virtual void MacroUndefined(const clang::Token &macroNameTok,
19+
const clang::MacroDefinition &md);
2020

2121
private:
2222
IR &ir;
2323
const clang::CompilerInstance &compiler;
2424
clang::Preprocessor &pp;
2525

26-
const clang::Token *getFinalIdentifier(const clang::Token &token) const;
27-
2826
void addNumericConstantDefine(const std::string &macroName,
2927
std::string literal,
3028
const clang::Token *finalToken);
3129

3230
void getTypeOfIntLiteralWithoutEnding(clang::NumericLiteralParser parser,
3331
std::string &literal,
3432
std::string &type);
33+
34+
const clang::Token *expandDefine(const clang::MacroDirective &md);
3535
};
3636

3737
#endif // SCALA_NATIVE_BINDGEN_DEFINEFINDER_H

bindgen/ir/IR.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ void IR::addUnion(std::string name, std::vector<Field> fields,
3232
unions.emplace_back(std::move(name), std::move(fields), maxSize);
3333
}
3434

35-
void IR::addLiteralDefine(std::string name, std::string literal) {
36-
literalDefines.emplace_back(std::move(name), std::move(literal));
37-
}
38-
3935
void IR::addLiteralDefine(std::string name, std::string literal,
4036
std::string type) {
4137
literalDefines.emplace_back(std::move(name), std::move(literal),

bindgen/ir/IR.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ class IR {
2929
void addUnion(std::string name, std::vector<Field> fields,
3030
uint64_t maxSize);
3131

32-
void addLiteralDefine(std::string name, std::string literal);
33-
3432
void addLiteralDefine(std::string name, std::string literal,
3533
std::string type);
3634

bindgen/ir/LiteralDefine.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#include "LiteralDefine.h"
22

3-
LiteralDefine::LiteralDefine(std::string name, std::string literal)
4-
: Define(std::move(name)), literal(std::move(literal)) {}
5-
63
LiteralDefine::LiteralDefine(std::string name, std::string literal,
74
std::string type)
85
: Define(std::move(name)), literal(std::move(literal)),

bindgen/ir/LiteralDefine.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@
66

77
class LiteralDefine : public Define {
88
public:
9-
LiteralDefine(std::string name, std::string literal);
10-
119
LiteralDefine(std::string name, std::string literal, std::string type);
1210

1311
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &s,
1412
const LiteralDefine &literalDefine);
1513

1614
private:
1715
std::string literal;
18-
std::string type; // might be empty
16+
std::string type;
1917
};
2018

2119
#endif // SCALA_NATIVE_BINDGEN_LITERALDEFINE_H

tests/samples/Define.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,25 @@
99
#define MAXIMUM_UNSIGNED_LONG 18446744073709551615
1010
#define MAXIMUM_SIGNED_LONG 9223372036854775807 // OK
1111

12+
#define NEGATIVE_NUMBER -1 // unsupported
13+
1214
/* negative values are currently ignored because there are 2 tokens in the
1315
* representation */
1416
// #define MINIMUM_SIGNED_LONG -9223372036854775808
1517

1618
#define FLOAT 5.6
1719

1820
#define INT 42
19-
#define NEW_INT INT // unsupported
21+
#define NEW_INT INT
2022

2123
extern int a;
2224
#define MY_A a // unsupported
2325

26+
#define wait_for_it(cond) \
27+
do { \
28+
sleep(1000); \
29+
} while (!cond) // unsupported
30+
2431
#ifdef NOT_DEFINED
2532
#define SHOULD_NOT_BE_DEFINED "Because NOT_DEFINED is not defined"
2633
#endif

tests/samples/Define.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ object DefineDefines {
1010
val LONG_LONG: native.CLongLong = 1000000000000L
1111
val MAXIMUM_SIGNED_LONG: native.CLong = 9223372036854775807L
1212
val INT: native.CInt = 42
13+
val NEW_INT: native.CInt = 42
1314
val SHOULD_BE_DEFINED: native.CString = c"Because INT is not equal to 0"
1415
}

0 commit comments

Comments
 (0)