1
1
#include " DefineFinder.h"
2
2
3
3
#include < llvm/ADT/APInt.h>
4
+ #include < sstream>
4
5
5
6
DefineFinder::DefineFinder (IR &ir, const clang::CompilerInstance &compiler,
6
7
clang::Preprocessor &pp)
@@ -92,7 +93,7 @@ void DefineFinder::MacroUndefined(const clang::Token ¯oNameTok,
92
93
const clang::MacroDirective *undef) {
93
94
clang::SourceManager &sm = compiler.getSourceManager ();
94
95
if (sm.isWrittenInMainFile (macroNameTok.getLocation ()) &&
95
- !md.getMacroInfo ()->isFunctionLike ()) {
96
+ md. getMacroInfo () && !md.getMacroInfo ()->isFunctionLike ()) {
96
97
std::string macroName = macroNameTok.getIdentifierInfo ()->getName ();
97
98
ir.removeDefine (macroName);
98
99
}
@@ -104,47 +105,59 @@ void DefineFinder::addNumericConstantDefine(const std::string ¯oName,
104
105
bool positive) {
105
106
clang::NumericLiteralParser parser (literal, token.getLocation (), pp);
106
107
std::string type;
108
+ std::string scalaLiteral;
107
109
if (parser.isIntegerLiteral ()) {
108
- std::replace (literal.begin (), literal.end (), ' l' , ' L' );
109
110
if (parser.isLongLong ) {
110
- /* literal has `LL` ending but `long long` is represented as
111
- * `Long` in Scala Native */
112
- literal = literal.substr (0 , literal.length () - 1 ); // remove last L
111
+ /* literal has `LL` ending. `long long` is represented as `Long`
112
+ * in Scala Native */
113
113
type = " native.CLongLong" ;
114
+
115
+ /* must fit into Scala integer type */
116
+ if (getTypeOfIntegerLiteral (parser, literal, positive).empty ()) {
117
+ type = " " ;
118
+ }
114
119
} else if (parser.isLong ) {
115
- /* literal already has `L` ending */
120
+ /* literal has `L` ending */
116
121
type = " native.CLong" ;
122
+
123
+ /* must fit into Scala integer type */
124
+ if (getTypeOfIntegerLiteral (parser, literal, positive).empty ()) {
125
+ type = " " ;
126
+ }
117
127
} else {
118
- /* literal may not have `l` or `ll` ending but still be of long type
119
- * NumericLiteralParser does not recognize that 10000000000
120
- * is a long value.
121
- * Therefore we need to check that value fits into certain number
122
- * of bits. */
123
- getTypeOfIntLiteralWithoutEnding (parser, literal, type, positive);
128
+ type = getTypeOfIntegerLiteral (parser, literal, positive);
124
129
}
125
- } else {
126
- if (parser.isFloatingLiteral ()) {
130
+
131
+ if (!type.empty ()) {
132
+ scalaLiteral = getDecimalLiteral (parser);
133
+ if (type == " native.CLong" || type == " native.CLongLong" ) {
134
+ scalaLiteral = scalaLiteral + " L" ;
135
+ }
136
+ }
137
+ } else if (parser.isFloatingLiteral ()) {
138
+ if (fitsIntoDouble (parser)) {
127
139
type = " native.CDouble" ;
128
- // TODO: distinguish between float and double
140
+ scalaLiteral = getDoubleLiteral (parser);
129
141
}
130
142
}
143
+
131
144
if (!type.empty ()) {
132
145
if (!positive) {
133
- literal = " -" + literal ;
146
+ scalaLiteral = " -" + scalaLiteral ;
134
147
}
135
- ir.addLiteralDefine (macroName, literal , type);
148
+ ir.addLiteralDefine (macroName, scalaLiteral , type);
136
149
}
137
150
}
138
151
139
- void DefineFinder::getTypeOfIntLiteralWithoutEnding (
140
- clang::NumericLiteralParser parser, std::string &literal, std::string &type,
141
- bool positive) {
152
+ std::string
153
+ DefineFinder::getTypeOfIntegerLiteral (const clang::NumericLiteralParser &parser,
154
+ const std::string &literal,
155
+ bool positive) {
142
156
143
- if (fitsIntoType<int , uint>(parser, positive)) {
144
- type = " native.CInt" ;
145
- } else if (fitsIntoType<long , ulong>(parser, positive)) {
146
- type = " native.CLong" ;
147
- literal = literal + " L" ;
157
+ if (integerFitsIntoType<int , uint>(parser, positive)) {
158
+ return " native.CInt" ;
159
+ } else if (integerFitsIntoType<long , ulong>(parser, positive)) {
160
+ return " native.CLong" ;
148
161
} else {
149
162
llvm::errs () << " Waring: integer value does not fit into 8 bytes: "
150
163
<< literal << " \n " ;
@@ -157,12 +170,13 @@ void DefineFinder::getTypeOfIntLiteralWithoutEnding(
157
170
* @endcode
158
171
* Therefore the case of `long long` is not considered here.
159
172
*/
173
+ return " " ;
160
174
}
161
175
}
162
176
163
177
template <typename signedT, typename unsignedT>
164
- bool DefineFinder::fitsIntoType (clang::NumericLiteralParser parser,
165
- bool positive) {
178
+ bool DefineFinder::integerFitsIntoType (clang::NumericLiteralParser parser,
179
+ bool positive) {
166
180
/* absolute value of minimum negative number will not fit
167
181
* into (sizeof(signedT) * 8 - 1) bits */
168
182
llvm::APInt uintValue (sizeof (signedT) * 8 , 0 , false );
@@ -180,3 +194,26 @@ bool DefineFinder::fitsIntoType(clang::NumericLiteralParser parser,
180
194
static_cast <unsignedT>(-std::numeric_limits<signedT>::min ());
181
195
}
182
196
}
197
+
198
+ std::string
199
+ DefineFinder::getDecimalLiteral (clang::NumericLiteralParser parser) {
200
+ llvm::APInt val (8 * 8 , 0 , false );
201
+ parser.GetIntegerValue (val);
202
+ return std::to_string (val.getZExtValue ());
203
+ }
204
+
205
+ std::string DefineFinder::getDoubleLiteral (clang::NumericLiteralParser parser) {
206
+ llvm::APFloat val (.0 ); // double
207
+ parser.GetFloatValue (val);
208
+ std::ostringstream ss;
209
+ ss << val.convertToDouble ();
210
+ return ss.str ();
211
+ }
212
+
213
+ bool DefineFinder::fitsIntoDouble (clang::NumericLiteralParser parser) {
214
+ llvm::APFloat val (.0 ); // double
215
+ parser.GetFloatValue (val);
216
+ std::ostringstream ss;
217
+ ss << val.convertToDouble ();
218
+ return ss.str () != " inf" ;
219
+ }
0 commit comments