This is an archive of the discontinued LLVM Phabricator instance.

[lld][WebAssembly] Fix for PIC output + TLS + non-shared-memory
ClosedPublic

Authored by sbc100 on May 21 2021, 11:00 AM.

Details

Summary

Prior to this change build with -shared/-pie and using TLS (but
without -shared-memory) would hit this assert:

"Currenly only a single data segment is supported in PIC mode"

This is because we were not including TLS data when merging data
segments. However, when we build without shared-memory (i.e. without
threads) we effectively lower away TLS into a normal active data
segment.. so we were ending up with two active data segments: the merged
data, and the lowered TLS data.

To fix this problem we can instead avoid combining data segments at
all when running in shared memory mode (because in this case all
segment initialization is passive). And then in non-shared memory
mode we know that TLS has been lowered and therefore we can can
and should combine all segments.

So with this new behavior we have two different modes:

  1. With shared memory / mutli-threaded: Never combine data segments since it is not necessary. (All data segments as passive already).
  1. Wihout shared memory / single-threaded: Combine *all* data segments since we treat TLS as normal data. (We end up with a single active data segment).

Diff Detail

Event Timeline

sbc100 created this revision.May 21 2021, 11:00 AM
sbc100 requested review of this revision.May 21 2021, 11:00 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 21 2021, 11:00 AM

Does avoiding combing data segments in shared-memory mode mean that there will have to be a lot more passive segment initializations run at load time, instead of just one before?

Does avoiding combing data segments in shared-memory mode mean that there will have to be a lot more passive segment initializations run at load time, instead of just one before?

Not really.. most programs only have .data and .rodata and so they are mostly combined already. The normal merging of .data.* etc is still performed either way. That is controlled by --no-/merge-data-segments which is on by default. This second level of merging was never about performance and we would not have it all if we could do arithmetic in the const exprs that place the segments.

Ah, got it. So is it the case that we have e.g. a single .tdata section that might be separate now, but just 1 or 2 and not scaling with the size of the program.
Mostly I just want to make sure we don't slow down loading too much, especially in the dylib case where it will already be slower than the non-library case.

lld/test/wasm/data-segments.ll
123–124

are these just data and rodata sections then?

lld/test/wasm/tls-non-shared-memory.s
102

I guess checking the content will ensure that the segments are merged. Does it also make sense to check that there are no additional segments?

sbc100 updated this revision to Diff 347122.May 21 2021, 2:11 PM
  • feedback
dschuff added inline comments.May 21 2021, 2:17 PM
lld/wasm/Writer.cpp
1428
sbc100 added inline comments.May 21 2021, 2:17 PM
lld/test/wasm/data-segments.ll
123–124

Yes, with passive (shared memory) segments we no longer combine them so they are separate. (as they would be for normal non-PIC code).

Added more checks below regarding the actual data.

lld/test/wasm/tls-non-shared-memory.s
102

I think this matches the above tests that checks for the two separate segments. I added a CHECK-NEXT to both of them to make sure there are no subsequent segments. I also added a comment here.

dschuff accepted this revision.May 21 2021, 2:18 PM
This revision is now accepted and ready to land.May 21 2021, 2:18 PM
This revision was landed with ongoing or failed builds.May 21 2021, 3:18 PM
This revision was automatically updated to reflect the committed changes.