11#include " IR.h"
22#include " ../Utils.h"
3- #include " location/SourceLocation.h"
43
54IR::IR (std::string libName, std::string linkName, std::string objectName,
6- std::string packageName)
5+ std::string packageName, const LocationManager &locationManager )
76 : 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)) {}
99
1010void IR::addFunction (std::string name, std::vector<Parameter *> parameters,
1111 std::shared_ptr<Type> retType, bool isVariadic) {
@@ -78,8 +78,10 @@ void IR::addVarDefine(std::string name, std::shared_ptr<Variable> variable) {
7878}
7979
8080bool 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 ();
8385}
8486
8587llvm::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) {
8991 s << " package " << ir.packageName << " \n\n " ;
9092 }
9193
92- if (!ir.libObjEmpty () || !ir.enums .empty () || !ir.literalDefines .empty ()) {
94+ if (!ir.libObjEmpty () || ir.hasOutputtedEnums () ||
95+ !ir.literalDefines .empty ()) {
9396 s << " import scala.scalanative._\n "
9497 << " import scala.scalanative.native._\n\n " ;
9598 }
@@ -105,7 +108,9 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
105108 << " object " << objectName << " {\n " ;
106109
107110 for (const auto &typeDef : ir.typeDefs ) {
108- s << *typeDef;
111+ if (ir.typeDefInMainFile (*typeDef) || ir.isTypeUsed (typeDef)) {
112+ s << *typeDef;
113+ }
109114 }
110115
111116 for (const auto &variable : ir.variables ) {
@@ -131,19 +136,20 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
131136 s << " }\n\n " ;
132137 }
133138
134- if (! ir.enums . empty () || ir.hasHelperMethods ()) {
139+ if (ir.hasOutputtedEnums () || ir.hasHelperMethods ()) {
135140 s << " import " << objectName << " ._\n\n " ;
136141 }
137142
138- if (! ir.enums . empty ()) {
143+ if (ir.hasOutputtedEnums ()) {
139144 s << " object " << ir.libName << " Enums {\n " ;
140145
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 " ;
147153 }
148154 }
149155
@@ -154,13 +160,15 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
154160 s << " object " << ir.libName << " Helpers {\n " ;
155161
156162 for (const auto &st : ir.structs ) {
157- if (st->hasHelperMethods ()) {
163+ if (ir. isOutputted (st. get ()) && st->hasHelperMethods ()) {
158164 s << " \n " << st->generateHelperClass ();
159165 }
160166 }
161167
162168 for (const auto &u : ir.unions ) {
163- s << " \n " << u->generateHelperClass ();
169+ if (ir.isOutputted (u.get ())) {
170+ s << " \n " << u->generateHelperClass ();
171+ }
164172 }
165173
166174 s << " }\n\n " ;
@@ -173,19 +181,19 @@ void IR::generate(const std::string &excludePrefix) {
173181 if (!generated) {
174182 setScalaNames ();
175183 filterDeclarations (excludePrefix);
176- removeUnusedExternalTypedefs ();
184+ // removeUnusedExternalTypedefs();
177185 generated = true ;
178186 }
179187}
180188
181189bool IR::hasHelperMethods () const {
182- if (!unions. empty ( )) {
190+ if (hasOutputtedDeclaration (unions )) {
183191 /* all unions have helper methods */
184192 return true ;
185193 }
186194
187195 for (const auto &s : structs) {
188- if (s->hasHelperMethods ()) {
196+ if (isOutputted (s. get ()) && s->hasHelperMethods ()) {
189197 return true ;
190198 }
191199 }
@@ -328,7 +336,7 @@ std::shared_ptr<Variable> IR::addVariable(const std::string &name,
328336 return variable;
329337}
330338
331- std::shared_ptr<TypeDef> IR::getTypeDefWithName (const std::string &name) {
339+ std::shared_ptr<TypeDef> IR::getTypeDefWithName (const std::string &name) const {
332340 /* nullptr is returned in 2 cases:
333341 * 1. TypeTranslator translates opaque struct/union type for which TypeDef
334342 * was not created.
@@ -338,8 +346,8 @@ std::shared_ptr<TypeDef> IR::getTypeDefWithName(const std::string &name) {
338346}
339347
340348template <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 {
343351 for (auto it = declarations.begin (), end = declarations.end (); it != end;
344352 ++it) {
345353 T declaration = (*it);
@@ -362,55 +370,60 @@ IR::~IR() {
362370 varDefines.clear ();
363371}
364372
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 ;
378401 }
379402 }
380- removeUnusedExternalTypeAndTypedef (structs);
381- removeUnusedExternalTypeAndTypedef (unions);
382- removeUnusedExternalTypeAndTypedef (enums);
403+ return false ;
383404}
384405
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 ;
394410 }
395411 }
412+ return false ;
396413}
397414
398415template <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 ;
414421 }
415422 }
423+ return false ;
424+ }
425+
426+ bool IR::isOutputted (const StructOrUnion *structOrUnion) const {
427+ return inMainFile (*structOrUnion) ||
428+ isTypeUsed (getTypeDefWithName (structOrUnion->getTypeAlias ()));
416429}
0 commit comments