Skip to content

Commit 005e14c

Browse files
TerrorJackdmjio
authored andcommitted
wasm-ld: split up __wasm_apply_data_relocs
1 parent 0ebf7b4 commit 005e14c

File tree

4 files changed

+71
-20
lines changed

4 files changed

+71
-20
lines changed

lld/wasm/InputChunks.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,12 +361,11 @@ uint64_t InputChunk::getVA(uint64_t offset) const {
361361
// Generate code to apply relocations to the data section at runtime.
362362
// This is only called when generating shared libraries (PIC) where address are
363363
// not known at static link time.
364-
bool InputChunk::generateRelocationCode(raw_ostream &os) const {
364+
void InputChunk::generateRelocationCode(std::vector<std::string> &funcs) const {
365365
LLVM_DEBUG(dbgs() << "generating runtime relocations: " << name
366366
<< " count=" << relocations.size() << "\n");
367367

368368
bool is64 = ctx.arg.is64.value_or(false);
369-
bool generated = false;
370369
unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST
371370
: WASM_OPCODE_I32_CONST;
372371
unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
@@ -385,6 +384,14 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
385384
if (!requiresRuntimeReloc)
386385
continue;
387386

387+
if (funcs.empty() || funcs.back().size() >= 7654300) {
388+
funcs.emplace_back(std::string());
389+
raw_string_ostream os(funcs.back());
390+
writeUleb128(os, 0, "num locals");
391+
}
392+
393+
raw_string_ostream os(funcs.back());
394+
388395
LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type)
389396
<< " addend=" << rel.Addend << " index=" << rel.Index
390397
<< " output offset=" << offset << "\n");
@@ -439,9 +446,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
439446
writeU8(os, opcode_reloc_store, "I32_STORE");
440447
writeUleb128(os, 2, "align");
441448
writeUleb128(os, 0, "offset");
442-
generated = true;
443449
}
444-
return generated;
445450
}
446451

447452
// Split WASM_SEG_FLAG_STRINGS section. Such a section is a sequence of

lld/wasm/InputChunks.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class InputChunk {
7878

7979
size_t getNumRelocations() const { return relocations.size(); }
8080
void writeRelocations(llvm::raw_ostream &os) const;
81-
bool generateRelocationCode(raw_ostream &os) const;
81+
void generateRelocationCode(std::vector<std::string> &funcs) const;
8282

8383
bool isTLS() const { return flags & llvm::wasm::WASM_SEG_FLAG_TLS; }
8484
bool isRetained() const { return flags & llvm::wasm::WASM_SEG_FLAG_RETAIN; }

lld/wasm/SyntheticSections.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ void FunctionSection::writeBody() {
299299
void FunctionSection::addFunction(InputFunction *func) {
300300
if (!func->live)
301301
return;
302+
if (func->hasFunctionIndex())
303+
return;
302304
uint32_t functionIndex =
303305
out.importSec->getNumImportedFunctions() + inputFunctions.size();
304306
inputFunctions.emplace_back(func);

lld/wasm/Writer.cpp

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,20 +1459,21 @@ void Writer::createStartFunction() {
14591459
void Writer::createApplyDataRelocationsFunction() {
14601460
LLVM_DEBUG(dbgs() << "createApplyDataRelocationsFunction\n");
14611461
// First write the body's contents to a string.
1462-
std::string bodyContent;
1462+
std::vector<std::string> funcs;
14631463
{
1464-
raw_string_ostream os(bodyContent);
1465-
writeUleb128(os, 0, "num locals");
1466-
bool generated = false;
14671464
for (const OutputSegment *seg : segments)
14681465
if (!ctx.arg.sharedMemory || !seg->isTLS())
14691466
for (const InputChunk *inSeg : seg->inputSegments)
1470-
generated |= inSeg->generateRelocationCode(os);
1467+
inSeg->generateRelocationCode(funcs);
1468+
}
14711469

1472-
if (!generated) {
1473-
LLVM_DEBUG(dbgs() << "skipping empty __wasm_apply_data_relocs\n");
1474-
return;
1475-
}
1470+
if (funcs.empty()) {
1471+
LLVM_DEBUG(dbgs() << "skipping empty __wasm_apply_data_relocs\n");
1472+
return;
1473+
}
1474+
1475+
for (auto &func : funcs) {
1476+
raw_string_ostream os(func);
14761477
writeU8(os, WASM_OPCODE_END, "END");
14771478
}
14781479

@@ -1485,24 +1486,67 @@ void Writer::createApplyDataRelocationsFunction() {
14851486
make<SyntheticFunction>(nullSignature, "__wasm_apply_data_relocs"));
14861487
def->markLive();
14871488

1488-
createFunction(def, bodyContent);
1489+
if (funcs.size() == 1) {
1490+
createFunction(def, funcs.back());
1491+
return;
1492+
}
1493+
1494+
std::string body;
1495+
{
1496+
raw_string_ostream os(body);
1497+
writeUleb128(os, 0, "num locals");
1498+
1499+
for (std::size_t i = 0; i < funcs.size(); ++i) {
1500+
auto &name =
1501+
*make<std::string>("__wasm_apply_data_relocs_" + std::to_string(i));
1502+
auto *func = make<SyntheticFunction>(nullSignature, name);
1503+
auto *def = symtab->addSyntheticFunction(
1504+
name, WASM_SYMBOL_VISIBILITY_HIDDEN, func);
1505+
def->markLive();
1506+
// Normally this shouldn't be called manually for a synthetic
1507+
// function, since the function indices in
1508+
// ctx.syntheticFunctions will be calculated later (check
1509+
// functionSec->addFunction call hierarchy for details).
1510+
// However, at this point we already need the correct index. The
1511+
// solution is to place the new synthetic function eagerly, and
1512+
// also making addFunction idempotent by skipping when there's
1513+
// already a function index.
1514+
out.functionSec->addFunction(func);
1515+
createFunction(def, funcs[i]);
1516+
1517+
writeU8(os, WASM_OPCODE_CALL, "CALL");
1518+
writeUleb128(os, def->getFunctionIndex(), "function index");
1519+
}
1520+
1521+
writeU8(os, WASM_OPCODE_END, "END");
1522+
}
1523+
createFunction(def, body);
14891524
}
14901525

14911526
void Writer::createApplyTLSRelocationsFunction() {
14921527
LLVM_DEBUG(dbgs() << "createApplyTLSRelocationsFunction\n");
1493-
std::string bodyContent;
1528+
std::vector<std::string> funcs;
14941529
{
1495-
raw_string_ostream os(bodyContent);
1496-
writeUleb128(os, 0, "num locals");
14971530
for (const OutputSegment *seg : segments)
14981531
if (seg->isTLS())
14991532
for (const InputChunk *inSeg : seg->inputSegments)
1500-
inSeg->generateRelocationCode(os);
1533+
inSeg->generateRelocationCode(funcs);
1534+
}
15011535

1536+
if (funcs.empty()) {
1537+
funcs.emplace_back(std::string());
1538+
raw_string_ostream os(funcs.back());
1539+
writeUleb128(os, 0, "num locals");
1540+
}
1541+
1542+
for (auto &func : funcs) {
1543+
raw_string_ostream os(func);
15021544
writeU8(os, WASM_OPCODE_END, "END");
15031545
}
15041546

1505-
createFunction(WasmSym::applyTLSRelocs, bodyContent);
1547+
assert(funcs.size() == 1);
1548+
1549+
createFunction(WasmSym::applyTLSRelocs, funcs.back());
15061550
}
15071551

15081552
// Similar to createApplyDataRelocationsFunction but generates relocation code

0 commit comments

Comments
 (0)