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;
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);
+ }
}
}
MCSymbolRefExpr::create(CurrentFnEnd, OutContext),
MCSymbolRefExpr::create(CurrentFnSymForSize, OutContext), OutContext);
OutStreamer->emitELFSize(CurrentFnSym, SizeExp);
+ if (CurrentFnBeginLocal)
+ OutStreamer->emitELFSize(CurrentFnBeginLocal, SizeExp);
}
for (const HandlerInfo &HI : Handlers) {
CurrentFnSymForSize = CurrentFnSym;
CurrentFnBegin = nullptr;
+ CurrentFnBeginLocal = nullptr;
CurrentSectionBeginSym = nullptr;
MBBSectionRanges.clear();
MBBSectionExceptionSyms.clear();
;
; 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:
;
; 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
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
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:
; 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
; 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
; 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
; 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
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
;
; 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
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
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
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]
;
; 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]
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]
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]
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)',
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
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',