@@ -77,39 +77,61 @@ void create_synthetic_sections(Context<E> &ctx) {
77
77
}
78
78
79
79
template <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) {
97
81
auto mark_symbol = [&](std::string_view name) {
98
82
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 ;
101
84
};
102
85
103
86
for (std::string_view name : ctx.arg .undefined )
104
87
mark_symbol (name);
105
88
for (std::string_view name : ctx.arg .require_defined )
106
89
mark_symbol (name);
107
90
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);
111
107
});
112
108
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
+
113
135
// Remove symbols of eliminated files.
114
136
tbb::parallel_for_each (files, [&](InputFile<E> *file) {
115
137
if (!file->is_alive )
0 commit comments