@@ -77,39 +77,61 @@ void create_synthetic_sections(Context<E> &ctx) {
7777}
7878
7979template <typename E>
80- void resolve_symbols (Context<E> &ctx) {
81- Timer t (ctx, " resolve_symbols" );
82-
83- std::vector<InputFile<E> *> files;
84- append (files, ctx.objs );
85- append (files, ctx.dsos );
86-
87- // Register symbols
88- tbb::parallel_for_each (files, [&](InputFile<E> *file) {
89- file->resolve_symbols (ctx);
90- });
91-
92- // Mark reachable objects to decide which files to include
93- // into an output.
94- std::vector<InputFile<E> *> live_set = files;
95- std::erase_if (live_set, [](InputFile<E> *file) { return !file->is_alive ; });
96-
80+ static void mark_live_objects (Context<E> &ctx) {
9781 auto mark_symbol = [&](std::string_view name) {
9882 if (InputFile<E> *file = get_symbol (ctx, name)->file )
99- if (!file->is_alive .exchange (true ))
100- live_set.push_back (file);
83+ file->is_alive = true ;
10184 };
10285
10386 for (std::string_view name : ctx.arg .undefined )
10487 mark_symbol (name);
10588 for (std::string_view name : ctx.arg .require_defined )
10689 mark_symbol (name);
10790
108- tbb::parallel_for_each (live_set, [&](InputFile<E> *file,
109- tbb::feeder<InputFile<E> *> &feeder) {
110- file->mark_live_objects (ctx, [&](InputFile<E> *obj) { feeder.add (obj); });
91+ auto mark_file = [&](InputFile<E> *file, tbb::feeder<InputFile<E> *> &feeder) {
92+ if (file->is_alive )
93+ file->mark_live_objects (ctx, [&](InputFile<E> *obj) { feeder.add (obj); });
94+ };
95+
96+ tbb::parallel_for_each (ctx.objs , mark_file);
97+ tbb::parallel_for_each (ctx.dsos , mark_file);
98+ }
99+
100+ template <typename E>
101+ void resolve_symbols (Context<E> &ctx) {
102+ Timer t (ctx, " resolve_symbols" );
103+
104+ // Register symbols
105+ tbb::parallel_for_each (ctx.objs , [&](InputFile<E> *file) {
106+ file->resolve_symbols (ctx);
111107 });
112108
109+ tbb::parallel_for_each (ctx.dsos , [&](InputFile<E> *file) {
110+ file->resolve_symbols (ctx);
111+ });
112+
113+ // Do link-time optimization. We pass all IR object files to the
114+ // compiler backend to compile them into a few ELF object files.
115+ if (ctx.has_lto_object ) {
116+ Timer t (ctx, " do_lto" );
117+
118+ // The compiler backend needs to know how symbols are resolved,
119+ // so compute symbolvisibility, import/export bits, etc early.
120+ mark_live_objects (ctx);
121+ apply_version_script (ctx);
122+ parse_symbol_version (ctx);
123+ compute_import_export (ctx);
124+ do_lto (ctx);
125+ }
126+
127+ // Mark reachable objects to decide which files to include into an output.
128+ // This also merges symbol visibility.
129+ mark_live_objects (ctx);
130+
131+ std::vector<InputFile<E> *> files;
132+ append (files, ctx.objs );
133+ append (files, ctx.dsos );
134+
113135 // Remove symbols of eliminated files.
114136 tbb::parallel_for_each (files, [&](InputFile<E> *file) {
115137 if (!file->is_alive )
0 commit comments