diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -194,6 +194,9 @@ protected: MCSymbol *CurrentFnBegin = nullptr; + /// For dso_local functions, the current $local alias for the function. + MCSymbol *CurrentFnBeginLocal = nullptr; + /// A vector of all debug/EH info emitters we should use. This vector /// maintains ownership of the emitters. std::vector Handlers; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1042,8 +1042,13 @@ if (TM.getTargetTriple().isOSBinFormatELF()) { MCSymbol *Sym = getSymbolPreferLocal(MF->getFunction()); - if (Sym != CurrentFnSym) + if (Sym != CurrentFnSym) { + cast(Sym)->setType(ELF::STT_FUNC); + CurrentFnBeginLocal = Sym; OutStreamer->emitLabel(Sym); + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction); + } } } @@ -1709,6 +1714,8 @@ MCSymbolRefExpr::create(CurrentFnEnd, OutContext), MCSymbolRefExpr::create(CurrentFnSymForSize, OutContext), OutContext); OutStreamer->emitELFSize(CurrentFnSym, SizeExp); + if (CurrentFnBeginLocal) + OutStreamer->emitELFSize(CurrentFnBeginLocal, SizeExp); } for (const HandlerInfo &HI : Handlers) { @@ -2240,6 +2247,7 @@ CurrentFnSymForSize = CurrentFnSym; CurrentFnBegin = nullptr; + CurrentFnBeginLocal = nullptr; CurrentSectionBeginSym = nullptr; MBBSectionRanges.clear(); MBBSectionExceptionSyms.clear(); diff --git a/llvm/test/CodeGen/AArch64/elf-preemption.ll b/llvm/test/CodeGen/AArch64/elf-preemption.ll --- a/llvm/test/CodeGen/AArch64/elf-preemption.ll +++ b/llvm/test/CodeGen/AArch64/elf-preemption.ll @@ -76,12 +76,18 @@ ; ; PIC-LABEL: dsolocal_func: ; PIC: .Ldsolocal_func$local: +; PIC-NEXT: .type .Ldsolocal_func$local,@function ; PIC-NEXT: // %bb.0: ; PIC-NEXT: adrp x0, .Ldsolocal_func$local ; PIC-NEXT: add x0, x0, :lo12:.Ldsolocal_func$local ; PIC-NEXT: ret ret void()* bitcast(void()*()* @dsolocal_func to void()*) } +; UTC-ARGS: --disable +; PIC: [[END_LABEL:.Lfunc_end.+]]: +; PIC-NEXT: .size dsolocal_func, [[END_LABEL]]-dsolocal_func +; PIC-NEXT: .size .Ldsolocal_func$local, [[END_LABEL]]-dsolocal_func +; UTC-ARGS: --enable define weak dso_local void()* @weak_dsolocal_func() nounwind { ; CHECK-LABEL: weak_dsolocal_func: @@ -104,6 +110,7 @@ ; ; PIC-LABEL: call_dsolocal_func: ; PIC: .Lcall_dsolocal_func$local: +; PIC-NEXT: .type .Lcall_dsolocal_func$local,@function ; PIC-NEXT: // %bb.0: ; PIC-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill ; PIC-NEXT: bl .Ldsolocal_func$local @@ -112,3 +119,8 @@ call void()* @dsolocal_func() ret void } +; UTC-ARGS: --disable +; PIC: [[END_LABEL:.Lfunc_end.+]]: +; PIC-NEXT: .size call_dsolocal_func, [[END_LABEL]]-call_dsolocal_func +; PIC-NEXT: .size .Lcall_dsolocal_func$local, [[END_LABEL]]-call_dsolocal_func +; UTC-ARGS: --enable diff --git a/llvm/test/CodeGen/AArch64/semantic-interposition-asm.ll b/llvm/test/CodeGen/AArch64/semantic-interposition-asm.ll --- a/llvm/test/CodeGen/AArch64/semantic-interposition-asm.ll +++ b/llvm/test/CodeGen/AArch64/semantic-interposition-asm.ll @@ -25,6 +25,7 @@ define dso_local void @fun0() nounwind { ; CHECK-LABEL: fun0: ; CHECK: .Lfun0$local: +; CHECK-NEXT: .type .Lfun0$local,@function ; CHECK-NEXT: // %bb.0: // %entry ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/ARM/dso-local-func.ll b/llvm/test/CodeGen/ARM/dso-local-func.ll --- a/llvm/test/CodeGen/ARM/dso-local-func.ll +++ b/llvm/test/CodeGen/ARM/dso-local-func.ll @@ -11,6 +11,7 @@ ; CHECK-NEXT: .code 32 ; CHECK-NEXT: dsolocal_func: ; PIC-NEXT: .Ldsolocal_func$local: +; PIC-NEXT: .type .Ldsolocal_func$local,%function ; CHECK-NEXT: .fnstart ; CHECK-NEXT: @ %bb.0: ; STATIC-NEXT: movw r0, :lower16:dsolocal_func @@ -26,6 +27,7 @@ ; PIC-NEXT: .long dsolocal_func-(.LPC0_0+8) ; CHECK-NEXT: .Lfunc_end0: ; CHECK-NEXT: .size dsolocal_func, .Lfunc_end0-dsolocal_func +; PIC-NEXT: .size .Ldsolocal_func$local, .Lfunc_end0-dsolocal_func ; CHECK-NEXT: .cantunwind ; CHECK-NEXT: .fnend ret ptr @dsolocal_func diff --git a/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll b/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll --- a/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll +++ b/llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll @@ -18,9 +18,8 @@ ; RELOCS-NEXT: } ; RELOCS-NEXT: Section (7) .rel.text.test { ; RELOCS-NEXT: 0x4 R_ARM_CALL _ZdlPv -; FIXME: these two relocation should not be against the section! -; RELOCS-NEXT: 0xC R_ARM_ABS32 .text._ZdlPv -; RELOCS-NEXT: 0x10 R_ARM_ABS32 .text._ZdlPv +; RELOCS-NEXT: 0xC R_ARM_ABS32 .L_ZdlPv$local +; RELOCS-NEXT: 0x10 R_ARM_ABS32 .L_ZdlPv$local ; RELOCS-NEXT: 0x1C R_ARM_REL32 _ZdlPv ; RELOCS-NEXT: } ; RELOCS-NEXT: Section (9) .rel.ARM.exidx.text.test { @@ -32,17 +31,15 @@ ; RELOCS-NEXT: ] ; RELOCS-LABEL: Symbols [ -; RELOCS: Symbol { -; FIXME: we should include the symbol in the symbol table! -; RELOCS-NOT: Name: .L_ZdlPv$local -; RELOCS-TODO: Name: .L_ZdlPv$local -; RELOCS-TODO: Value: 0x1 -; RELOCS-TODO: Size: 2 -; RELOCS-TODO: Binding: Local (0x0) -; RELOCS-TODO: Type: Function (0x2) -; RELOCS-TODO: Other: 0 -; RELOCS-TODO: Section: .text._ZdlPv ( -; RELOCS-TODO: } +; RELOCS: Symbol { +; RELOCS: Name: .L_ZdlPv$local +; RELOCS-NEXT: Value: 0x1 +; RELOCS-NEXT: Size: 2 +; RELOCS-NEXT: Binding: Local (0x0) +; RELOCS-NEXT: Type: Function (0x2) +; RELOCS-NEXT: Other: 0 +; RELOCS-NEXT: Section: .text._ZdlPv ( +; RELOCS-NEXT: } define dso_local void @_ZdlPv(ptr %ptr) local_unnamed_addr nounwind "target-features"="+armv7-a,+thumb-mode" { ; CHECK-LABEL: .section .text._ZdlPv,"ax",%progbits @@ -53,11 +50,13 @@ ; CHECK-NEXT: .thumb_func ; CHECK-NEXT: _ZdlPv: ; CHECK-NEXT: .L_ZdlPv$local: +; CHECK-NEXT: .type .L_ZdlPv$local,%function ; CHECK-NEXT: .fnstart ; CHECK-NEXT: @ %bb.0: ; CHECK-NEXT: bx lr ; CHECK-NEXT: .Lfunc_end0: ; CHECK-NEXT: .size _ZdlPv, .Lfunc_end0-_ZdlPv +; CHECK-NEXT: .size .L_ZdlPv$local, .Lfunc_end0-_ZdlPv ; CHECK-NEXT: .cantunwind ; CHECK-NEXT: .fnend ret void diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.generated.expected --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.generated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.generated.expected @@ -66,6 +66,7 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } ; CHECK-LABEL: check_boundaries: ; CHECK: check_boundaries$local: +; CHECK-NEXT: .type check_boundaries$local,@function ; CHECK-NEXT: ; %bb.0: ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CHECK-NEXT: s_mov_b32 s4, s33 @@ -76,6 +77,7 @@ ; ; CHECK-LABEL: main: ; CHECK: main$local: +; CHECK-NEXT: .type main$local,@function ; CHECK-NEXT: ; %bb.0: ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CHECK-NEXT: s_mov_b32 s6, s33 diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.nogenerated.expected --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.nogenerated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.nogenerated.expected @@ -7,6 +7,7 @@ define dso_local i32 @check_boundaries() #0 { ; CHECK-LABEL: check_boundaries: ; CHECK: check_boundaries$local: +; CHECK-NEXT: .type check_boundaries$local,@function ; CHECK-NEXT: ; %bb.0: ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CHECK-NEXT: s_mov_b32 s4, s33 @@ -53,6 +54,7 @@ define dso_local i32 @main() #0 { ; CHECK-LABEL: main: ; CHECK: main$local: +; CHECK-NEXT: .type main$local,@function ; CHECK-NEXT: ; %bb.0: ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CHECK-NEXT: s_mov_b32 s6, s33 diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.generated.expected --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.generated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.generated.expected @@ -66,6 +66,7 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } ; CHECK-LABEL: check_boundaries: ; CHECK: .Lcheck_boundaries$local: +; CHECK-NEXT: .type .Lcheck_boundaries$local,@function ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: ! %bb.0: ; CHECK-NEXT: st %fp, [--%sp] @@ -113,6 +114,7 @@ ; ; CHECK-LABEL: main: ; CHECK: .Lmain$local: +; CHECK-NEXT: .type .Lmain$local,@function ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: ! %bb.0: ; CHECK-NEXT: st %fp, [--%sp] diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.nogenerated.expected --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.nogenerated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.nogenerated.expected @@ -7,6 +7,7 @@ define dso_local i32 @check_boundaries() #0 { ; CHECK-LABEL: check_boundaries: ; CHECK: .Lcheck_boundaries$local: +; CHECK-NEXT: .type .Lcheck_boundaries$local,@function ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: ! %bb.0: ; CHECK-NEXT: st %fp, [--%sp] @@ -90,6 +91,7 @@ define dso_local i32 @main() #0 { ; CHECK-LABEL: main: ; CHECK: .Lmain$local: +; CHECK-NEXT: .type .Lmain$local,@function ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: ! %bb.0: ; CHECK-NEXT: st %fp, [--%sp] diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -16,7 +16,8 @@ ASM_FUNCTION_X86_RE = re.compile( r'^_?(?P[^:]+):[ \t]*#+[ \t]*(@"?(?P=func)"?| -- Begin function (?P=func))\n(?:\s*\.?Lfunc_begin[^:\n]*:\n)?' - r'(?:\.L[^$]+\$local:\n)?' # drop .L$local: + r'(?:\.L(?P=func)\$local:\n)?' # drop .L$local: + r'(?:\s*\.type\s+\.L(?P=func)\$local,@function\n)?' # drop .type .L$local r'(?:[ \t]+.cfi_startproc\n|.seh_proc[^\n]+\n)?' # drop optional cfi r'(?P^##?[ \t]+[^:]+:.*?)\s*' r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section|#+ -- End function)', @@ -25,6 +26,7 @@ ASM_FUNCTION_ARM_RE = re.compile( r'^(?P[0-9a-zA-Z_$]+):\n' # f: (name of function) r'(?:\.L(?P=func)\$local:\n)?' # drop .L$local: + r'(?:\s*\.type\s+\.L(?P=func)\$local,@function\n)?' # drop .type .L$local r'\s+\.fnstart\n' # .fnstart r'(?P.*?)' # (body of the function) r'^.Lfunc_end[0-9]+:', # .Lfunc_end0: or # -- End function @@ -95,6 +97,7 @@ ASM_FUNCTION_RISCV_RE = re.compile( r'^_?(?P[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n' r'(?:\s*\.?L(?P=func)\$local:\n)?' # optional .L$local: due to -fno-semantic-interposition + r'(?:\s*\.type\s+\.?L(?P=func)\$local,@function\n)?' # optional .type .L$local r'(?:\s*\.?Lfunc_begin[^:\n]*:\n)?[^:]*?' r'(?P^##?[ \t]+[^:]+:.*?)\s*' r'.Lfunc_end[0-9]+:\n',