@@ -81,10 +81,9 @@ void IR::addVarDefine(std::string name, std::shared_ptr<Variable> variable) {
81
81
}
82
82
83
83
bool IR::libObjEmpty () const {
84
- return functions.empty () && !hasOutputtedDeclaration (typeDefs) &&
85
- !hasOutputtedDeclaration (structs) &&
86
- !hasOutputtedDeclaration (unions) && varDefines.empty () &&
87
- variables.empty ();
84
+ return functions.empty () && !hasOutputtedType (typeDefs) &&
85
+ !hasOutputtedType (structs) && !hasOutputtedType (unions) &&
86
+ varDefines.empty () && variables.empty ();
88
87
}
89
88
90
89
llvm::raw_ostream &operator <<(llvm::raw_ostream &s, const IR &ir) {
@@ -94,7 +93,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
94
93
s << " package " << ir.packageName << " \n\n " ;
95
94
}
96
95
97
- if (!ir.libObjEmpty () || ir.hasOutputtedDeclaration (ir.enums ) ||
96
+ if (!ir.libObjEmpty () || ir.hasOutputtedType (ir.enums ) ||
98
97
!ir.literalDefines .empty ()) {
99
98
s << " import scala.scalanative._\n "
100
99
<< " import scala.scalanative.native._\n\n " ;
@@ -117,8 +116,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
117
116
118
117
for (const auto &typeDef : ir.typeDefs ) {
119
118
visitedTypes.clear ();
120
- if (ir.shouldOutput (typeDef, visitedTypes)) {
121
- s << * typeDef;
119
+ if (ir.shouldOutputTypeDef (typeDef, visitedTypes)) {
120
+ s << typeDef-> getDefinition (ir. locationManager ) ;
122
121
} else if (typeDef->hasLocation () &&
123
122
isAliasForOpaqueType (typeDef.get ()) &&
124
123
ir.locationManager .inMainFile (*typeDef->getLocation ())) {
@@ -132,7 +131,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
132
131
133
132
for (const auto &variable : ir.variables ) {
134
133
if (!variable->hasIllegalUsageOfOpaqueType ()) {
135
- s << * variable;
134
+ s << variable-> getDefinition (ir. locationManager ) ;
136
135
} else {
137
136
llvm::errs () << " Error: Variable " << variable->getName ()
138
137
<< " is skipped because it has incomplete type.\n " ;
@@ -141,7 +140,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
141
140
142
141
for (const auto &varDefine : ir.varDefines ) {
143
142
if (!varDefine->hasIllegalUsageOfOpaqueType ()) {
144
- s << * varDefine;
143
+ s << varDefine-> getDefinition (ir. locationManager ) ;
145
144
} else {
146
145
llvm::errs () << " Error: Variable alias " << varDefine->getName ()
147
146
<< " is skipped because it has incomplete type.\n " ;
@@ -156,7 +155,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
156
155
" passing structs and arrays by value.\n " ;
157
156
llvm::errs ().flush ();
158
157
} else {
159
- s << * func;
158
+ s << func-> getDefinition (ir. locationManager ) ;
160
159
}
161
160
}
162
161
@@ -167,16 +166,16 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
167
166
if (!ir.literalDefines .empty ()) {
168
167
s << " object " << ir.libName << " Defines {\n " ;
169
168
for (const auto &literalDefine : ir.literalDefines ) {
170
- s << * literalDefine;
169
+ s << literalDefine-> getDefinition (ir. locationManager ) ;
171
170
}
172
171
s << " }\n\n " ;
173
172
}
174
173
175
- if (ir.hasOutputtedDeclaration (ir.enums ) || ir.hasHelperMethods ()) {
174
+ if (ir.hasOutputtedType (ir.enums ) || ir.hasHelperMethods ()) {
176
175
s << " import " << objectName << " ._\n\n " ;
177
176
}
178
177
179
- if (ir.hasOutputtedDeclaration (ir.enums )) {
178
+ if (ir.hasOutputtedType (ir.enums )) {
180
179
s << " object " << ir.libName << " Enums {\n " ;
181
180
182
181
std::string sep = " " ;
@@ -197,14 +196,14 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
197
196
for (const auto &st : ir.structs ) {
198
197
visitedTypes.clear ();
199
198
if (ir.shouldOutput (st, visitedTypes) && st->hasHelperMethods ()) {
200
- s << " \n " << st->generateHelperClass ();
199
+ s << " \n " << st->generateHelperClass (ir. locationManager );
201
200
}
202
201
}
203
202
204
203
for (const auto &u : ir.unions ) {
205
204
visitedTypes.clear ();
206
205
if (ir.shouldOutput (u, visitedTypes) && u->hasHelperMethods ()) {
207
- s << " \n " << u->generateHelperClass ();
206
+ s << " \n " << u->generateHelperClass (ir. locationManager );
208
207
}
209
208
}
210
209
@@ -321,7 +320,7 @@ bool IR::isTypeUsed(
321
320
for (const auto &typeDef : typeDefs) {
322
321
visitedTypesInner.clear ();
323
322
if (typeDef->usesType (type, false , visitedTypesInner)) {
324
- if (shouldOutput (typeDef, visitedTypes)) {
323
+ if (shouldOutputTypeDef (typeDef, visitedTypes)) {
325
324
return true ;
326
325
}
327
326
}
@@ -461,13 +460,21 @@ IR::~IR() {
461
460
}
462
461
463
462
template <typename T>
464
- bool IR::hasOutputtedDeclaration (
463
+ bool IR::hasOutputtedType (
465
464
const std::vector<std::shared_ptr<T>> &declarations) const {
466
465
std::vector<std::shared_ptr<const Type>> visitedTypes;
467
466
for (const auto &declaration : declarations) {
468
467
visitedTypes.clear ();
469
- if (shouldOutput (declaration, visitedTypes)) {
470
- return true ;
468
+ auto typeDefPointer =
469
+ std::dynamic_pointer_cast<const TypeDef>(declaration);
470
+ if (typeDefPointer) {
471
+ if (shouldOutputTypeDef (typeDefPointer, visitedTypes)) {
472
+ return true ;
473
+ }
474
+ } else {
475
+ if (shouldOutput (declaration, visitedTypes)) {
476
+ return true ;
477
+ }
471
478
}
472
479
}
473
480
return false ;
@@ -476,12 +483,31 @@ bool IR::hasOutputtedDeclaration(
476
483
bool IR::shouldOutput (
477
484
const std::shared_ptr<const LocatableType> &type,
478
485
std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
486
+ if (locationManager.isImported (*type->getLocation ())) {
487
+ return false ;
488
+ }
479
489
if (isTypeUsed (type, visitedTypes)) {
480
490
return true ;
481
491
}
482
- if (isAliasForOpaqueType (type.get ())) {
492
+ /* remove unused types from included files */
493
+ return locationManager.inMainFile (*type->getLocation ());
494
+ }
495
+
496
+ bool IR::shouldOutputTypeDef (
497
+ const std::shared_ptr<const TypeDef> &typeDef,
498
+ std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
499
+ if (isTypeUsed (typeDef, visitedTypes)) {
500
+ if (typeDef->wrapperForOpaqueType ()) {
501
+ /* it is not possible to get location of this typedef
502
+ * so the typedef cannot be imported from other bindings */
503
+ return true ;
504
+ }
505
+ return !locationManager.isImported (*typeDef->getLocation ());
506
+ }
507
+ if (isAliasForOpaqueType (typeDef.get ())) {
508
+ /* it does not matter where unused alias for opaque type is located */
483
509
return false ;
484
510
}
485
511
/* remove unused types from included files */
486
- return locationManager.inMainFile (*type ->getLocation ());
512
+ return locationManager.inMainFile (*typeDef ->getLocation ());
487
513
}
0 commit comments