@@ -10,77 +10,77 @@ DefineFinder::DefineFinder(IR &ir, const clang::CompilerInstance &compiler,
10
10
clang::Preprocessor &pp)
11
11
: ir(ir), compiler(compiler), pp(pp) {}
12
12
13
- void DefineFinder::MacroDefined (const clang::Token &MacroNameTok ,
14
- const clang::MacroDirective *MD ) {
13
+ void DefineFinder::MacroDefined (const clang::Token ¯oNameTok ,
14
+ const clang::MacroDirective *md ) {
15
15
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 ()) {
18
18
/* save defines only from the given header.
19
19
*
20
20
* Ignore function-like definitions because they usually are meaningful
21
21
* only inside C functions. */
22
22
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) {
26
25
return ;
27
26
}
28
- std::string macroName = MacroNameTok .getIdentifierInfo ()->getName ();
27
+ std::string macroName = macroNameTok .getIdentifierInfo ()->getName ();
29
28
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 ()) {
42
30
/* 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) {
48
35
ir.addLiteralDefine (macroName, " c" + literal, " native.CString" );
49
36
} 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 " ;
52
39
llvm::errs ().flush ();
53
40
}
54
- } else if (finalToken ->isAnyIdentifier ()) {
41
+ } else if (token ->isAnyIdentifier ()) {
55
42
// TODO: save identifier and get its type in ScalaFrontendAction
56
43
}
57
44
}
58
45
}
59
46
47
+ /* *
48
+ * Follows simple chain of defines.
49
+ *
50
+ * @return token that is not a define
51
+ */
60
52
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 ;
65
63
}
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 ()));
68
68
}
69
69
70
- void DefineFinder::MacroUndefined (const clang::Token &MacroNameTok ,
71
- const clang::MacroDefinition &MD ) {
70
+ void DefineFinder::MacroUndefined (const clang::Token ¯oNameTok ,
71
+ const clang::MacroDefinition &md ) {
72
72
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 ();
76
76
ir.removeDefine (macroName);
77
77
}
78
78
}
79
79
80
80
void DefineFinder::addNumericConstantDefine (const std::string ¯oName,
81
81
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);
84
84
std::string type;
85
85
if (parser.isIntegerLiteral ()) {
86
86
std::replace (literal.begin (), literal.end (), ' l' , ' L' );
@@ -113,28 +113,21 @@ void DefineFinder::addNumericConstantDefine(const std::string ¯oName,
113
113
114
114
/* *
115
115
* Check if literal without `l` or `ll` ending fits into int or long variable.
116
+ * Supports only non-negative numbers
116
117
*
117
118
* Set `literal` and `type` parameters.
118
119
*/
119
120
void DefineFinder::getTypeOfIntLiteralWithoutEnding (
120
121
clang::NumericLiteralParser parser, std::string &literal,
121
122
std::string &type) {
122
123
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)) {
132
127
type = " native.CInt" ;
133
128
} 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)) {
138
131
type = " native.CLong" ;
139
132
literal = literal + " L" ;
140
133
} else {
0 commit comments