Skip to content

Commit 33a2b52

Browse files
committed
[WebAssembly] Backport custom import name changes for LLVM to 8.0.
Specifically, this backports r352479, r352931, r353474, and r353476 to the 8.0 branch. The trunk patches don't apply cleanly to 8.0 due to some contemporaneous mass-rename and mass-clang-tidy patches, so this merges them to simplify rebasing. r352479 [WebAssembly] Re-enable main-function signature rewriting r352931 [WebAssembly] Add codegen support for the import_field attribute r353474 [WebAssembly] Fix imported function symbol names that differ from their import names in the .o format r353476 [WebAssembly] Update test output after rL353474. NFC. By Dan Gohman! llvm-svn: 353835
1 parent 16b7c08 commit 33a2b52

19 files changed

+176
-62
lines changed

llvm/include/llvm/BinaryFormat/Wasm.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ struct WasmSymbolInfo {
165165
StringRef Name;
166166
uint8_t Kind;
167167
uint32_t Flags;
168-
StringRef Module; // For undefined symbols the module name of the import
168+
StringRef ImportModule; // For undefined symbols the module of the import
169+
StringRef ImportName; // For undefined symbols the name of the import
169170
union {
170171
// For function or global symbols, the index in function or global index
171172
// space.
@@ -284,6 +285,7 @@ const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
284285
const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
285286
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
286287
const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
288+
const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40;
287289

288290
#define WASM_RELOC(name, value) name = value,
289291

llvm/include/llvm/MC/MCSymbolWasm.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ class MCSymbolWasm : public MCSymbol {
1919
bool IsWeak = false;
2020
bool IsHidden = false;
2121
bool IsComdat = false;
22-
std::string ModuleName;
22+
Optional<std::string> ImportModule;
23+
Optional<std::string> ImportName;
2324
wasm::WasmSignature *Signature = nullptr;
2425
Optional<wasm::WasmGlobalType> GlobalType;
2526
Optional<wasm::WasmEventType> EventType;
@@ -32,7 +33,7 @@ class MCSymbolWasm : public MCSymbol {
3233
// Use a module name of "env" for now, for compatibility with existing tools.
3334
// This is temporary, and may change, as the ABI is not yet stable.
3435
MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary)
35-
: MCSymbol(SymbolKindWasm, Name, isTemporary), ModuleName("env") {}
36+
: MCSymbol(SymbolKindWasm, Name, isTemporary) {}
3637
static bool classof(const MCSymbol *S) { return S->isWasm(); }
3738

3839
const MCExpr *getSize() const { return SymbolSize; }
@@ -55,8 +56,21 @@ class MCSymbolWasm : public MCSymbol {
5556
bool isComdat() const { return IsComdat; }
5657
void setComdat(bool isComdat) { IsComdat = isComdat; }
5758

58-
const StringRef getModuleName() const { return ModuleName; }
59-
void setModuleName(StringRef Name) { ModuleName = Name; }
59+
const StringRef getImportModule() const {
60+
if (ImportModule.hasValue()) {
61+
return ImportModule.getValue();
62+
}
63+
return "env";
64+
}
65+
void setImportModule(StringRef Name) { ImportModule = Name; }
66+
67+
const StringRef getImportName() const {
68+
if (ImportName.hasValue()) {
69+
return ImportName.getValue();
70+
}
71+
return getName();
72+
}
73+
void setImportName(StringRef Name) { ImportName = Name; }
6074

6175
const wasm::WasmSignature *getSignature() const { return Signature; }
6276
void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; }

llvm/lib/MC/WasmObjectWriter.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,8 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
982982
case wasm::WASM_SYMBOL_TYPE_GLOBAL:
983983
case wasm::WASM_SYMBOL_TYPE_EVENT:
984984
encodeULEB128(Sym.ElementIndex, W.OS);
985-
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
985+
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
986+
(Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
986987
writeString(Sym.Name);
987988
break;
988989
case wasm::WASM_SYMBOL_TYPE_DATA:
@@ -1162,8 +1163,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
11621163
MCSymbolWasm *MemorySym =
11631164
cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory"));
11641165
wasm::WasmImport MemImport;
1165-
MemImport.Module = MemorySym->getModuleName();
1166-
MemImport.Field = MemorySym->getName();
1166+
MemImport.Module = MemorySym->getImportModule();
1167+
MemImport.Field = MemorySym->getImportName();
11671168
MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
11681169
Imports.push_back(MemImport);
11691170

@@ -1173,8 +1174,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
11731174
MCSymbolWasm *TableSym =
11741175
cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table"));
11751176
wasm::WasmImport TableImport;
1176-
TableImport.Module = TableSym->getModuleName();
1177-
TableImport.Field = TableSym->getName();
1177+
TableImport.Module = TableSym->getImportModule();
1178+
TableImport.Field = TableSym->getImportName();
11781179
TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
11791180
TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF;
11801181
Imports.push_back(TableImport);
@@ -1200,8 +1201,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
12001201
if (!WS.isDefined() && !WS.isComdat()) {
12011202
if (WS.isFunction()) {
12021203
wasm::WasmImport Import;
1203-
Import.Module = WS.getModuleName();
1204-
Import.Field = WS.getName();
1204+
Import.Module = WS.getImportModule();
1205+
Import.Field = WS.getImportName();
12051206
Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
12061207
Import.SigIndex = getFunctionType(WS);
12071208
Imports.push_back(Import);
@@ -1211,8 +1212,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
12111212
report_fatal_error("undefined global symbol cannot be weak");
12121213

12131214
wasm::WasmImport Import;
1214-
Import.Module = WS.getModuleName();
1215-
Import.Field = WS.getName();
1215+
Import.Module = WS.getImportModule();
1216+
Import.Field = WS.getImportName();
12161217
Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
12171218
Import.Global = WS.getGlobalType();
12181219
Imports.push_back(Import);
@@ -1222,8 +1223,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
12221223
report_fatal_error("undefined event symbol cannot be weak");
12231224

12241225
wasm::WasmImport Import;
1225-
Import.Module = WS.getModuleName();
1226-
Import.Field = WS.getName();
1226+
Import.Module = WS.getImportModule();
1227+
Import.Field = WS.getImportName();
12271228
Import.Kind = wasm::WASM_EXTERNAL_EVENT;
12281229
Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
12291230
Import.Event.SigIndex = getEventType(WS);
@@ -1448,6 +1449,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
14481449
Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
14491450
if (WS.isUndefined())
14501451
Flags |= wasm::WASM_SYMBOL_UNDEFINED;
1452+
if (WS.getName() != WS.getImportName())
1453+
Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
14511454

14521455
wasm::WasmSymbolInfo Info;
14531456
Info.Name = WS.getName();

llvm/lib/Object/WasmObjectFile.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
505505
Function.SymbolName = Info.Name;
506506
} else {
507507
wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
508+
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
509+
Info.Name = readString(Ctx);
510+
else
511+
Info.Name = Import.Field;
508512
Signature = &Signatures[Import.SigIndex];
509-
Info.Name = Import.Field;
510-
Info.Module = Import.Module;
513+
Info.ImportName = Import.Field;
514+
Info.ImportModule = Import.Module;
511515
}
512516
break;
513517

@@ -530,8 +534,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
530534
Global.SymbolName = Info.Name;
531535
} else {
532536
wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
533-
Info.Name = Import.Field;
537+
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
538+
Info.Name = readString(Ctx);
539+
else
540+
Info.Name = Import.Field;
534541
GlobalType = &Import.Global;
542+
Info.ImportName = Import.Field;
543+
Info.ImportModule = Import.Module;
535544
}
536545
break;
537546

@@ -585,9 +594,14 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
585594

586595
} else {
587596
wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
597+
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
598+
Info.Name = readString(Ctx);
599+
else
600+
Info.Name = Import.Field;
588601
EventType = &Import.Event;
589602
Signature = &Signatures[EventType->SigIndex];
590-
Info.Name = Import.Field;
603+
Info.ImportName = Import.Field;
604+
Info.ImportModule = Import.Module;
591605
}
592606
break;
593607
}

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,15 @@ void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) {
113113
}
114114

115115
void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym,
116-
StringRef ModuleName) {
117-
OS << "\t.import_module\t" << Sym->getName() << ", " << ModuleName << '\n';
116+
StringRef ImportModule) {
117+
OS << "\t.import_module\t" << Sym->getName() << ", "
118+
<< ImportModule << '\n';
119+
}
120+
121+
void WebAssemblyTargetAsmStreamer::emitImportName(const MCSymbolWasm *Sym,
122+
StringRef ImportName) {
123+
OS << "\t.import_name\t" << Sym->getName() << ", "
124+
<< ImportName << '\n';
118125
}
119126

