1
1
#include " IR.h"
2
2
#include " ../Utils.h"
3
- #include " location/SourceLocation.h"
4
3
5
4
IR::IR (std::string libName, std::string linkName, std::string objectName,
6
- std::string packageName)
5
+ std::string packageName, const LocationManager &locationManager )
7
6
: libName(std::move(libName)), linkName(std::move(linkName)),
8
- objectName(std::move(objectName)), packageName(std::move(packageName)) {}
7
+ objectName(std::move(objectName)), locationManager(locationManager),
8
+ packageName(std::move(packageName)) {}
9
9
10
10
void IR::addFunction (std::string name, std::vector<Parameter *> parameters,
11
11
std::shared_ptr<Type> retType, bool isVariadic) {
@@ -78,8 +78,10 @@ void IR::addVarDefine(std::string name, std::shared_ptr<Variable> variable) {
78
78
}
79
79
80
80
bool IR::libObjEmpty () const {
81
- return functions.empty () && typeDefs.empty () && structs.empty () &&
82
- unions.empty () && varDefines.empty () && variables.empty ();
81
+ return functions.empty () && !hasOutputtedTypeDefs () &&
82
+ !hasOutputtedDeclaration (structs) &&
83
+ !hasOutputtedDeclaration (unions) && varDefines.empty () &&
84
+ variables.empty ();
83
85
}
84
86
85
87
llvm::raw_ostream &operator <<(llvm::raw_ostream &s, const IR &ir) {
@@ -89,7 +91,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
89
91
s << " package " << ir.packageName << " \n\n " ;
90
92
}
91
93
92
- if (!ir.libObjEmpty () || !ir.enums .empty () || !ir.literalDefines .empty ()) {
94
+ if (!ir.libObjEmpty () || ir.hasOutputtedEnums () ||
95
+ !ir.literalDefines .empty ()) {
93
96
s << " import scala.scalanative._\n "
94
97
<< " import scala.scalanative.native._\n\n " ;
95
98
}
@@ -105,7 +108,9 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
105
108
<< " object " << objectName << " {\n " ;
106
109
107
110
for (const auto &typeDef : ir.typeDefs ) {
108
- s << *typeDef;
111
+ if (ir.typeDefInMainFile (*typeDef) || ir.isTypeUsed (typeDef)) {
112
+ s << *typeDef;
113
+ }
109
114
}
110
115
111
116
for (const auto &variable : ir.variables ) {
@@ -131,19 +136,20 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
131
136
s << " }\n\n " ;
132
137
}
133
138
134
- if (! ir.enums . empty () || ir.hasHelperMethods ()) {
139
+ if (ir.hasOutputtedEnums () || ir.hasHelperMethods ()) {
135
140
s << " import " << objectName << " ._\n\n " ;
136
141
}
137
142
138
- if (! ir.enums . empty ()) {
143
+ if (ir.hasOutputtedEnums ()) {
139
144
s << " object " << ir.libName << " Enums {\n " ;
140
145
141
- unsigned long enumeratorsCount = ir.enums .size ();
142
- for (unsigned long i = 0 ; i < enumeratorsCount; i++) {
143
- auto e = ir.enums [i];
144
- s << *e;
145
- if (i < enumeratorsCount - 1 ) {
146
- s << " \n " ; // space between groups of enums
146
+ std::string sep = " " ;
147
+ for (const auto &e : ir.enums ) {
148
+ if (ir.inMainFile (*e) ||
149
+ (!e->isAnonymous () &&
150
+ ir.isTypeUsed (ir.getTypeDefWithName (e->getTypeAlias ())))) {
151
+ s << sep << *e;
152
+ sep = " \n " ;
147
153
}
148
154
}
149
155
@@ -154,13 +160,15 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
154
160
s << " object " << ir.libName << " Helpers {\n " ;
155
161
156
162
for (const auto &st : ir.structs ) {
157
- if (st->hasHelperMethods ()) {
163
+ if (ir. isOutputted (st. get ()) && st->hasHelperMethods ()) {
158
164
s << " \n " << st->generateHelperClass ();
159
165
}
160
166
}
161
167
162
168
for (const auto &u : ir.unions ) {
163
- s << " \n " << u->generateHelperClass ();
169
+ if (ir.isOutputted (u.get ())) {
170
+ s << " \n " << u->generateHelperClass ();
171
+ }
164
172
}
165
173
166
174
s << " }\n\n " ;
@@ -173,19 +181,19 @@ void IR::generate(const std::string &excludePrefix) {
173
181
if (!generated) {
174
182
setScalaNames ();
175
183
filterDeclarations (excludePrefix);
176
- removeUnusedExternalTypedefs ();
184
+ // removeUnusedExternalTypedefs();
177
185
generated = true ;
178
186
}
179
187
}
180
188
181
189
bool IR::hasHelperMethods () const {
182
- if (!unions. empty ( )) {
190
+ if (hasOutputtedDeclaration (unions )) {
183
191
/* all unions have helper methods */
184
192
return true ;
185
193
}
186
194
187
195
for (const auto &s : structs) {
188
- if (s->hasHelperMethods ()) {
196
+ if (isOutputted (s. get ()) && s->hasHelperMethods ()) {
189
197
return true ;
190
198
}
191
199
}
@@ -328,7 +336,7 @@ std::shared_ptr<Variable> IR::addVariable(const std::string &name,
328
336
return variable;
329
337
}
330
338
331
- std::shared_ptr<TypeDef> IR::getTypeDefWithName (const std::string &name) {
339
+ std::shared_ptr<TypeDef> IR::getTypeDefWithName (const std::string &name) const {
332
340
/* nullptr is returned in 2 cases:
333
341
* 1. TypeTranslator translates opaque struct/union type for which TypeDef
334
342
* was not created.
@@ -338,8 +346,8 @@ std::shared_ptr<TypeDef> IR::getTypeDefWithName(const std::string &name) {
338
346
}
339
347
340
348
template <typename T>
341
- T IR::getDeclarationWithName (std::vector<T> &declarations,
342
- const std::string &name) {
349
+ T IR::getDeclarationWithName (const std::vector<T> &declarations,
350
+ const std::string &name) const {
343
351
for (auto it = declarations.begin (), end = declarations.end (); it != end;
344
352
++it) {
345
353
T declaration = (*it);
@@ -362,55 +370,60 @@ IR::~IR() {
362
370
varDefines.clear ();
363
371
}
364
372
365
- void IR::removeUnusedExternalTypedefs () {
366
- for (auto it = typeDefs.begin (); it != typeDefs.end ();) {
367
- std::shared_ptr<TypeDef> typeDef = *it;
368
- std::shared_ptr<Location> location = typeDef->getLocation ();
369
- auto *sourceLocation = dynamic_cast <SourceLocation *>(location.get ());
370
- if (sourceLocation && !sourceLocation->isMainFile ()) {
371
- if (!isTypeUsed (typeDef)) {
372
- it = typeDefs.erase (it);
373
- } else {
374
- ++it;
375
- }
376
- } else {
377
- ++it;
373
+ bool IR::typeDefInMainFile (const TypeDef &typeDef) const {
374
+ if (inMainFile (typeDef)) {
375
+ return true ;
376
+ }
377
+ Type *type = typeDef.getType ().get ();
378
+ if (isInstanceOf<Struct>(type)) {
379
+ return inMainFile (*dynamic_cast <Struct *>(type));
380
+ }
381
+ if (isInstanceOf<Union>(type)) {
382
+ return inMainFile (*dynamic_cast <Union *>(type));
383
+ }
384
+ if (isInstanceOf<Enum>(type)) {
385
+ return inMainFile (*dynamic_cast <Enum *>(type));
386
+ }
387
+ return false ;
388
+ }
389
+
390
+ template <typename T> bool IR::inMainFile (const T &type) const {
391
+ std::shared_ptr<Location> location = type.getLocation ();
392
+ return location && locationManager.inMainFile (*location);
393
+ }
394
+
395
+ bool IR::hasOutputtedEnums () const {
396
+ for (const auto &e : enums) {
397
+ if (inMainFile (*e) ||
398
+ (!e->isAnonymous () &&
399
+ isTypeUsed (getTypeDefWithName (e->getTypeAlias ())))) {
400
+ return true ;
378
401
}
379
402
}
380
- removeUnusedExternalTypeAndTypedef (structs);
381
- removeUnusedExternalTypeAndTypedef (unions);
382
- removeUnusedExternalTypeAndTypedef (enums);
403
+ return false ;
383
404
}
384
405
385
- template <typename T>
386
- void IR::removeDeclaration (std::vector<std::shared_ptr<T>> &declarations,
387
- T *declaration) {
388
- for (auto it = declarations.begin (); it != declarations.end ();) {
389
- T *decl = (*it).get ();
390
- if (decl == declaration) {
391
- it = declarations.erase (it);
392
- } else {
393
- ++it;
406
+ bool IR::hasOutputtedTypeDefs () const {
407
+ for (const auto &typeDef : typeDefs) {
408
+ if (inMainFile (*typeDef) || isTypeUsed (typeDef)) {
409
+ return true ;
394
410
}
395
411
}
412
+ return false ;
396
413
}
397
414
398
415
template <typename T>
399
- void IR::removeUnusedExternalTypeAndTypedef (
400
- std::vector<std::shared_ptr<T>> &types) {
401
- for (auto it = types.begin (); it != types.end ();) {
402
- std::shared_ptr<T> t = *it;
403
- auto *sourceLocation =
404
- dynamic_cast <SourceLocation *>(t->getLocation ().get ());
405
- if (sourceLocation && !sourceLocation->isMainFile ()) {
406
- std::shared_ptr<TypeDef> typeDef =
407
- getTypeDefWithName (t->getTypeAlias ());
408
- if (!isTypeUsed (typeDef)) {
409
- it = types.erase (it);
410
- removeDeclaration (typeDefs, typeDef.get ());
411
- } else {
412
- ++it;
413
- }
416
+ bool IR::hasOutputtedDeclaration (
417
+ const std::vector<std::shared_ptr<T>> &declarations) const {
418
+ for (const auto &declaration : declarations) {
419
+ if (isOutputted (declaration.get ())) {
420
+ return true ;
414
421
}
415
422
}
423
+ return false ;
424
+ }
425
+
426
+ bool IR::isOutputted (const StructOrUnion *structOrUnion) const {
427
+ return inMainFile (*structOrUnion) ||
428
+ isTypeUsed (getTypeDefWithName (structOrUnion->getTypeAlias ()));
416
429
}
0 commit comments