summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2014-03-22 19:26:18 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2014-03-22 19:26:18 +0000
commit44419fc3cdc126898caa87824287dd6065942a2e (patch)
treeb411b3bb1084b3210f49e67082db3e51e79b2537
parent55805eb562abe19a6bbea29c8f416377cc742963 (diff)
downloadbcm5719-llvm-44419fc3cdc126898caa87824287dd6065942a2e.tar.gz
bcm5719-llvm-44419fc3cdc126898caa87824287dd6065942a2e.zip
ARM IAS: properly handle function entries in .thumb
When a label is parsed, check if there is type information available for the label. If so, check if the symbol is a function. If the symbol is a function and we are in thumb mode and no explicit thumb_func has been emitted, adjust the symbol data to indicate that the function definition is a thumb function. The application of this inferencing is improved value handling in the object file (the required thumb bit is set on symbols which are thumb functions). It also helps improve compatibility with binutils. The one complication that arises from this handling is the MCAsmStreamer. The default implementation of getOrCreateSymbolData in MCStreamer does not support tracking the symbol data. In order to support the semantics of thumb functions, track symbol data in assembly streamer. Although O(n) in number of labels in the TU, this is already done in various other streamers and as such the memory overhead is not a practical concern in this scenario. llvm-svn: 204544
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp13
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp30
-rw-r--r--llvm/test/MC/ARM/thumb-types.s82
-rw-r--r--llvm/test/MC/ARM/thumb_set.s3
4 files changed, 126 insertions, 2 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 759058efcba..85d4dd79b30 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -57,6 +57,8 @@ private:
EHPrivateExtern = 1 << 2 };
DenseMap<const MCSymbol*, unsigned> FlagMap;
+ DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap;
+
bool needsSet(const MCExpr *Value);
void EmitRegisterName(int64_t Register);
@@ -252,6 +254,8 @@ public:
void EmitRawTextImpl(StringRef String) override;
void FinishImpl() override;
+
+ virtual MCSymbolData &getOrCreateSymbolData(const MCSymbol *Symbol) override;
};
} // end anonymous namespace.
@@ -1417,6 +1421,15 @@ void MCAsmStreamer::FinishImpl() {
EmitFrames(AsmBackend.get(), false);
}
+MCSymbolData &MCAsmStreamer::getOrCreateSymbolData(const MCSymbol *Symbol) {
+ MCSymbolData *&Entry = SymbolMap[Symbol];
+
+ if (!Entry)
+ Entry = new MCSymbolData(*Symbol, 0, 0, 0);
+
+ return *Entry;
+}
+
MCStreamer *llvm::createAsmStreamer(MCContext &Context,
formatted_raw_ostream &OS,
bool isVerboseAsm, bool useCFI,
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index ccb1c641efe..1a153522796 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -25,7 +25,9 @@
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCELF.h"
#include "llvm/MC/MCELFStreamer.h"
+#include "llvm/MC/MCELFSymbolFlags.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrDesc.h"
@@ -8085,6 +8087,7 @@ bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
if (!isThumb())
SwitchMode();
+
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
return false;
}
@@ -8105,6 +8108,7 @@ bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
if (isThumb())
SwitchMode();
+
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
return false;
}
@@ -8113,6 +8117,32 @@ void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) {
if (NextSymbolIsThumb) {
getParser().getStreamer().EmitThumbFunc(Symbol);
NextSymbolIsThumb = false;
+ return;
+ }
+
+ if (!isThumb())
+ return;
+
+ const MCObjectFileInfo::Environment Format =
+ getContext().getObjectFileInfo()->getObjectFileType();
+ switch (Format) {
+ case MCObjectFileInfo::IsCOFF: {
+ const MCSymbolData &SD =
+ getParser().getStreamer().getOrCreateSymbolData(Symbol);
+ char Type = COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT;
+ if (SD.getFlags() & (Type << COFF::SF_TypeShift))
+ getParser().getStreamer().EmitThumbFunc(Symbol);
+ break;
+ }
+ case MCObjectFileInfo::IsELF: {
+ const MCSymbolData &SD =
+ getParser().getStreamer().getOrCreateSymbolData(Symbol);
+ if (MCELF::GetType(SD) & (ELF::STT_FUNC << ELF_STT_Shift))
+ getParser().getStreamer().EmitThumbFunc(Symbol);
+ break;
+ }
+ case MCObjectFileInfo::IsMachO:
+ break;
}
}
diff --git a/llvm/test/MC/ARM/thumb-types.s b/llvm/test/MC/ARM/thumb-types.s
new file mode 100644
index 00000000000..2fd71525bab
--- /dev/null
+++ b/llvm/test/MC/ARM/thumb-types.s
@@ -0,0 +1,82 @@
+@ RUN: llvm-mc -triple armv7-elf -filetype obj -o - %s | llvm-readobj -t \
+@ RUN: | FileCheck %s
+
+ .syntax unified
+
+ .thumb
+
+ .type implicit_function,%function
+implicit_function:
+ nop
+
+ .type implicit_data,%object
+implicit_data:
+ .long 0
+
+ .arm
+ .type arm_function,%function
+arm_function:
+ nop
+
+ .thumb
+
+ .text
+
+untyped_text_label:
+ nop
+
+ .type explicit_function,%function
+explicit_function:
+ nop
+
+ .data
+
+untyped_data_label:
+ nop
+
+ .type explicit_data,%object
+explicit_data:
+ .long 0
+
+@ CHECK: Symbol {
+@ CHECK: Name: arm_function
+@ CHECK: Value: 0x6
+@ CHECK: Type: Function
+@ CHECK: }
+
+@ CHECK: Symbol {
+@ CHECK: Name: explicit_data
+@ CHECK: Value: 0x2
+@ CHECK: Type: Object
+@ CHECK: }
+
+@ CHECK: Symbol {
+@ CHECK: Name: explicit_function
+@ CHECK: Value: 0xD
+@ CHECK: Type: Function
+@ CHECK: }
+
+@ CHECK: Symbol {
+@ CHECK: Name: implicit_data
+@ CHECK: Value: 0x2
+@ CHECK: Type: Object
+@ CHECK: }
+
+@ CHECK: Symbol {
+@ CHECK: Name: implicit_function
+@ CHECK: Value: 0x1
+@ CHECK: Type: Function
+@ CHECK: }
+
+@ CHECK: Symbol {
+@ CHECK: Name: untyped_data_label
+@ CHECK: Value: 0x0
+@ CHECK: Type: None
+@ CHECK: }
+
+@ CHECK: Symbol {
+@ CHECK: Name: untyped_text_label
+@ CHECK: Value: 0xA
+@ CHECK: Type: None
+@ CHECK: }
+
diff --git a/llvm/test/MC/ARM/thumb_set.s b/llvm/test/MC/ARM/thumb_set.s
index 7381a98134d..d0bc9858ddc 100644
--- a/llvm/test/MC/ARM/thumb_set.s
+++ b/llvm/test/MC/ARM/thumb_set.s
@@ -79,8 +79,7 @@ beta:
@ CHECK: Symbol {
@ CHECK: Name: alpha
-@ CHECK: Value: 0x6
-@ XFAIL-CHECK: Value: 0x7
+@ CHECK: Value: 0x7
@ CHECK: Type: Function
@ CHECK: }
OpenPOWER on IntegriCloud