120127
void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) {

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ class WebAssemblyTargetStreamer : public MCTargetStreamer {
4545
virtual void emitEventType(const MCSymbolWasm *Sym) = 0;
4646
/// .import_module
4747
virtual void emitImportModule(const MCSymbolWasm *Sym,
48-
StringRef ModuleName) = 0;
48+
StringRef ImportModule) = 0;
49+
/// .import_name
50+
virtual void emitImportName(const MCSymbolWasm *Sym,
51+
StringRef ImportName) = 0;
4952

5053
protected:
5154
void emitValueType(wasm::ValType Type);
@@ -67,7 +70,8 @@ class WebAssemblyTargetAsmStreamer final : public WebAssemblyTargetStreamer {
6770
void emitIndIdx(const MCExpr *Value) override;
6871
void emitGlobalType(const MCSymbolWasm *Sym) override;
6972
void emitEventType(const MCSymbolWasm *Sym) override;
70-
void emitImportModule(const MCSymbolWasm *Sym, StringRef ModuleName) override;
73+
void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule) override;
74+
void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override;
7175
};
7276

7377
/// This part is for Wasm object output
@@ -82,7 +86,9 @@ class WebAssemblyTargetWasmStreamer final : public WebAssemblyTargetStreamer {
8286
void emitGlobalType(const MCSymbolWasm *Sym) override {}
8387
void emitEventType(const MCSymbolWasm *Sym) override {}
8488
void emitImportModule(const MCSymbolWasm *Sym,
85-
StringRef ModuleName) override {}
89+
StringRef ImportModule) override {}
90+
void emitImportName(const MCSymbolWasm *Sym,
91+
StringRef ImportName) override {}
8692
};
8793

