Index: llvm/trunk/lib/IR/ValueSymbolTable.cpp =================================================================== --- llvm/trunk/lib/IR/ValueSymbolTable.cpp +++ llvm/trunk/lib/IR/ValueSymbolTable.cpp @@ -13,7 +13,9 @@ #include "llvm/IR/ValueSymbolTable.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Triple.h" #include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" @@ -45,8 +47,17 @@ // Trim any suffix off and append the next number. UniqueName.resize(BaseSize); raw_svector_ostream S(UniqueName); - if (isa(V)) - S << "."; + if (auto *GV = dyn_cast(V)) { + // A dot is appended to mark it as clone during ABI demangling so that + // for example "_Z1fv" and "_Z1fv.1" both demangle to "f()", the second + // one being a clone. + // On NVPTX we cannot use a dot because PTX only allows [A-Za-z0-9_$] for + // identifiers. This breaks ABI demangling but at least ptxas accepts and + // compiles the program. + const Module *M = GV->getParent(); + if (!(M && Triple(M->getTargetTriple()).isNVPTX())) + S << "."; + } S << ++LastUnique; // Try insert the vmap entry with this suffix. Index: llvm/trunk/lib/Target/NVPTX/NVPTXAssignValidGlobalNames.cpp =================================================================== --- llvm/trunk/lib/Target/NVPTX/NVPTXAssignValidGlobalNames.cpp +++ llvm/trunk/lib/Target/NVPTX/NVPTXAssignValidGlobalNames.cpp @@ -18,6 +18,7 @@ //===----------------------------------------------------------------------===// #include "NVPTX.h" +#include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" @@ -61,6 +62,11 @@ } } + // Do the same for local functions. + for (Function &F : M.functions()) + if (F.hasLocalLinkage()) + F.setName(cleanUpName(F.getName())); + return true; } Index: llvm/trunk/test/CodeGen/NVPTX/symbol-naming.ll =================================================================== --- llvm/trunk/test/CodeGen/NVPTX/symbol-naming.ll +++ llvm/trunk/test/CodeGen/NVPTX/symbol-naming.ll @@ -1,17 +1,17 @@ -; RUN: llc < %s -march=nvptx -mcpu=sm_20 | FileCheck %s --check-prefix=PTX32 -; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 | FileCheck %s --check-prefix=PTX64 +; RUN: llc < %s -march=nvptx -mcpu=sm_20 | FileCheck %s +; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 | FileCheck %s ; Verify that the NVPTX target removes invalid symbol names prior to emitting ; PTX. -; PTX32-NOT: .str -; PTX64-NOT: .str +; CHECK-NOT: .str +; CHECK-NOT: .function. -; PTX32-DAG: _$_str.1 -; PTX32-DAG: _$_str +; CHECK-DAG: _$_str +; CHECK-DAG: _$_str1 -; PTX64-DAG: _$_str.1 -; PTX64-DAG: _$_str +; CHECK-DAG: _$_function_$_ +; CHECK-DAG: _$_function_$_2 target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64" target triple = "nvptx64-unknown-unknown" @@ -22,10 +22,25 @@ ; Function Attrs: nounwind -define void @foo(i32 %a, float %b, i8 signext %c, i32 %e) { +define internal void @.function.() { entry: %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i32 0, i32 0)) ret void } +; Function Attrs: nounwind +define internal void @_$_function_$_() { +entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @_$_str, i32 0, i32 0)) + ret void +} + +; Function Attrs: nounwind +define void @global_function() { +entry: + call void @.function.() + call void @_$_function_$_() + ret void +} + declare i32 @printf(i8*, ...)