Skip to content

Commit

Permalink
[LTO] Add function alias as function instead of data (#112599)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
scui-ibm authored Oct 17, 2024
1 parent 94643a4 commit 0205667
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 7 deletions.
2 changes: 1 addition & 1 deletion llvm/include/llvm/LTO/legacy/LTOModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 13 additions & 4 deletions llvm/lib/LTO/LTOModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,11 +406,16 @@ void LTOModule::addDefinedFunctionSymbol(ModuleSymbolTable::Symbol Sym) {
Buffer.c_str();
}

const Function *F = cast<Function>(cast<GlobalValue *>(Sym));
addDefinedFunctionSymbol(Buffer, F);
auto *GV = cast<GlobalValue *>(Sym);
assert((isa<Function>(GV) ||
(isa<GlobalAlias>(GV) &&
isa<Function>(cast<GlobalAlias>(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);
}
Expand Down Expand Up @@ -611,7 +616,11 @@ void LTOModule::parseSymbols() {
}

assert(isa<GlobalAlias>(GV));
addDefinedDataSymbol(Sym);

if (isa<Function>(cast<GlobalAlias>(GV)->getAliasee()))
addDefinedFunctionSymbol(Sym);
else
addDefinedDataSymbol(Sym);
}

// make symbols for all undefines
Expand Down
16 changes: 16 additions & 0 deletions llvm/test/LTO/PowerPC/list-symbol.ll
Original file line number Diff line number Diff line change
@@ -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
}
65 changes: 63 additions & 2 deletions llvm/tools/llvm-lto/llvm-lto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 0205667

Please sign in to comment.