8894
/// This part is for null output
@@ -98,6 +104,7 @@ class WebAssemblyTargetNullStreamer final : public WebAssemblyTargetStreamer {
98104
void emitGlobalType(const MCSymbolWasm *) override {}
99105
void emitEventType(const MCSymbolWasm *) override {}
100106
void emitImportModule(const MCSymbolWasm *, StringRef) override {}
107+
void emitImportName(const MCSymbolWasm *, StringRef) override {}
101108
};
102109

103110
} // end namespace llvm

llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,16 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
111111
F.hasFnAttribute("wasm-import-module")) {
112112
StringRef Name =
113113
F.getFnAttribute("wasm-import-module").getValueAsString();
114-
Sym->setModuleName(Name);
114+
Sym->setImportModule(Name);
115115
getTargetStreamer()->emitImportModule(Sym, Name);
116116
}
117+
if (TM.getTargetTriple().isOSBinFormatWasm() &&
118+
F.hasFnAttribute("wasm-import-name")) {
119+
StringRef Name =
120+
F.getFnAttribute("wasm-import-name").getValueAsString();
121+
Sym->setImportName(Name);
122+
getTargetStreamer()->emitImportName(Sym, Name);
123+
}
117124
}
118125
}
119126

llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@ using namespace llvm;
3636

3737
#define DEBUG_TYPE "wasm-fix-function-bitcasts"
3838

