Index: llvm/trunk/include/llvm/MC/MCSymbolWasm.h =================================================================== --- llvm/trunk/include/llvm/MC/MCSymbolWasm.h +++ llvm/trunk/include/llvm/MC/MCSymbolWasm.h @@ -54,6 +54,7 @@ void setComdat(bool isComdat) { IsComdat = isComdat; } const StringRef getModuleName() const { return ModuleName; } + void setModuleName(StringRef Name) { ModuleName = Name; } const SmallVector &getReturns() const { assert(ReturnsSet); Index: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h =================================================================== --- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -24,6 +24,7 @@ class MCELFStreamer; class MCWasmStreamer; +class MCSymbolWasm; /// WebAssembly-specific streamer interface, to implement support /// WebAssembly-specific assembly directives. @@ -47,6 +48,8 @@ virtual void emitIndIdx(const MCExpr *Value) = 0; /// .import_global virtual void emitGlobalImport(StringRef name) = 0; + /// .import_module + virtual void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) = 0; protected: void emitValueType(wasm::ValType Type); @@ -68,6 +71,7 @@ SmallVectorImpl &Results) override; void emitIndIdx(const MCExpr *Value) override; void emitGlobalImport(StringRef name) override; + void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) override; }; /// This part is for ELF object output @@ -84,6 +88,7 @@ SmallVectorImpl &Results) override; void emitIndIdx(const MCExpr *Value) override; void emitGlobalImport(StringRef name) override; + void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) override; }; /// This part is for Wasm object output @@ -100,6 +105,7 @@ SmallVectorImpl &Results) override; void emitIndIdx(const MCExpr *Value) override; void emitGlobalImport(StringRef name) override; + void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) override; }; } // end namespace llvm Index: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -107,6 +107,11 @@ OS << "\t.import_global\t" << name << '\n'; } +void WebAssemblyTargetAsmStreamer::emitImportModule(MCSymbolWasm *Sym, + StringRef ModuleName) { + OS << "\t.import_module\t" << Sym->getName() << ", " << ModuleName << '\n'; +} + void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { OS << "\t.indidx \t" << *Value << '\n'; } @@ -144,6 +149,11 @@ void WebAssemblyTargetELFStreamer::emitGlobalImport(StringRef name) { } +void WebAssemblyTargetELFStreamer::emitImportModule(MCSymbolWasm *Sym, + StringRef ModuleName) { + llvm_unreachable(".import_module encoding not yet implemented"); +} + void WebAssemblyTargetWasmStreamer::emitParam(MCSymbol *Symbol, ArrayRef Types) { SmallVector Params; @@ -211,3 +221,8 @@ void WebAssemblyTargetWasmStreamer::emitGlobalImport(StringRef name) { llvm_unreachable(".global_import is not needed for direct wasm output"); } + +void WebAssemblyTargetWasmStreamer::emitImportModule(MCSymbolWasm *Sym, + StringRef ModuleName) { + Sym->setModuleName(ModuleName); +} Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -84,8 +84,14 @@ SmallVector Results; SmallVector Params; ComputeSignatureVTs(F, TM, Params, Results); - getTargetStreamer()->emitIndirectFunctionType(getSymbol(&F), Params, - Results); + MCSymbolWasm *Sym = cast(getSymbol(&F)); + getTargetStreamer()->emitIndirectFunctionType(Sym, Params, Results); + + if (F.hasFnAttribute("wasm-import-module")) { + StringRef Name = F.getFnAttribute("wasm-import-module") + .getValueAsString(); + getTargetStreamer()->emitImportModule(Sym, Name); + } } } for (const auto &G : M.globals()) { Index: llvm/trunk/test/CodeGen/WebAssembly/import-module.ll =================================================================== --- llvm/trunk/test/CodeGen/WebAssembly/import-module.ll +++ llvm/trunk/test/CodeGen/WebAssembly/import-module.ll @@ -0,0 +1,19 @@ +; RUN: llc < %s -asm-verbose=false | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +define void @test() { + call void @foo() + call void @plain() + ret void +} + +declare void @foo() #0 +declare void @plain() + +attributes #0 = { "wasm-import-module"="bar" } + +; CHECK-NOT: .import_module plain +; CHECK: .import_module foo, bar +; CHECK-NOT: .import_module plain Index: llvm/trunk/test/MC/WebAssembly/external-func-address.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/external-func-address.ll +++ llvm/trunk/test/MC/WebAssembly/external-func-address.ll @@ -5,6 +5,11 @@ ; Verify that addresses of external functions generate correctly typed ; imports and relocations or type R_TABLE_INDEX_I32. +declare void @f0(i32) #0 +@ptr_to_f0 = hidden global void (i32)* @f0, align 4 + +attributes #0 = { "wasm-import-module"="somewhere" } + declare void @f1(i32) #1 @ptr_to_f1 = hidden global void (i32)* @f1, align 4 @@ -24,6 +29,8 @@ ; CHECK-NEXT: Field: __linear_memory ; CHECK: - Module: env ; CHECK-NEXT: Field: __indirect_function_table +; CHECK: - Module: somewhere +; CHECK-NEXT: Field: f0 ; CHECK: - Module: env ; CHECK-NEXT: Field: f1 ; CHECK-NEXT: Kind: FUNCTION @@ -33,7 +40,7 @@ ; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1 -; CHECK-NEXT: Functions: [ 0 ] +; CHECK-NEXT: Functions: [ 0, 1 ] ; CHECK: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32