@@ -78,7 +78,7 @@ void IR::addVarDefine(std::string name, std::shared_ptr<Variable> variable) {
7878}
7979
8080bool IR::libObjEmpty () const {
81- return functions.empty () && !hasOutputtedTypeDefs ( ) &&
81+ return functions.empty () && !hasOutputtedDeclaration (typeDefs ) &&
8282 !hasOutputtedDeclaration (structs) &&
8383 !hasOutputtedDeclaration (unions) && varDefines.empty () &&
8484 variables.empty ();
@@ -91,7 +91,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
9191 s << " package " << ir.packageName << " \n\n " ;
9292 }
9393
94- if (!ir.libObjEmpty () || ir.hasOutputtedEnums ( ) ||
94+ if (!ir.libObjEmpty () || ir.hasOutputtedDeclaration (ir. enums ) ||
9595 !ir.literalDefines .empty ()) {
9696 s << " import scala.scalanative._\n "
9797 << " import scala.scalanative.native._\n\n " ;
@@ -108,7 +108,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
108108 << " object " << objectName << " {\n " ;
109109
110110 for (const auto &typeDef : ir.typeDefs ) {
111- if (ir.typeDefInMainFile (*typeDef) || ir. isTypeUsed (typeDef)) {
111+ if (ir.isOutputted (typeDef)) {
112112 s << *typeDef;
113113 }
114114 }
@@ -136,18 +136,16 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
136136 s << " }\n\n " ;
137137 }
138138
139- if (ir.hasOutputtedEnums ( ) || ir.hasHelperMethods ()) {
139+ if (ir.hasOutputtedDeclaration (ir. enums ) || ir.hasHelperMethods ()) {
140140 s << " import " << objectName << " ._\n\n " ;
141141 }
142142
143- if (ir.hasOutputtedEnums ( )) {
143+ if (ir.hasOutputtedDeclaration (ir. enums )) {
144144 s << " object " << ir.libName << " Enums {\n " ;
145145
146146 std::string sep = " " ;
147147 for (const auto &e : ir.enums ) {
148- if (ir.inMainFile (*e) ||
149- (!e->isAnonymous () &&
150- ir.isTypeUsed (ir.getTypeDefWithName (e->getTypeAlias ())))) {
148+ if (ir.isOutputted (e)) {
151149 s << sep << *e;
152150 sep = " \n " ;
153151 }
@@ -160,13 +158,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
160158 s << " object " << ir.libName << " Helpers {\n " ;
161159
162160 for (const auto &st : ir.structs ) {
163- if (ir.isOutputted (st. get () ) && st->hasHelperMethods ()) {
161+ if (ir.isOutputted (st) && st->hasHelperMethods ()) {
164162 s << " \n " << st->generateHelperClass ();
165163 }
166164 }
167165
168166 for (const auto &u : ir.unions ) {
169- if (ir.isOutputted (u. get () )) {
167+ if (ir.isOutputted (u)) {
170168 s << " \n " << u->generateHelperClass ();
171169 }
172170 }
@@ -193,7 +191,7 @@ bool IR::hasHelperMethods() const {
193191 }
194192
195193 for (const auto &s : structs) {
196- if (isOutputted (s. get () ) && s->hasHelperMethods ()) {
194+ if (isOutputted (s) && s->hasHelperMethods ()) {
197195 return true ;
198196 }
199197 }
@@ -259,9 +257,46 @@ bool IR::typeIsUsedOnlyInTypeDefs(const std::shared_ptr<Type> &type) const {
259257 isTypeUsed (literalDefines, type, true ));
260258}
261259
262- bool IR::isTypeUsed (const std::shared_ptr<Type> &type) const {
263- return !(typeIsUsedOnlyInTypeDefs (type) &&
264- !isTypeUsed (typeDefs, type, false ));
260+ bool IR::isTypeUsed (const std::shared_ptr<Type> &type,
261+ bool checkRecursively) const {
262+ if (checkRecursively) {
263+ if (isTypeUsed (functions, type, true ) ||
264+ isTypeUsed (variables, type, true ) ||
265+ isTypeUsed (literalDefines, type, true )) {
266+ return true ;
267+ }
268+ /* type is used if there exists another type that is used and that
269+ * references this type */
270+ for (const auto &typeDef : typeDefs) {
271+ if (typeDef->usesType (type, false )) {
272+ if (isOutputted (typeDef)) {
273+ return true ;
274+ }
275+ }
276+ }
277+ for (const auto &s : structs) {
278+ /* stopOnTypeDefs parameter is true because because typedefs were
279+ * checked */
280+ if (s->usesType (type, true )) {
281+ if (isOutputted (s)) {
282+ return true ;
283+ }
284+ }
285+ }
286+ for (const auto &u : unions) {
287+ /* stopOnTypeDefs parameter is true because because typedefs were
288+ * checked */
289+ if (u->usesType (type, true )) {
290+ if (isOutputted (u)) {
291+ return true ;
292+ }
293+ }
294+ }
295+ return false ;
296+ } else {
297+ return !(typeIsUsedOnlyInTypeDefs (type) &&
298+ !isTypeUsed (typeDefs, type, false ));
299+ }
265300}
266301
267302void IR::setScalaNames () {
@@ -370,60 +405,38 @@ IR::~IR() {
370405 varDefines.clear ();
371406}
372407
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-
390408template <typename T> bool IR::inMainFile (const T &type) const {
391409 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 ;
410+ if (!location) {
411+ /* generated TypeDef */
412+ auto *typeDef = dynamic_cast <const TypeDef *>(&type);
413+ assert (typeDef);
414+ Type *innerType = typeDef->getType ().get ();
415+ if (isInstanceOf<Struct>(innerType)) {
416+ return inMainFile (*dynamic_cast <Struct *>(innerType));
401417 }
402- }
403- return false ;
404- }
405-
406- bool IR::hasOutputtedTypeDefs () const {
407- for (const auto &typeDef : typeDefs) {
408- if (inMainFile (*typeDef) || isTypeUsed (typeDef)) {
409- return true ;
418+ if (isInstanceOf<Union>(innerType)) {
419+ return inMainFile (*dynamic_cast <Union *>(innerType));
420+ }
421+ if (isInstanceOf<Enum>(innerType)) {
422+ return inMainFile (*dynamic_cast <Enum *>(innerType));
410423 }
411424 }
412- return false ;
425+ return location && locationManager. inMainFile (*location) ;
413426}
414427
415428template <typename T>
416429bool IR::hasOutputtedDeclaration (
417430 const std::vector<std::shared_ptr<T>> &declarations) const {
418431 for (const auto &declaration : declarations) {
419- if (isOutputted (declaration. get () )) {
432+ if (isOutputted (declaration)) {
420433 return true ;
421434 }
422435 }
423436 return false ;
424437}
425438
426- bool IR::isOutputted ( const StructOrUnion *structOrUnion) const {
427- return inMainFile (*structOrUnion) ||
428- isTypeUsed (getTypeDefWithName (structOrUnion-> getTypeAlias ()) );
439+ template < typename T>
440+ bool IR::isOutputted ( const std::shared_ptr<T> &type) const {
441+ return inMainFile (*type) || isTypeUsed (type, true );
429442}
0 commit comments