diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -579,6 +579,28 @@ } } + /// If a label is defined before the .type directive sets the label's type + /// then the label can't be recorded as thumb function when the label is + /// defined. We override emitSymbolAttribute() which is called as part of the + /// parsing of .type so that if the symbol has already been defined we can + /// record the label as Thumb. FIXME: there is a corner case where the state + /// is changed in between the label definition and the .type directive, this + /// is not expected to occur in practice and handling it would require the + /// backend to track IsThumb for every label. + bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { + bool Val = MCELFStreamer::emitSymbolAttribute(Symbol, Attribute); + + if (!IsThumb) + return Val; + + unsigned Type = cast(Symbol)->getType(); + if ((Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC) && + Symbol->isDefined()) + getAssembler().setIsThumbFunc(Symbol); + + return Val; + }; + private: enum ElfMappingSymbol { EMS_None, diff --git a/llvm/test/MC/ARM/thumb-function-address.s b/llvm/test/MC/ARM/thumb-function-address.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ARM/thumb-function-address.s @@ -0,0 +1,20 @@ +@ RUN: llvm-mc -filetype=obj -triple=armv7-linux-gnueabi %s -o %t +@ RUN: llvm-readobj --symbols %t | FileCheck %s + + .syntax unified + .text + .thumb +func_label: + .type func_label, %function + +@ Check func_label address has bit 1 set. +@ CHECK: Symbol { +@ CHECK: Name: func_label (7) +@ CHECK: Value: 0x1 +@ CHECK: Size: 0 +@ CHECK: Binding: Local (0x0) +@ CHECK: Type: Function (0x2) +@ CHECK: Other: 0 +@ CHECK: Section: .text (0x2) +@ CHECK: } +