Mark the $local function begin symbol as a function
authorAlex Richardson <alexrichardson@google.com>
Thu, 25 Aug 2022 12:15:47 +0000 (12:15 +0000)
committerAlex Richardson <alexrichardson@google.com>
Fri, 26 Aug 2022 09:34:04 +0000 (09:34 +0000)
While this does not matter for most targets, when building for Arm Morello,
we have to mark the symbol as a function and add size information, so that
LLD can correctly evaluate relocations against the local symbol.
Since Morello is an out-of-tree target, I tried to reproduce this with
in-tree backends and with the previous reviews applied this results in
a noticeable difference when targeting Thumb.

Background: Morello uses a method similar Thumb where the encoding mode is
specified in the LSB of the symbol. If we don't mark the target as a
function, the relocation will not have the LSB set and calls will end up
using the wrong encoding mode (which will almost certainly crash).

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D131429

llvm/include/llvm/CodeGen/AsmPrinter.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/test/CodeGen/AArch64/elf-preemption.ll
llvm/test/CodeGen/AArch64/semantic-interposition-asm.ll
llvm/test/CodeGen/ARM/dso-local-func.ll
llvm/test/CodeGen/ARM/thumb-function-section-reloc.ll
llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.generated.expected
llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/amdgpu_generated_funcs.ll.nogenerated.expected
llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.generated.expected
llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_generated_funcs.ll.nogenerated.expected
llvm/utils/UpdateTestChecks/asm.py

index d5b844b..989cb71 100644 (file)
@@ -194,6 +194,9 @@ private:
 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<HandlerInfo> Handlers;
index c335577..ea9399c 100644 (file)
@@ -1042,8 +1042,13 @@ void AsmPrinter::emitFunctionEntryLabel() {
 
   if (TM.getTargetTriple().isOSBinFormatELF()) {
     MCSymbol *Sym = getSymbolPreferLocal(MF->getFunction());
-    if (Sym != CurrentFnSym)
+    if (Sym != CurrentFnSym) {
+      cast<MCSymbolELF>(Sym)->setType(ELF::STT_FUNC);
+      CurrentFnBeginLocal = Sym;
       OutStreamer->emitLabel(Sym);
+      if (MAI->hasDotTypeDotSizeDirective())
+        OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
+    }
   }
 }
 
@@ -1709,6 +1714,8 @@ void AsmPrinter::emitFunctionBody() {
         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 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
 
   CurrentFnSymForSize = CurrentFnSym;
   CurrentFnBegin = nullptr;
+  CurrentFnBeginLocal = nullptr;
   CurrentSectionBeginSym = nullptr;
   MBBSectionRanges.clear();
   MBBSectionExceptionSyms.clear();
index 7507837..3b77f5b 100644 (file)
@@ -76,12 +76,18 @@ define dso_local void()* @dsolocal_func() nounwind {
 ;
 ; 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 @@ define dso_local void @call_dsolocal_func() nounwind {
 ;
 ; 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 @@ define dso_local void @call_dsolocal_func() nounwind {
   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
index e09d16d..7c14664 100644 (file)
@@ -25,6 +25,7 @@ entry:
 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:
index ae57bbe..6dfbe32 100644 (file)
@@ -11,6 +11,7 @@ define dso_local ptr @dsolocal_func() nounwind {
 ; 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 @@ define dso_local ptr @dsolocal_func() nounwind {
 ; 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
index 31f6ae2..e5a980f 100644 (file)
@@ -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 {
 ; 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 @@ define dso_local void @_ZdlPv(ptr %ptr) local_unnamed_addr nounwind "target-feat
 ; 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
index d8880ff..758ea1a 100644 (file)
@@ -66,6 +66,7 @@ define dso_local i32 @main() #0 {
 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 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" }
 ;
 ; 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
index be208f0..a8a36fd 100644 (file)
@@ -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 @check_boundaries() #0 {
 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
index 36a9525..a41bc63 100644 (file)
@@ -66,6 +66,7 @@ define dso_local i32 @main() #0 {
 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 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" }
 ;
 ; 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]
index 9336609..35ebbf9 100644 (file)
@@ -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 @check_boundaries() #0 {
 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]
index db853ea..1366e10 100644 (file)
@@ -16,7 +16,8 @@ else:
 
 ASM_FUNCTION_X86_RE = re.compile(
     r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*(@"?(?P=func)"?| -- Begin function (?P=func))\n(?:\s*\.?Lfunc_begin[^:\n]*:\n)?'
-    r'(?:\.L[^$]+\$local:\n)?'      # drop .L<func>$local:
+    r'(?:\.L(?P=func)\$local:\n)?'      # drop .L<func>$local:
+    r'(?:\s*\.type\s+\.L(?P=func)\$local,@function\n)?'  # drop .type .L<func>$local
     r'(?:[ \t]+.cfi_startproc\n|.seh_proc[^\n]+\n)?'  # drop optional cfi
     r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
     r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section|#+ -- End function)',
@@ -25,6 +26,7 @@ ASM_FUNCTION_X86_RE = re.compile(
 ASM_FUNCTION_ARM_RE = re.compile(
     r'^(?P<func>[0-9a-zA-Z_$]+):\n' # f: (name of function)
     r'(?:\.L(?P=func)\$local:\n)?'  # drop .L<func>$local:
+    r'(?:\s*\.type\s+\.L(?P=func)\$local,@function\n)?'  # drop .type .L<func>$local
     r'\s+\.fnstart\n' # .fnstart
     r'(?P<body>.*?)' # (body of the function)
     r'^.Lfunc_end[0-9]+:', # .Lfunc_end0: or # -- End function
@@ -95,6 +97,7 @@ ASM_FUNCTION_PPC_RE = re.compile(
 ASM_FUNCTION_RISCV_RE = re.compile(
     r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n'
     r'(?:\s*\.?L(?P=func)\$local:\n)?'  # optional .L<func>$local: due to -fno-semantic-interposition
+    r'(?:\s*\.type\s+\.?L(?P=func)\$local,@function\n)?'  # optional .type .L<func>$local
     r'(?:\s*\.?Lfunc_begin[^:\n]*:\n)?[^:]*?'
     r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
     r'.Lfunc_end[0-9]+:\n',