39-
static cl::opt<bool>
40-
TemporaryWorkarounds("wasm-temporary-workarounds",
41-
cl::desc("Apply certain temporary workarounds"),
42-
cl::init(true), cl::Hidden);
43-
4439
namespace {
4540
class FixFunctionBitcasts final : public ModulePass {
4641
StringRef getPassName() const override {
@@ -227,6 +222,17 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
227222
return Wrapper;
228223
}
229224

225+
// Test whether a main function with type FuncTy should be rewritten to have
226+
// type MainTy.
227+
bool shouldFixMainFunction(FunctionType *FuncTy, FunctionType *MainTy) {
228+
// Only fix the main function if it's the standard zero-arg form. That way,
229+
// the standard cases will work as expected, and users will see signature
230+
// mismatches from the linker for non-standard cases.
231+
return FuncTy->getReturnType() == MainTy->getReturnType() &&
232+
FuncTy->getNumParams() == 0 &&
233+
!FuncTy->isVarArg();
234+
}
235+
230236
bool FixFunctionBitcasts::runOnModule(Module &M) {
231237
LLVM_DEBUG(dbgs() << "********** Fix Function Bitcasts **********\n");
232238

@@ -243,14 +249,14 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
243249
// "int main(int argc, char *argv[])", create an artificial call with it
244250
// bitcasted to that type so that we generate a wrapper for it, so that
245251
// the C runtime can call it.
246-
if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") {
252+
if (F.getName() == "main") {
247253
Main = &F;
248254
LLVMContext &C = M.getContext();
249255
Type *MainArgTys[] = {Type::getInt32Ty(C),
250256
PointerType::get(Type::getInt8PtrTy(C), 0)};
251257
FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys,
252258
/*isVarArg=*/false);
253-
if (F.getFunctionType() != MainTy) {
259+
if (shouldFixMainFunction(F.getFunctionType(), MainTy)) {
254260
LLVM_DEBUG(dbgs() << "Found `main` function with incorrect type: "
255261
<< *F.getFunctionType() << "\n");
256262
Value *Args[] = {UndefValue::get(MainArgTys[0]),
@@ -298,12 +304,18 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
298304
Main->setName("__original_main");
299305
Function *MainWrapper =
300306
cast<Function>(CallMain->getCalledValue()->stripPointerCasts());
301-
MainWrapper->setName("main");
302-
MainWrapper->setLinkage(Main->getLinkage());
303-
MainWrapper->setVisibility(Main->getVisibility());
304-
Main->setLinkage(Function::PrivateLinkage);
305-
Main->setVisibility(Function::DefaultVisibility);
306307
delete CallMain;
308+
if (Main->isDeclaration()) {
309+
// The wrapper is not needed in this case as we don't need to export
310+
// it to anyone else.
311+
MainWrapper->eraseFromParent();
312+
} else {
313+
// Otherwise give the wrapper the same linkage as the original main
314+
// function, so that it can be called from the same places.
315+
MainWrapper->setName("main");
316+
MainWrapper->setLinkage(Main->getLinkage());
317+
MainWrapper->setVisibility(Main->getVisibility());
318+
}
307319
}
308320

309321
return true;

llvm/test/CodeGen/WebAssembly/call.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -wasm-temporary-workarounds=false -mattr=+sign-ext,+simd128 | FileCheck %s
2-
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 -wasm-temporary-workarounds=false -mattr=+sign-ext,+simd128 | FileCheck %s
1+
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+sign-ext,+simd128 | FileCheck %s
2+
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 -mattr=+sign-ext,+simd128 | FileCheck %s
33

44
; Test that basic call operations assemble as expected.
55

llvm/test/CodeGen/WebAssembly/function-bitcasts-varargs.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false -wasm-keep-registers | FileCheck %s
1+
; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
22

33
; Test that function pointer casts casting away varargs are replaced with
44
; wrappers.

llvm/test/CodeGen/WebAssembly/function-bitcasts.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions -wasm-temporary-workarounds=false | FileCheck %s
1+
; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions | FileCheck %s
22

33
; Test that function pointer casts are replaced with wrappers.
44

llvm/test/CodeGen/WebAssembly/import-module.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ define void @test() {
1212
declare void @foo() #0
1313
declare void @plain()
1414

15-
attributes #0 = { "wasm-import-module"="bar" }
15+
attributes #0 = { "wasm-import-module"="bar" "wasm-import-name"="qux" }
1616

1717
; CHECK-NOT: .import_module plain
1818
; CHECK: .import_module foo, bar
19+
; CHECK: .import_name foo, qux
1920
; CHECK-NOT: .import_module plain
Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s
1+
; RUN: llc < %s -asm-verbose=false | FileCheck %s
22

33
; Test main functions with alternate signatures.
44

55
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
66
target triple = "wasm32-unknown-unknown"
77

8-
declare void @main()
8+
declare i32 @main()
99

10-
define void @foo() {
11-
call void @main()
12-
ret void
10+
define i32 @foo() {
11+
%t = call i32 @main()
12+
ret i32 %t
1313
}
1414

15-
; CHECK-NOT: __original_main
1615
; CHECK-LABEL: foo:
17-
; CHECK-NEXT: .functype foo () -> ()
18-
; CHECK-NEXT: call main@FUNCTION
16+
; CHECK-NEXT: .functype foo () -> (i32)
17+
; CHECK-NEXT: call __original_main@FUNCTION
1918
; CHECK-NEXT: end_function
20-
; CHECK-NOT: __original_main

0 commit comments

Comments
 (0)