Index: test/wasm/alias.ll =================================================================== --- /dev/null +++ test/wasm/alias.ll @@ -0,0 +1,66 @@ +; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s +; RUN: lld -flavor wasm %t.o -o %t.wasm +; RUN: obj2yaml %t.wasm | FileCheck %s + +@start_alias = alias i32 (), i32 ()* @_start + +; Function Attrs: nounwind uwtable +define i32 @_start() local_unnamed_addr #1 { +entry: + ret i32 0 +} + +; CHECK: --- !WASM +; CHECK-NEXT: FileHeader: +; CHECK-NEXT: Version: 0x00000001 +; CHECK-NEXT: Sections: +; CHECK-NEXT: - Type: TYPE +; CHECK-NEXT: Signatures: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: ReturnType: I32 +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Type: FUNCTION +; CHECK-NEXT: FunctionTypes: [ 0 ] +; CHECK-NEXT: - Type: TABLE +; CHECK-NEXT: Tables: +; CHECK-NEXT: - ElemType: ANYFUNC +; CHECK-NEXT: Limits: +; CHECK-NEXT: Flags: [ HAS_MAX ] +; CHECK-NEXT: Initial: 0x00000001 +; CHECK-NEXT: Maximum: 0x00000001 +; CHECK-NEXT: - Type: MEMORY +; CHECK-NEXT: Memories: +; CHECK-NEXT: - Initial: 0x00000002 +; CHECK-NEXT: - Type: GLOBAL +; CHECK-NEXT: Globals: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: true +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 66560 +; CHECK-NEXT: - Type: EXPORT +; CHECK-NEXT: Exports: +; CHECK-NEXT: - Name: memory +; CHECK-NEXT: Kind: MEMORY +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: - Name: _start +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: - Name: start_alias +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: - Type: CODE +; CHECK-NEXT: Functions: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 41000B +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: linking +; CHECK-NEXT: DataSize: 0 +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: name +; CHECK-NEXT: FunctionNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: start_alias +; CHECK-NEXT: ... Index: wasm/InputChunks.h =================================================================== --- wasm/InputChunks.h +++ wasm/InputChunks.h @@ -110,7 +110,7 @@ public: InputFunction(const WasmSignature &S, const WasmFunction &Func, const ObjFile &F) - : InputChunk(F), Signature(S), Function(Func) {} + : InputChunk(F), Signature(S), WrittenToNameSec(false), Function(Func) {} uint32_t getSize() const override { return Function.Size; } const uint8_t *getData() const override { @@ -126,6 +126,8 @@ const WasmSignature &Signature; + unsigned WrittenToNameSec : 1; + protected: uint32_t getInputSectionOffset() const override { return Function.CodeSectionOffset; Index: wasm/Symbols.h =================================================================== --- wasm/Symbols.h +++ wasm/Symbols.h @@ -93,11 +93,11 @@ void update(Kind K, InputFile *F = nullptr, uint32_t Flags = 0, const InputSegment *Segment = nullptr, - const InputFunction *Function = nullptr, - uint32_t Address = UINT32_MAX); + InputFunction *Function = nullptr, uint32_t Address = UINT32_MAX); void setArchiveSymbol(const Archive::Symbol &Sym) { ArchiveSymbol = Sym; } const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; } + InputFunction *getFunction() { return Function; } // This bit is used by Writer::writeNameSection() to prevent // symbols from being written to the symbol table more than once. @@ -113,7 +113,7 @@ Kind SymbolKind = InvalidKind; InputFile *File = nullptr; const InputSegment *Segment = nullptr; - const InputFunction *Function = nullptr; + InputFunction *Function = nullptr; llvm::Optional OutputIndex; llvm::Optional TableIndex; const WasmSignature *FunctionType = nullptr; Index: wasm/Symbols.cpp =================================================================== --- wasm/Symbols.cpp +++ wasm/Symbols.cpp @@ -74,7 +74,7 @@ } void Symbol::update(Kind K, InputFile *F, uint32_t Flags_, - const InputSegment *Seg, const InputFunction *Func, + const InputSegment *Seg, InputFunction *Func, uint32_t Address) { SymbolKind = K; File = F; Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -442,6 +442,15 @@ for (Symbol *S : File->getSymbols()) { if (!S->isFunction() || S->isWeak() || S->WrittenToNameSec) continue; + // We also need to guard against two different symbols (two different + // names) for the same wasm function. While this is possible (aliases) + // it is not legal in the "name" section. + InputFunction *Function = S->getFunction(); + if (Function) { + if (Function->WrittenToNameSec) + continue; + Function->WrittenToNameSec = true; + } S->WrittenToNameSec = true; Names.emplace_back(S); }