Index: test/wasm/Inputs/local1.ll =================================================================== --- /dev/null +++ test/wasm/Inputs/local1.ll @@ -0,0 +1,13 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +define internal i32 @staticFn() { +entry: + ret i32 0 +} + +define i32 @fn1() { +entry: + %rv = call i32 @staticFn() + ret i32 %rv +} Index: test/wasm/Inputs/local2.ll =================================================================== --- /dev/null +++ test/wasm/Inputs/local2.ll @@ -0,0 +1,13 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +define internal i32 @staticFn() { +entry: + ret i32 0 +} + +define i32 @fn2() { +entry: + %rv = call i32 @staticFn() + ret i32 %rv +} Index: test/wasm/duplicate-static.ll =================================================================== --- /dev/null +++ test/wasm/duplicate-static.ll @@ -0,0 +1,16 @@ +; RUN: llc -filetype=obj %S/Inputs/local1.ll -o %t.o +; RUN: llc -filetype=obj %S/Inputs/local2.ll -o %t2.o +; RUN: lld -flavor wasm --entry '' -o %t.wasm %t.o %t2.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +; CHECK: - Type: CUSTOM +; CHECK: Name: name +; CHECK-NEXT: FunctionNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: staticFn +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: fn1 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: staticFn.2 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Name: fn2 Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -430,16 +430,29 @@ } } +static std::string budgeName(StringRef Name, llvm::StringSet<> *UsedNames) { + for (int i = 2; true; ++i) { + std::string BudgedName = (Name + Twine(".") + Twine(i)).str(); + if (UsedNames->insert(BudgedName).second) + return BudgedName; + } +} + // Create the custom "name" section containing debug symbol names. void Writer::createNameSection() { // Create an array of all function sorted by function index space std::vector Names; + llvm::StringSet<> UsedNames; for (ObjFile *File : Symtab->ObjectFiles) { Names.reserve(Names.size() + File->getSymbols().size()); for (Symbol *S : File->getSymbols()) { if (!S->isFunction() || S->isWeak() || S->WrittenToNameSec) continue; + if (!S->isLocal()) { + bool inserted = UsedNames.insert(S->getName()).second; + assert(inserted); // Cannot have duplicate non-local, non-weak symbols + } S->WrittenToNameSec = true; Names.emplace_back(S); } @@ -459,7 +472,11 @@ // appear first before any of the local function names. for (const Symbol *S : Names) { writeUleb128(OS, S->getOutputIndex(), "func index"); - writeStr(OS, S->getName(), "symbol name"); + StringRef Name = S->getName(); + std::string BudgedName; + if (S->isLocal() && !UsedNames.insert(Name).second) + Name = (BudgedName = budgeName(Name, &UsedNames)); + writeStr(OS, Name, "symbol name"); } FunctionSubsection.finalizeContents();