Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 3 additions & 82 deletions src/passes/EmscriptenPIC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,6 @@

namespace wasm {

static Global* ensureGlobalImport(Module* module, Name name, Type type) {
// See if its already imported.
// FIXME: O(N)
ImportInfo info(*module);
if (auto* g = info.getImportedGlobal(ENV, name)) {
return g;
}
// Failing that create a new import.
auto import = new Global;
import->name = name;
import->module = ENV;
import->base = name;
import->type = type;
module->addGlobal(import);
return import;
}

static Function*
ensureFunctionImport(Module* module, Name name, Signature sig) {
// See if its already imported.
Expand Down Expand Up @@ -110,34 +93,8 @@ struct EmscriptenPIC : public WalkerPass<PostWalker<EmscriptenPIC>> {
Block* block = builder.makeBlock();
assignFunc->body = block;

bool hasSingleMemorySegment =
module->memory.exists && module->memory.segments.size() == 1;

for (Global* g : gotMemEntries) {
// If this global is defined in this module, we export its address
// relative to the relocatable memory. If we are in a main module, we can
// just use that location (since if other modules have this symbol too, we
// will "win" as we are loaded first). Otherwise, import a g$ getter. Note
// that this depends on memory having a single segment, so we know the
// offset, and that the export is a global.
auto base = g->base;
if (hasSingleMemorySegment && !sideModule) {
if (auto* ex = module->getExportOrNull(base)) {
if (ex->kind == ExternalKind::Global) {
// The base relative to which we are computed is the offset of the
// singleton segment.
auto* relativeBase = ExpressionManipulator::copy(
module->memory.segments[0].offset, *module);

auto* offset = builder.makeGlobalGet(
ex->value, module->getGlobal(ex->value)->type);
auto* add = builder.makeBinary(AddInt32, relativeBase, offset);
GlobalSet* globalSet = builder.makeGlobalSet(g->name, add);
block->list.push_back(globalSet);
continue;
}
}
}
Name getter(std::string("g$") + base.c_str());
ensureFunctionImport(module, getter, Signature(Type::none, Type::i32));
Expression* call = builder.makeCall(getter, {}, Type::i32);
Expand All @@ -147,52 +104,16 @@ struct EmscriptenPIC : public WalkerPass<PostWalker<EmscriptenPIC>> {

ImportInfo importInfo(*module);

// We may have to add things to the table.
Global* tableBase = nullptr;

for (Global* g : gotFuncEntries) {
// The function has to exist either as export or an import.
// Note that we don't search for the function by name since its internal
// name may be different.
auto* ex = module->getExportOrNull(g->base);
// If this is exported then it must be one of the functions implemented
// here, and if this is a main module, then we can simply place the
// function in the table: the loader will see it there and resolve all
// other uses to this one.
if (ex && !sideModule) {
assert(ex->kind == ExternalKind::Function);
auto* f = module->getFunction(ex->value);
if (f->imported()) {
Fatal() << "GOT.func entry is both imported and exported: "
<< g->base;
}
// The base relative to which we are computed is the offset of the
// singleton segment, which we must ensure exists
if (!tableBase) {
tableBase = ensureGlobalImport(module, TABLE_BASE, Type::i32);
}
if (!module->table.exists) {
module->table.exists = true;
}
if (module->table.segments.empty()) {
module->table.segments.resize(1);
module->table.segments[0].offset =
builder.makeGlobalGet(tableBase->name, Type::i32);
}
auto tableIndex =
TableUtils::getOrAppend(module->table, f->name, *module);
auto* c = LiteralUtils::makeFromInt32(tableIndex, Type::i32, *module);
auto* getBase = builder.makeGlobalGet(tableBase->name, Type::i32);
auto* add = builder.makeBinary(AddInt32, getBase, c);
auto* globalSet = builder.makeGlobalSet(g->name, add);
block->list.push_back(globalSet);
continue;
}
// This is imported or in a side module. Create an fp$ import to get the
// function table index from the dynamic loader.
// This is imported create an fp$ import to get the function table index
// from the dynamic loader.
auto* f = importInfo.getImportedFunction(ENV, g->base);
if (!f) {
if (!ex) {
if (!module->getExportOrNull(g->base)) {
Fatal() << "GOT.func entry with no import/export: " << g->base;
}
f = module->getFunction(ex->value);
Expand Down
20 changes: 0 additions & 20 deletions test/lld/gdollar_mainmodule.wat

This file was deleted.

73 changes: 0 additions & 73 deletions test/lld/gdollar_mainmodule.wat.out

This file was deleted.

21 changes: 6 additions & 15 deletions test/lld/main_module.wat.out
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
(type $i32_=>_i32 (func (param i32) (result i32)))
(import "env" "memory" (memory $0 0))
(data (global.get $gimport$2) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00")
(import "env" "table" (table $timport$1 1 funcref))
(elem (global.get $gimport$3) $print_message\28\29)
(import "env" "table" (table $timport$1 0 funcref))
(import "env" "__stack_pointer" (global $sp_import i32))
(import "env" "__memory_base" (global $gimport$2 i32))
(import "env" "__table_base" (global $gimport$3 i32))
(import "env" "puts" (func $puts (param i32) (result i32)))
(import "env" "g$external_var" (func $g$external_var (result i32)))
(import "env" "fp$puts$ii" (func $fp$puts$ii (result i32)))
(import "env" "fp$_Z13print_messagev$i" (func $fp$_Z13print_messagev$i (result i32)))
(global $gimport$5 (mut i32) (i32.const 0))
(global $gimport$6 (mut i32) (i32.const 0))
(global $gimport$7 (mut i32) (i32.const 0))
Expand All @@ -24,7 +24,6 @@
(export "ptr_puts" (global $global$0))
(export "ptr_local_func" (global $global$1))
(export "__data_end" (global $global))
(export "dynCall_i" (func $dynCall_i))
(export "__assign_got_enties" (func $__assign_got_enties))
(func $__wasm_call_ctors
(call $__wasm_apply_relocs)
Expand Down Expand Up @@ -66,31 +65,24 @@
(call $fp$puts$ii)
)
(global.set $gimport$7
(i32.add
(global.get $gimport$3)
(i32.const 0)
)
)
)
(func $dynCall_i (param $fptr i32) (result i32)
(call_indirect (type $none_=>_i32)
(local.get $fptr)
(call $fp$_Z13print_messagev$i)
)
)
)
(;
--BEGIN METADATA --
{
"staticBump": 4294966770,
"tableSize": 1,
"tableSize": 0,
"initializers": [
"__assign_got_enties",
"__wasm_call_ctors"
],
"declares": [
"puts",
"g$external_var",
"fp$puts$ii"
"fp$puts$ii",
"fp$_Z13print_messagev$i"
],
"externs": [
"___stack_pointer",
Expand All @@ -100,7 +92,6 @@
"exports": [
"__wasm_call_ctors",
"_Z13print_messagev",
"dynCall_i",
"__assign_got_enties"
],
"namedGlobals": {
Expand Down
24 changes: 6 additions & 18 deletions test/lld/main_module_table.wat.out
Original file line number Diff line number Diff line change
@@ -1,51 +1,39 @@
(module
(type $none_=>_none (func))
(type $i32_=>_none (func (param i32)))
(type $none_=>_i32 (func (result i32)))
(import "env" "__stack_pointer" (global $sp_import i32))
(import "env" "__table_base" (global $__table_base i32))
(table $0 1 funcref)
(elem (global.get $__table_base) $__stdio_write)
(import "env" "fp$__stdio_write$v" (func $fp$__stdio_write$v (result i32)))
(global $gimport$9 (mut i32) (i32.const 0))
(global $global i32 (i32.const 42))
(global $sp (mut i32) (global.get $sp_import))
(export "__stdio_write" (func $__stdio_write))
(export "__data_end" (global $global))
(export "dynCall_v" (func $dynCall_v))
(export "__assign_got_enties" (func $__assign_got_enties))
(func $__stdio_write
(nop)
)
(func $__assign_got_enties
(global.set $gimport$9
(i32.add
(global.get $__table_base)
(i32.const 0)
)
)
)
(func $dynCall_v (param $fptr i32)
(call_indirect (type $none_=>_none)
(local.get $fptr)
(call $fp$__stdio_write$v)
)
)
)
(;
--BEGIN METADATA --
{
"staticBump": 4294966770,
"tableSize": 1,
"tableSize": 0,
"initializers": [
"__assign_got_enties"
],
"declares": [
"fp$__stdio_write$v"
],
"externs": [
"___stack_pointer",
"___table_base"
"___stack_pointer"
],
"exports": [
"__stdio_write",
"dynCall_v",
"__assign_got_enties"
],
"namedGlobals": {
Expand Down
25 changes: 7 additions & 18 deletions test/lld/main_module_table_2.wat.out
Original file line number Diff line number Diff line change
@@ -1,51 +1,40 @@
(module
(type $none_=>_none (func))
(type $i32_=>_none (func (param i32)))
(import "env" "table" (table $timport$9 2 funcref))
(elem (global.get $__table_base) $__stdio_write)
(type $none_=>_i32 (func (result i32)))
(import "env" "table" (table $timport$9 1 funcref))
(import "env" "__stack_pointer" (global $sp_import i32))
(import "env" "__table_base" (global $__table_base i32))
(import "env" "fp$__stdio_write$v" (func $fp$__stdio_write$v (result i32)))
(global $gimport$9 (mut i32) (i32.const 0))
(global $global i32 (i32.const 42))
(global $sp (mut i32) (global.get $sp_import))
(export "__stdio_write" (func $__stdio_write))
(export "__data_end" (global $global))
(export "dynCall_v" (func $dynCall_v))
(export "__assign_got_enties" (func $__assign_got_enties))
(func $__stdio_write
(nop)
)
(func $__assign_got_enties
(global.set $gimport$9
(i32.add
(global.get $__table_base)
(i32.const 0)
)
)
)
(func $dynCall_v (param $fptr i32)
(call_indirect (type $none_=>_none)
(local.get $fptr)
(call $fp$__stdio_write$v)
)
)
)
(;
--BEGIN METADATA --
{
"staticBump": 4294966770,
"tableSize": 2,
"tableSize": 1,
"initializers": [
"__assign_got_enties"
],
"declares": [
"fp$__stdio_write$v"
],
"externs": [
"___stack_pointer",
"___table_base"
"___stack_pointer"
],
"exports": [
"__stdio_write",
"dynCall_v",
"__assign_got_enties"
],
"namedGlobals": {
Expand Down
Loading