@@ -87,10 +87,9 @@ void IR::addVarDefine(std::string name, std::shared_ptr<Variable> variable) {
87
87
}
88
88
89
89
bool IR::libObjEmpty () const {
90
- return functions.empty () && !hasOutputtedDeclaration (typeDefs) &&
91
- !hasOutputtedDeclaration (structs) &&
92
- !hasOutputtedDeclaration (unions) && varDefines.empty () &&
93
- variables.empty ();
90
+ return functions.empty () && !hasOutputtedType (typeDefs) &&
91
+ !hasOutputtedType (structs) && !hasOutputtedType (unions) &&
92
+ varDefines.empty () && variables.empty ();
94
93
}
95
94
96
95
llvm::raw_ostream &operator <<(llvm::raw_ostream &s, const IR &ir) {
@@ -100,7 +99,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
100
99
s << " package " << ir.packageName << " \n\n " ;
101
100
}
102
101
103
- if (!ir.libObjEmpty () || ir.hasOutputtedDeclaration (ir.enums ) ||
102
+ if (!ir.libObjEmpty () || ir.hasOutputtedType (ir.enums ) ||
104
103
!ir.literalDefines .empty ()) {
105
104
s << " import scala.scalanative._\n "
106
105
<< " import scala.scalanative.native._\n\n " ;
@@ -123,8 +122,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
123
122
124
123
for (const auto &typeDef : ir.typeDefs ) {
125
124
visitedTypes.clear ();
126
- if (ir.shouldOutput (typeDef, visitedTypes)) {
127
- s << * typeDef;
125
+ if (ir.shouldOutputTypeDef (typeDef, visitedTypes)) {
126
+ s << typeDef-> getDefinition (ir. locationManager ) ;
128
127
} else if (typeDef->hasLocation () &&
129
128
isAliasForOpaqueType (typeDef.get ()) &&
130
129
ir.locationManager .inMainFile (*typeDef->getLocation ())) {
@@ -138,7 +137,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
138
137
139
138
for (const auto &variable : ir.variables ) {
140
139
if (!variable->hasIllegalUsageOfOpaqueType ()) {
141
- s << * variable;
140
+ s << variable-> getDefinition (ir. locationManager ) ;
142
141
} else {
143
142
llvm::errs () << " Error: Variable " << variable->getName ()
144
143
<< " is skipped because it has incomplete type.\n " ;
@@ -147,7 +146,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
147
146
148
147
for (const auto &varDefine : ir.varDefines ) {
149
148
if (!varDefine->hasIllegalUsageOfOpaqueType ()) {
150
- s << * varDefine;
149
+ s << varDefine-> getDefinition (ir. locationManager ) ;
151
150
} else {
152
151
llvm::errs () << " Error: Variable alias " << varDefine->getName ()
153
152
<< " is skipped because it has incomplete type.\n " ;
@@ -162,7 +161,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
162
161
" passing structs and arrays by value.\n " ;
163
162
llvm::errs ().flush ();
164
163
} else {
165
- s << * func;
164
+ s << func-> getDefinition (ir. locationManager ) ;
166
165
}
167
166
}
168
167
@@ -173,16 +172,16 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
173
172
if (!ir.literalDefines .empty ()) {
174
173
s << " object " << ir.libName << " Defines {\n " ;
175
174
for (const auto &literalDefine : ir.literalDefines ) {
176
- s << * literalDefine;
175
+ s << literalDefine-> getDefinition (ir. locationManager ) ;
177
176
}
178
177
s << " }\n\n " ;
179
178
}
180
179
181
- if (ir.hasOutputtedDeclaration (ir.enums ) || ir.hasHelperMethods ()) {
180
+ if (ir.hasOutputtedType (ir.enums ) || ir.hasHelperMethods ()) {
182
181
s << " import " << objectName << " ._\n\n " ;
183
182
}
184
183
185
- if (ir.hasOutputtedDeclaration (ir.enums )) {
184
+ if (ir.hasOutputtedType (ir.enums )) {
186
185
s << " object " << ir.libName << " Enums {\n " ;
187
186
188
187
std::string sep = " " ;
@@ -203,14 +202,14 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
203
202
for (const auto &st : ir.structs ) {
204
203
visitedTypes.clear ();
205
204
if (ir.shouldOutput (st, visitedTypes) && st->hasHelperMethods ()) {
206
- s << " \n " << st->generateHelperClass ();
205
+ s << " \n " << st->generateHelperClass (ir. locationManager );
207
206
}
208
207
}
209
208
210
209
for (const auto &u : ir.unions ) {
211
210
visitedTypes.clear ();
212
211
if (ir.shouldOutput (u, visitedTypes) && u->hasHelperMethods ()) {
213
- s << " \n " << u->generateHelperClass ();
212
+ s << " \n " << u->generateHelperClass (ir. locationManager );
214
213
}
215
214
}
216
215
@@ -327,7 +326,7 @@ bool IR::isTypeUsed(
327
326
for (const auto &typeDef : typeDefs) {
328
327
visitedTypesInner.clear ();
329
328
if (typeDef->usesType (type, false , visitedTypesInner)) {
330
- if (shouldOutput (typeDef, visitedTypes)) {
329
+ if (shouldOutputTypeDef (typeDef, visitedTypes)) {
331
330
return true ;
332
331
}
333
332
}
@@ -462,13 +461,21 @@ IR::~IR() {
462
461
}
463
462
464
463
template <typename T>
465
- bool IR::hasOutputtedDeclaration (
464
+ bool IR::hasOutputtedType (
466
465
const std::vector<std::shared_ptr<T>> &declarations) const {
467
466
std::vector<std::shared_ptr<const Type>> visitedTypes;
468
467
for (const auto &declaration : declarations) {
469
468
visitedTypes.clear ();
470
- if (shouldOutput (declaration, visitedTypes)) {
471
- return true ;
469
+ auto typeDefPointer =
470
+ std::dynamic_pointer_cast<const TypeDef>(declaration);
471
+ if (typeDefPointer) {
472
+ if (shouldOutputTypeDef (typeDefPointer, visitedTypes)) {
473
+ return true ;
474
+ }
475
+ } else {
476
+ if (shouldOutput (declaration, visitedTypes)) {
477
+ return true ;
478
+ }
472
479
}
473
480
}
474
481
return false ;
@@ -477,12 +484,31 @@ bool IR::hasOutputtedDeclaration(
477
484
bool IR::shouldOutput (
478
485
const std::shared_ptr<const LocatableType> &type,
479
486
std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
487
+ if (locationManager.isImported (*type->getLocation ())) {
488
+ return false ;
489
+ }
480
490
if (isTypeUsed (type, visitedTypes)) {
481
491
return true ;
482
492
}
483
- if (isAliasForOpaqueType (type.get ())) {
493
+ /* remove unused types from included files */
494
+ return locationManager.inMainFile (*type->getLocation ());
495
+ }
496
+
497
+ bool IR::shouldOutputTypeDef (
498
+ const std::shared_ptr<const TypeDef> &typeDef,
499
+ std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
500
+ if (isTypeUsed (typeDef, visitedTypes)) {
501
+ if (typeDef->wrapperForOpaqueType ()) {
502
+ /* it is not possible to get location of this typedef
503
+ * so the typedef cannot be imported from other bindings */
504
+ return true ;
505
+ }
506
+ return !locationManager.isImported (*typeDef->getLocation ());
507
+ }
508
+ if (isAliasForOpaqueType (typeDef.get ())) {
509
+ /* it does not matter where unused alias for opaque type is located */
484
510
return false ;
485
511
}
486
512
/* remove unused types from included files */
487
- return locationManager.inMainFile (*type ->getLocation ());
513
+ return locationManager.inMainFile (*typeDef ->getLocation ());
488
514
}
0 commit comments