Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1337,9 +1337,20 @@ else assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage"); + bool isFunction = GIS.getType()->getPointerElementType()->isFunctionTy(); + + // Treat bitcasts of functions as functions also. This is important at least + // on WebAssembly where object and function addresses can't alias each other. + if (!isFunction) + if (auto *CE = dyn_cast(GIS.getIndirectSymbol())) + if (CE->getOpcode() == Instruction::BitCast) + isFunction = + CE->getOperand(0)->getType()->getPointerElementType()->isFunctionTy(); + + // Set the symbol type to function if the alias has a function type. // This affects codegen when the aliasee is not a function. - if (GIS.getType()->getPointerElementType()->isFunctionTy()) { + if (isFunction) { OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeFunction); if (isa(GIS)) OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeIndFunction); Index: test/MC/WebAssembly/function-alias.ll =================================================================== --- /dev/null +++ test/MC/WebAssembly/function-alias.ll @@ -0,0 +1,29 @@ +; RUN: llc -filetype=obj %s -o - | llvm-readobj -symbols | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +@foo = alias i8, bitcast (i8* ()* @func to i8*) +@bar = alias i8* (), i8* ()* @func + +define i8* @func() { + ret i8* @foo; +} + +; CHECK: Symbols [ +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Name: func +; CHECK-NEXT: Type: FUNCTION (0x0) +; CHECK-NEXT: Flags: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Name: foo +; CHECK-NEXT: Type: FUNCTION (0x0) +; CHECK-NEXT: Flags: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Name: bar +; CHECK-NEXT: Type: FUNCTION (0x0) +; CHECK-NEXT: Flags: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: ]