From 020566701030425f44eb80387d0ae76c5a867aa9 Mon Sep 17 00:00:00 2001 From: Shimin Cui Date: Thu, 17 Oct 2024 12:10:05 -0400 Subject: [PATCH] [LTO] Add function alias as function instead of data (#112599) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On AIX, for undefined functions, only the dotnamed symbols (the address of the function) are generated after linking (i.e., no named function symbol is generated).   Currently, all alias symbols are added as defined data symbols when parsing symbols in LTOModule (the Link Time Optimization library used by linker to optimization code at link time). On AIX, if the function alias is used in the native object, and only its dotnamed symbol is generated, the linker will have problem to match the dotnamed symbol from the native object and the defined symbol marked as data from the bitcode at LTO linktime.   This patch is to add function alias as function instead of data. --- llvm/include/llvm/LTO/legacy/LTOModule.h | 2 +- llvm/lib/LTO/LTOModule.cpp | 17 +++++-- llvm/test/LTO/PowerPC/list-symbol.ll | 16 ++++++ llvm/tools/llvm-lto/llvm-lto.cpp | 65 +++++++++++++++++++++++- 4 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 llvm/test/LTO/PowerPC/list-symbol.ll diff --git a/llvm/include/llvm/LTO/legacy/LTOModule.h b/llvm/include/llvm/LTO/legacy/LTOModule.h index 1b2de3b333855c..e861a56bcbac1d 100644 --- a/llvm/include/llvm/LTO/legacy/LTOModule.h +++ b/llvm/include/llvm/LTO/legacy/LTOModule.h @@ -195,7 +195,7 @@ struct LTOModule { /// Add a function symbol as defined to the list. void addDefinedFunctionSymbol(ModuleSymbolTable::Symbol Sym); - void addDefinedFunctionSymbol(StringRef Name, const Function *F); + void addDefinedFunctionSymbol(StringRef Name, const GlobalValue *F); /// Add a global symbol from module-level ASM to the defined list. void addAsmGlobalSymbol(StringRef, lto_symbol_attributes scope); diff --git a/llvm/lib/LTO/LTOModule.cpp b/llvm/lib/LTO/LTOModule.cpp index eac78069f4d2bc..00eb8adb4e1035 100644 --- a/llvm/lib/LTO/LTOModule.cpp +++ b/llvm/lib/LTO/LTOModule.cpp @@ -406,11 +406,16 @@ void LTOModule::addDefinedFunctionSymbol(ModuleSymbolTable::Symbol Sym) { Buffer.c_str(); } - const Function *F = cast(cast(Sym)); - addDefinedFunctionSymbol(Buffer, F); + auto *GV = cast(Sym); + assert((isa(GV) || + (isa(GV) && + isa(cast(GV)->getAliasee()))) && + "Not function or function alias"); + + addDefinedFunctionSymbol(Buffer, GV); } -void LTOModule::addDefinedFunctionSymbol(StringRef Name, const Function *F) { +void LTOModule::addDefinedFunctionSymbol(StringRef Name, const GlobalValue *F) { // add to list of defined symbols addDefinedSymbol(Name, F, true); } @@ -611,7 +616,11 @@ void LTOModule::parseSymbols() { } assert(isa(GV)); - addDefinedDataSymbol(Sym); + + if (isa(cast(GV)->getAliasee())) + addDefinedFunctionSymbol(Sym); + else + addDefinedDataSymbol(Sym); } // make symbols for all undefines diff --git a/llvm/test/LTO/PowerPC/list-symbol.ll b/llvm/test/LTO/PowerPC/list-symbol.ll new file mode 100644 index 00000000000000..75300b11f7f188 --- /dev/null +++ b/llvm/test/LTO/PowerPC/list-symbol.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as < %s > %t +; RUN: llvm-lto -list-symbols-only %t | FileCheck %s +; REQUIRES: default_triple + +; CHECK-DAG: v { data defined default } +; CHECK-DAG: va { data defined default alias } +; CHECK-DAG: f { function defined default } +; CHECK-DAG: fa { function defined default alias } + +@v = global i32 0 +@va = alias i32, ptr @v +@fa = alias void (ptr), ptr @f + +define void @f() { + ret void +} diff --git a/llvm/tools/llvm-lto/llvm-lto.cpp b/llvm/tools/llvm-lto/llvm-lto.cpp index f5076f0b975178..4090faf4e3fd95 100644 --- a/llvm/tools/llvm-lto/llvm-lto.cpp +++ b/llvm/tools/llvm-lto/llvm-lto.cpp @@ -407,6 +407,64 @@ static void printIndexStats() { } } +/// Print the lto symbol attributes. +static void printLTOSymbolAttributes(lto_symbol_attributes Attrs) { + outs() << "{ "; + unsigned Permission = Attrs & LTO_SYMBOL_PERMISSIONS_MASK; + switch (Permission) { + case LTO_SYMBOL_PERMISSIONS_CODE: + outs() << "function "; + break; + case LTO_SYMBOL_PERMISSIONS_DATA: + outs() << "data "; + break; + case LTO_SYMBOL_PERMISSIONS_RODATA: + outs() << "constant "; + break; + } + unsigned Definition = Attrs & LTO_SYMBOL_DEFINITION_MASK; + switch (Definition) { + case LTO_SYMBOL_DEFINITION_REGULAR: + outs() << "defined "; + break; + case LTO_SYMBOL_DEFINITION_TENTATIVE: + outs() << "common "; + break; + case LTO_SYMBOL_DEFINITION_WEAK: + outs() << "weak "; + break; + case LTO_SYMBOL_DEFINITION_UNDEFINED: + outs() << "extern "; + break; + case LTO_SYMBOL_DEFINITION_WEAKUNDEF: + outs() << "extern-weak "; + break; + } + unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK; + switch (Scope) { + case LTO_SYMBOL_SCOPE_INTERNAL: + outs() << "internal "; + break; + case LTO_SYMBOL_SCOPE_HIDDEN: + outs() << "hidden "; + break; + case LTO_SYMBOL_SCOPE_PROTECTED: + outs() << "protected "; + break; + case LTO_SYMBOL_SCOPE_DEFAULT: + outs() << "default "; + break; + case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN: + outs() << "omitted "; + break; + } + if (Attrs & LTO_SYMBOL_COMDAT) + outs() << "comdat "; + if (Attrs & LTO_SYMBOL_ALIAS) + outs() << "alias "; + outs() << "}"; +} + /// Load each IR file and dump certain information based on active flags. /// /// The main point here is to provide lit-testable coverage for the LTOModule @@ -421,8 +479,11 @@ static void testLTOModule(const TargetOptions &Options) { if (ListSymbolsOnly) { // List the symbols. outs() << Filename << ":\n"; - for (int I = 0, E = Module->getSymbolCount(); I != E; ++I) - outs() << Module->getSymbolName(I) << "\n"; + for (int I = 0, E = Module->getSymbolCount(); I != E; ++I) { + outs() << Module->getSymbolName(I) << " "; + printLTOSymbolAttributes(Module->getSymbolAttributes(I)); + outs() << "\n"; + } } if (QueryHasCtorDtor) outs() << Filename