llvm.org GIT mirror llvm / 831b204
[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! git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_80@353835 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 6 months ago
19 changed file(s) with 176 addition(s) and 62 deletion(s). Raw diff Collapse all Expand all
164164 StringRef Name;
165165 uint8_t Kind;
166166 uint32_t Flags;
167 StringRef Module; // For undefined symbols the module name of the import
167 StringRef ImportModule; // For undefined symbols the module of the import
168 StringRef ImportName; // For undefined symbols the name of the import
168169 union {
169170 // For function or global symbols, the index in function or global index
170171 // space.
283284 const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
284285 const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
285286 const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
287 const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40;
286288
287289 #define WASM_RELOC(name, value) name = value,
288290
1818 bool IsWeak = false;
1919 bool IsHidden = false;
2020 bool IsComdat = false;
21 std::string ModuleName;
21 Optional ImportModule;
22 Optional ImportName;
2223 wasm::WasmSignature *Signature = nullptr;
2324 Optional GlobalType;
2425 Optional EventType;
3132 // Use a module name of "env" for now, for compatibility with existing tools.
3233 // This is temporary, and may change, as the ABI is not yet stable.
3334 MCSymbolWasm(const StringMapEntry *Name, bool isTemporary)
34 : MCSymbol(SymbolKindWasm, Name, isTemporary), ModuleName("env") {}
35 : MCSymbol(SymbolKindWasm, Name, isTemporary) {}
3536 static bool classof(const MCSymbol *S) { return S->isWasm(); }
3637
3738 const MCExpr *getSize() const { return SymbolSize; }
5455 bool isComdat() const { return IsComdat; }
5556 void setComdat(bool isComdat) { IsComdat = isComdat; }
5657
57 const StringRef getModuleName() const { return ModuleName; }
58 void setModuleName(StringRef Name) { ModuleName = Name; }
58 const StringRef getImportModule() const {
59 if (ImportModule.hasValue()) {
60 return ImportModule.getValue();
61 }
62 return "env";
63 }
64 void setImportModule(StringRef Name) { ImportModule = Name; }
65
66 const StringRef getImportName() const {
67 if (ImportName.hasValue()) {
68 return ImportName.getValue();
69 }
70 return getName();
71 }
72 void setImportName(StringRef Name) { ImportName = Name; }
5973
6074 const wasm::WasmSignature *getSignature() const { return Signature; }
6175 void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; }
981981 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
982982 case wasm::WASM_SYMBOL_TYPE_EVENT:
983983 encodeULEB128(Sym.ElementIndex, W.OS);
984 if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
984 if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
985 (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
985986 writeString(Sym.Name);
986987 break;
987988 case wasm::WASM_SYMBOL_TYPE_DATA:
11611162 MCSymbolWasm *MemorySym =
11621163 cast(Ctx.getOrCreateSymbol("__linear_memory"));
11631164 wasm::WasmImport MemImport;
1164 MemImport.Module = MemorySym->getModuleName();
1165 MemImport.Field = MemorySym->getName();
1165 MemImport.Module = MemorySym->getImportModule();
1166 MemImport.Field = MemorySym->getImportName();
11661167 MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
11671168 Imports.push_back(MemImport);
11681169
11721173 MCSymbolWasm *TableSym =
11731174 cast(Ctx.getOrCreateSymbol("__indirect_function_table"));
11741175 wasm::WasmImport TableImport;
1175 TableImport.Module = TableSym->getModuleName();
1176 TableImport.Field = TableSym->getName();
1176 TableImport.Module = TableSym->getImportModule();
1177 TableImport.Field = TableSym->getImportName();
11771178 TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
11781179 TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF;
11791180 Imports.push_back(TableImport);
11991200 if (!WS.isDefined() && !WS.isComdat()) {
12001201 if (WS.isFunction()) {
12011202 wasm::WasmImport Import;
1202 Import.Module = WS.getModuleName();
1203 Import.Field = WS.getName();
1203 Import.Module = WS.getImportModule();
1204 Import.Field = WS.getImportName();
12041205 Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
12051206 Import.SigIndex = getFunctionType(WS);
12061207 Imports.push_back(Import);
12101211 report_fatal_error("undefined global symbol cannot be weak");
12111212
12121213 wasm::WasmImport Import;
1213 Import.Module = WS.getModuleName();
1214 Import.Field = WS.getName();
1214 Import.Module = WS.getImportModule();
1215 Import.Field = WS.getImportName();
12151216 Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
12161217 Import.Global = WS.getGlobalType();
12171218 Imports.push_back(Import);
12211222 report_fatal_error("undefined event symbol cannot be weak");
12221223
12231224 wasm::WasmImport Import;
1224 Import.Module = WS.getModuleName();
1225 Import.Field = WS.getName();
1225 Import.Module = WS.getImportModule();
1226 Import.Field = WS.getImportName();
12261227 Import.Kind = wasm::WASM_EXTERNAL_EVENT;
12271228 Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
12281229 Import.Event.SigIndex = getEventType(WS);
14471448 Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
14481449 if (WS.isUndefined())
14491450 Flags |= wasm::WASM_SYMBOL_UNDEFINED;
1451 if (WS.getName() != WS.getImportName())
1452 Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
14501453
14511454 wasm::WasmSymbolInfo Info;
14521455 Info.Name = WS.getName();
504504 Function.SymbolName = Info.Name;
505505 } else {
506506 wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
507 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
508 Info.Name = readString(Ctx);
509 else
510 Info.Name = Import.Field;
507511 Signature = &Signatures[Import.SigIndex];
508 Info.Name = Import.Field;
509 Info.Module = Import.Module;
512 Info.ImportName = Import.Field;
513 Info.ImportModule = Import.Module;
510514 }
511515 break;
512516
529533 Global.SymbolName = Info.Name;
530534 } else {
531535 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
532 Info.Name = Import.Field;
536 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
537 Info.Name = readString(Ctx);
538 else
539 Info.Name = Import.Field;
533540 GlobalType = &Import.Global;
541 Info.ImportName = Import.Field;
542 Info.ImportModule = Import.Module;
534543 }
535544 break;
536545
584593
585594 } else {
586595 wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
596 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
597 Info.Name = readString(Ctx);
598 else
599 Info.Name = Import.Field;
587600 EventType = &Import.Event;
588601 Signature = &Signatures[EventType->SigIndex];
589 Info.Name = Import.Field;
602 Info.ImportName = Import.Field;
603 Info.ImportModule = Import.Module;
590604 }
591605 break;
592606 }
112112 }
113113
114114 void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym,
115 StringRef ModuleName) {
116 OS << "\t.import_module\t" << Sym->getName() << ", " << ModuleName << '\n';
115 StringRef ImportModule) {
116 OS << "\t.import_module\t" << Sym->getName() << ", "
117 << ImportModule << '\n';
118 }
119
120 void WebAssemblyTargetAsmStreamer::emitImportName(const MCSymbolWasm *Sym,
121 StringRef ImportName) {
122 OS << "\t.import_name\t" << Sym->getName() << ", "
123 << ImportName << '\n';
117124 }
118125
119126 void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) {
4444 virtual void emitEventType(const MCSymbolWasm *Sym) = 0;
4545 /// .import_module
4646 virtual void emitImportModule(const MCSymbolWasm *Sym,
47 StringRef ModuleName) = 0;
47 StringRef ImportModule) = 0;
48 /// .import_name
49 virtual void emitImportName(const MCSymbolWasm *Sym,
50 StringRef ImportName) = 0;
4851
4952 protected:
5053 void emitValueType(wasm::ValType Type);
6669 void emitIndIdx(const MCExpr *Value) override;
6770 void emitGlobalType(const MCSymbolWasm *Sym) override;
6871 void emitEventType(const MCSymbolWasm *Sym) override;
69 void emitImportModule(const MCSymbolWasm *Sym, StringRef ModuleName) override;
72 void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule) override;
73 void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override;
7074 };
7175
7276 /// This part is for Wasm object output
8185 void emitGlobalType(const MCSymbolWasm *Sym) override {}
8286 void emitEventType(const MCSymbolWasm *Sym) override {}
8387 void emitImportModule(const MCSymbolWasm *Sym,
84 StringRef ModuleName) override {}
88 StringRef ImportModule) override {}
89 void emitImportName(const MCSymbolWasm *Sym,
90 StringRef ImportName) override {}
8591 };
8692
8793 /// This part is for null output
97103 void emitGlobalType(const MCSymbolWasm *) override {}
98104 void emitEventType(const MCSymbolWasm *) override {}
99105 void emitImportModule(const MCSymbolWasm *, StringRef) override {}
106 void emitImportName(const MCSymbolWasm *, StringRef) override {}
100107 };
101108
102109 } // end namespace llvm
110110 F.hasFnAttribute("wasm-import-module")) {
111111 StringRef Name =
112112 F.getFnAttribute("wasm-import-module").getValueAsString();
113 Sym->setModuleName(Name);
113 Sym->setImportModule(Name);
114114 getTargetStreamer()->emitImportModule(Sym, Name);
115 }
116 if (TM.getTargetTriple().isOSBinFormatWasm() &&
117 F.hasFnAttribute("wasm-import-name")) {
118 StringRef Name =
119 F.getFnAttribute("wasm-import-name").getValueAsString();
120 Sym->setImportName(Name);
121 getTargetStreamer()->emitImportName(Sym, Name);
115122 }
116123 }
117124 }
3434 using namespace llvm;
3535
3636 #define DEBUG_TYPE "wasm-fix-function-bitcasts"
37
38 static cl::opt
39 TemporaryWorkarounds("wasm-temporary-workarounds",
40 cl::desc("Apply certain temporary workarounds"),
41 cl::init(true), cl::Hidden);
4237
4338 namespace {
4439 class FixFunctionBitcasts final : public ModulePass {
226221 return Wrapper;
227222 }
228223
224 // Test whether a main function with type FuncTy should be rewritten to have
225 // type MainTy.
226 bool shouldFixMainFunction(FunctionType *FuncTy, FunctionType *MainTy) {
227 // Only fix the main function if it's the standard zero-arg form. That way,
228 // the standard cases will work as expected, and users will see signature
229 // mismatches from the linker for non-standard cases.
230 return FuncTy->getReturnType() == MainTy->getReturnType() &&
231 FuncTy->getNumParams() == 0 &&
232 !FuncTy->isVarArg();
233 }
234
229235 bool FixFunctionBitcasts::runOnModule(Module &M) {
230236 LLVM_DEBUG(dbgs() << "********** Fix Function Bitcasts **********\n");
231237
242248 // "int main(int argc, char *argv[])", create an artificial call with it
243249 // bitcasted to that type so that we generate a wrapper for it, so that
244250 // the C runtime can call it.
245 if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") {
251 if (F.getName() == "main") {
246252 Main = &F;
247253 LLVMContext &C = M.getContext();
248254 Type *MainArgTys[] = {Type::getInt32Ty(C),
249255 PointerType::get(Type::getInt8PtrTy(C), 0)};
250256 FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys,
251257 /*isVarArg=*/false);
252 if (F.getFunctionType() != MainTy) {
258 if (shouldFixMainFunction(F.getFunctionType(), MainTy)) {
253259 LLVM_DEBUG(dbgs() << "Found `main` function with incorrect type: "
254260 << *F.getFunctionType() << "\n");
255261 Value *Args[] = {UndefValue::get(MainArgTys[0]),
297303 Main->setName("__original_main");
298304 Function *MainWrapper =
299305 cast(CallMain->getCalledValue()->stripPointerCasts());
300 MainWrapper->setName("main");
301 MainWrapper->setLinkage(Main->getLinkage());
302 MainWrapper->setVisibility(Main->getVisibility());
303 Main->setLinkage(Function::PrivateLinkage);
304 Main->setVisibility(Function::DefaultVisibility);
305306 delete CallMain;
307 if (Main->isDeclaration()) {
308 // The wrapper is not needed in this case as we don't need to export
309 // it to anyone else.
310 MainWrapper->eraseFromParent();
311 } else {
312 // Otherwise give the wrapper the same linkage as the original main
313 // function, so that it can be called from the same places.
314 MainWrapper->setName("main");
315 MainWrapper->setLinkage(Main->getLinkage());
316 MainWrapper->setVisibility(Main->getVisibility());
317 }
306318 }
307319
308320 return true;
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -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 -fast-isel -fast-isel-abort=1 -wasm-temporary-workarounds=false -mattr=+sign-ext,+simd128 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+sign-ext,+simd128 | FileCheck %s
1 ; 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
22
33 ; Test that basic call operations assemble as expected.
44
None ; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false -wasm-keep-registers | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
11
22 ; Test that function pointer casts casting away varargs are replaced with
33 ; wrappers.
None ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions -wasm-temporary-workarounds=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions | FileCheck %s
11
22 ; Test that function pointer casts are replaced with wrappers.
33
1111 declare void @foo() #0
1212 declare void @plain()
1313
14 attributes #0 = { "wasm-import-module"="bar" }
14 attributes #0 = { "wasm-import-module"="bar" "wasm-import-name"="qux" }
1515
1616 ; CHECK-NOT: .import_module plain
1717 ; CHECK: .import_module foo, bar
18 ; CHECK: .import_name foo, qux
1819 ; CHECK-NOT: .import_module plain
None ; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false | FileCheck %s
11
22 ; Test main functions with alternate signatures.
33
44 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
55 target triple = "wasm32-unknown-unknown"
66
7 declare void @main()
7 declare i32 @main()
88
9 define void @foo() {
10 call void @main()
11 ret void
9 define i32 @foo() {
10 %t = call i32 @main()
11 ret i32 %t
1212 }
1313
14 ; CHECK-NOT: __original_main
1514 ; CHECK-LABEL: foo:
16 ; CHECK-NEXT: .functype foo () -> ()
17 ; CHECK-NEXT: call main@FUNCTION
15 ; CHECK-NEXT: .functype foo () -> (i32)
16 ; CHECK-NEXT: call __original_main@FUNCTION
1817 ; CHECK-NEXT: end_function
19 ; CHECK-NOT: __original_main
None ; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false | FileCheck %s
11
22 ; Test main functions with alternate signatures.
33
44 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
55 target triple = "wasm32-unknown-unknown"
66
7 define void @main() {
8 ret void
7 define i32 @main() {
8 ret i32 0
99 }
1010
11 ; CHECK-LABEL: .L__original_main:
12 ; CHECK-NEXT: .functype .L__original_main () -> ()
11 ; CHECK-LABEL: __original_main:
12 ; CHECK-NEXT: .functype __original_main () -> (i32)
13 ; CHECK-NEXT: i32.const 0
1314 ; CHECK-NEXT: end_function
1415
1516 ; CHECK-LABEL: main:
1617 ; CHECK-NEXT: .functype main (i32, i32) -> (i32)
17 ; CHECK: call .L__original_main@FUNCTION
18 ; CHECK: call __original_main@FUNCTION
0 ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1
2 ; Test that main function with a non-standard third argument is
3 ; not wrapped.
4
5 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6 target triple = "wasm32-unknown-unknown"
7
8 define i32 @main(i32 %a, i8** %b, i8** %c) {
9 ret i32 0
10 }
11
12 ; CHECK-LABEL: main:
13 ; CHECK-NEXT: .functype main (i32, i32, i32) -> (i32)
14
15 ; CHECK-NOT: __original_main:
None ; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false | FileCheck %s
11
22 ; Test that main function with expected signature is not wrapped
33
77 declare void @f0(i32) #0
88 @ptr_to_f0 = hidden global void (i32)* @f0, align 4
99
10 attributes #0 = { "wasm-import-module"="somewhere" }
10 attributes #0 = { "wasm-import-module"="somewhere" "wasm-import-name"="something" }
1111
1212 declare void @f1(i32) #1
1313 @ptr_to_f1 = hidden global void (i32)* @f1, align 4
4646 ; CHECK-NEXT: Kind: FUNCTION
4747 ; CHECK-NEXT: SigIndex: 1
4848 ; CHECK: - Module: somewhere
49 ; CHECK-NEXT: Field: f0
49 ; CHECK-NEXT: Field: something
5050 ; CHECK: - Module: env
5151 ; CHECK-NEXT: Field: f1
5252 ; CHECK-NEXT: Kind: FUNCTION
0 ; RUN: llc -filetype=obj %s -o - | obj2yaml | FileCheck %s
1
2 target triple = "wasm32-unknown-unknown"
3
4 define void @test() {
5 call void @foo()
6 call void @plain()
7 ret void
8 }
9
10 declare void @foo() #0
11 declare void @plain()
12
13 attributes #0 = { "wasm-import-module"="bar" "wasm-import-name"="qux" }
14
15 ; CHECK: - Type: IMPORT
16 ; CHECK-NEXT: Imports:
17 ; CHECK: - Module: bar
18 ; CHECK-NEXT: Field: qux
19 ; CHECK-NEXT: Kind: FUNCTION
20
21 ; CHECK: - Module: env
22 ; CHECK-NEXT: Field: plain
23 ; CHECK-NEXT: Kind: FUNCTION
24
25 ; CHECK: - Type: CUSTOM
26 ; CHECK: Name: foo
27 ; CHECK-NEXT: Flags: [ UNDEFINED ]
28
29 ; CHECK: Name: plain
30 ; CHECK-NEXT: Flags: [ UNDEFINED ]
171171 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
172172 case wasm::WASM_SYMBOL_TYPE_EVENT:
173173 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
174 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
174 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
175 (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
175176 writeStringRef(Info.Name, SubSection.GetStream());
176177 break;
177178 case wasm::WASM_SYMBOL_TYPE_DATA: