summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCStreamer.h63
-rw-r--r--include/llvm/MC/MCTargetAsmParser.h5
-rw-r--r--lib/MC/MCParser/AsmParser.cpp4
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp104
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp3
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp7
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp248
-rw-r--r--lib/Target/ARM/MCTargetDesc/CMakeLists.txt1
-rw-r--r--test/CodeGen/ARM/inlineasm-ldr-pseudo.ll17
9 files changed, 312 insertions, 140 deletions
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 3228aa7bb9..2a677c5678 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -39,6 +39,7 @@ class StringRef;
class Twine;
class raw_ostream;
class formatted_raw_ostream;
+class AssemblerConstantPools;
typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair;
@@ -83,37 +84,51 @@ public:
// FIXME: declared here because it is used from
// lib/CodeGen/AsmPrinter/ARMException.cpp.
class ARMTargetStreamer : public MCTargetStreamer {
- virtual void anchor();
public:
ARMTargetStreamer(MCStreamer &S);
-
- virtual void emitFnStart() = 0;
- virtual void emitFnEnd() = 0;
- virtual void emitCantUnwind() = 0;
- virtual void emitPersonality(const MCSymbol *Personality) = 0;
- virtual void emitPersonalityIndex(unsigned Index) = 0;
- virtual void emitHandlerData() = 0;
+ ~ARMTargetStreamer();
+
+ virtual void emitFnStart();
+ virtual void emitFnEnd();
+ virtual void emitCantUnwind();
+ virtual void emitPersonality(const MCSymbol *Personality);
+ virtual void emitPersonalityIndex(unsigned Index);
+ virtual void emitHandlerData();
virtual void emitSetFP(unsigned FpReg, unsigned SpReg,
- int64_t Offset = 0) = 0;
- virtual void emitMovSP(unsigned Reg, int64_t Offset = 0) = 0;
- virtual void emitPad(int64_t Offset) = 0;
+ int64_t Offset = 0);
+ virtual void emitMovSP(unsigned Reg, int64_t Offset = 0);
+ virtual void emitPad(int64_t Offset);
virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
- bool isVector) = 0;
+ bool isVector);
virtual void emitUnwindRaw(int64_t StackOffset,
- const SmallVectorImpl<uint8_t> &Opcodes) = 0;
+ const SmallVectorImpl<uint8_t> &Opcodes);
- virtual void switchVendor(StringRef Vendor) = 0;
- virtual void emitAttribute(unsigned Attribute, unsigned Value) = 0;
- virtual void emitTextAttribute(unsigned Attribute, StringRef String) = 0;
+ virtual void switchVendor(StringRef Vendor);
+ virtual void emitAttribute(unsigned Attribute, unsigned Value);
+ virtual void emitTextAttribute(unsigned Attribute, StringRef String);
virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
- StringRef StringValue = "") = 0;
- virtual void emitFPU(unsigned FPU) = 0;
- virtual void emitArch(unsigned Arch) = 0;
- virtual void emitObjectArch(unsigned Arch) = 0;
- virtual void finishAttributeSection() = 0;
- virtual void emitInst(uint32_t Inst, char Suffix = '\0') = 0;
-
- virtual void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) = 0;
+ StringRef StringValue = "");
+ virtual void emitFPU(unsigned FPU);
+ virtual void emitArch(unsigned Arch);
+ virtual void emitObjectArch(unsigned Arch);
+ virtual void finishAttributeSection();
+ virtual void emitInst(uint32_t Inst, char Suffix = '\0');
+
+ virtual void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE);
+
+ virtual void finish();
+
+ /// Callback used to implement the ldr= pseudo.
+ /// Add a new entry to the constant pool for the current section and return an
+ /// MCExpr that can be used to refer to the constant pool location.
+ const MCExpr *addConstantPoolEntry(const MCExpr *);
+
+ /// Callback used to implemnt the .ltorg directive.
+ /// Emit contents of constant pool for the current section.
+ void emitCurrentConstantPool();
+
+private:
+ OwningPtr<AssemblerConstantPools> ConstantPools;
};
/// MCStreamer - Streaming machine code generation interface. This interface
diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h
index c5fb30ef99..0073136015 100644
--- a/include/llvm/MC/MCTargetAsmParser.h
+++ b/include/llvm/MC/MCTargetAsmParser.h
@@ -182,11 +182,6 @@ public:
return 0;
}
- /// Allow a target to perform any actions after the parse completes
- /// successfully. For example, to write out constant pools for ldr pseudo on
- /// ARM.
- virtual void finishParse() {};
-
virtual void onLabelParsed(MCSymbol *Symbol) { };
};
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 63a00fedfa..459e126793 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -681,10 +681,6 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
}
}
- // Callback to the target parser in case it needs to do anything.
- if (!HadError)
- getTargetParser().finishParse();
-
// Finalize the output stream if there are no errors and if the client wants
// us to.
if (!HadError && !NoFinalize)
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 74e4e66c6e..288d9b96da 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -56,64 +56,6 @@ class ARMOperand;
enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
-// A class to keep track of assembler-generated constant pools that are use to
-// implement the ldr-pseudo.
-class ConstantPool {
- typedef SmallVector<std::pair<MCSymbol *, const MCExpr *>, 4> EntryVecTy;
- EntryVecTy Entries;
-
-public:
- // Initialize a new empty constant pool
- ConstantPool() { }
-
- // Add a new entry to the constant pool in the next slot.
- // \param Value is the new entry to put in the constant pool.
- //
- // \returns a MCExpr that references the newly inserted value
- const MCExpr *addEntry(const MCExpr *Value, MCContext &Context) {
- MCSymbol *CPEntryLabel = Context.CreateTempSymbol();
-
- Entries.push_back(std::make_pair(CPEntryLabel, Value));
- return MCSymbolRefExpr::Create(CPEntryLabel, Context);
- }
-
- // Emit the contents of the constant pool using the provided streamer.
- void emitEntries(MCStreamer &Streamer) {
- if (Entries.empty())
- return;
- Streamer.EmitCodeAlignment(4); // align to 4-byte address
- Streamer.EmitDataRegion(MCDR_DataRegion);
- for (EntryVecTy::const_iterator I = Entries.begin(), E = Entries.end();
- I != E; ++I) {
- Streamer.EmitLabel(I->first);
- Streamer.EmitValue(I->second, 4);
- }
- Streamer.EmitDataRegion(MCDR_DataRegionEnd);
- Entries.clear();
- }
-
- // Return true if the constant pool is empty
- bool empty() {
- return Entries.empty();
- }
-};
-
-// Map type used to keep track of per-Section constant pools used by the
-// ldr-pseudo opcode. The map associates a section to its constant pool. The
-// constant pool is a vector of (label, value) pairs. When the ldr
-// pseudo is parsed we insert a new (label, value) pair into the constant pool
-// for the current section and add MCSymbolRefExpr to the new label as
-// an opcode to the ldr. After we have parsed all the user input we
-// output the (label, value) pairs in each constant pool at the end of the
-// section.
-//
-// We use the MapVector for the map type to ensure stable iteration of
-// the sections at the end of the parse. We need to iterate over the
-// sections in a stable order to ensure that we have print the
-// constant pools in a deterministic order when printing an assembly
-// file.
-typedef MapVector<const MCSection *, ConstantPool> ConstantPoolMapTy;
-
class UnwindContext {
MCAsmParser &Parser;
@@ -191,22 +133,8 @@ class ARMAsmParser : public MCTargetAsmParser {
MCAsmParser &Parser;
const MCInstrInfo &MII;
const MCRegisterInfo *MRI;
- ConstantPoolMapTy ConstantPools;
UnwindContext UC;
- // Assembler created constant pools for ldr pseudo
- ConstantPool *getConstantPool(const MCSection *Section) {
- ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
- if (CP == ConstantPools.end())
- return 0;
-
- return &CP->second;
- }
-
- ConstantPool &getOrCreateConstantPool(const MCSection *Section) {
- return ConstantPools[Section];
- }
-
ARMTargetStreamer &getTargetStreamer() {
MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
return static_cast<ARMTargetStreamer &>(TS);
@@ -443,7 +371,6 @@ public:
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm);
void onLabelParsed(MCSymbol *Symbol);
- void finishParse();
};
} // end anonymous namespace
@@ -4812,17 +4739,13 @@ bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
return Error(Parser.getTok().getLoc(), "unexpected token in operand");
- const MCSection *Section =
- getParser().getStreamer().getCurrentSection().first;
- assert(Section);
Parser.Lex(); // Eat '='
const MCExpr *SubExprVal;
if (getParser().parseExpression(SubExprVal))
return true;
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- const MCExpr *CPLoc =
- getOrCreateConstantPool(Section).addEntry(SubExprVal, getContext());
+ const MCExpr *CPLoc = getTargetStreamer().addConstantPoolEntry(SubExprVal);
Operands.push_back(ARMOperand::CreateImm(CPLoc, S, E));
return false;
}
@@ -8843,13 +8766,7 @@ bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) {
/// parseDirectiveLtorg
/// ::= .ltorg | .pool
bool ARMAsmParser::parseDirectiveLtorg(SMLoc L) {
- MCStreamer &Streamer = getParser().getStreamer();
- const MCSection *Section = Streamer.getCurrentSection().first;
-
- if (ConstantPool *CP = getConstantPool(Section)) {
- if (!CP->empty())
- CP->emitEntries(Streamer);
- }
+ getTargetStreamer().emitCurrentConstantPool();
return false;
}
@@ -9181,20 +9098,3 @@ unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand *AsmOp,
}
return Match_InvalidOperand;
}
-
-void ARMAsmParser::finishParse() {
- // Dump contents of assembler constant pools.
- MCStreamer &Streamer = getParser().getStreamer();
- for (ConstantPoolMapTy::iterator CPI = ConstantPools.begin(),
- CPE = ConstantPools.end();
- CPI != CPE; ++CPI) {
- const MCSection *Section = CPI->first;
- ConstantPool &CP = CPI->second;
-
- // Dump non-empty assembler constant pools at the end of the section.
- if (!CP.empty()) {
- Streamer.SwitchSection(Section);
- CP.emitEntries(Streamer);
- }
- }
-}
diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
index 44b56fbe19..710f19a863 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
@@ -104,9 +104,6 @@ static unsigned GetArchDefaultCPUArch(unsigned ID) {
return 0;
}
-void ARMTargetStreamer::anchor() {}
-ARMTargetStreamer::ARMTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
-
namespace {
class ARMELFStreamer;
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
index 4581f41130..434f27f46f 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
@@ -247,8 +247,11 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
bool NoExecStack) {
Triple TheTriple(TT);
- if (TheTriple.isOSBinFormatMachO())
- return createMachOStreamer(Ctx, MAB, OS, Emitter, false);
+ if (TheTriple.isOSBinFormatMachO()) {
+ MCStreamer *S = createMachOStreamer(Ctx, MAB, OS, Emitter, false);
+ new ARMTargetStreamer(*S);
+ return S;
+ }
if (TheTriple.isOSWindows()) {
llvm_unreachable("ARM does not support Windows COFF format");
diff --git a/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
new file mode 100644
index 0000000000..ce8b67f1ee
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
@@ -0,0 +1,248 @@
+//===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- C++ -*---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ARMTargetStreamer class.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/ADT/MapVector.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCContext.h"
+
+using namespace llvm;
+
+namespace {
+// A class to keep track of assembler-generated constant pools that are use to
+// implement the ldr-pseudo.
+class ConstantPool {
+ typedef SmallVector<std::pair<MCSymbol *, const MCExpr *>, 4> EntryVecTy;
+ EntryVecTy Entries;
+
+public:
+ // Initialize a new empty constant pool
+ ConstantPool() {}
+
+ // Add a new entry to the constant pool in the next slot.
+ // \param Value is the new entry to put in the constant pool.
+ //
+ // \returns a MCExpr that references the newly inserted value
+ const MCExpr *addEntry(const MCExpr *Value, MCContext &Context);
+
+ // Emit the contents of the constant pool using the provided streamer.
+ void emitEntries(MCStreamer &Streamer);
+
+ // Return true if the constant pool is empty
+ bool empty();
+};
+}
+
+namespace llvm {
+class AssemblerConstantPools {
+ // Map type used to keep track of per-Section constant pools used by the
+ // ldr-pseudo opcode. The map associates a section to its constant pool. The
+ // constant pool is a vector of (label, value) pairs. When the ldr
+ // pseudo is parsed we insert a new (label, value) pair into the constant pool
+ // for the current section and add MCSymbolRefExpr to the new label as
+ // an opcode to the ldr. After we have parsed all the user input we
+ // output the (label, value) pairs in each constant pool at the end of the
+ // section.
+ //
+ // We use the MapVector for the map type to ensure stable iteration of
+ // the sections at the end of the parse. We need to iterate over the
+ // sections in a stable order to ensure that we have print the
+ // constant pools in a deterministic order when printing an assembly
+ // file.
+ typedef MapVector<const MCSection *, ConstantPool> ConstantPoolMapTy;
+ ConstantPoolMapTy ConstantPools;
+
+public:
+ AssemblerConstantPools() {}
+ ~AssemblerConstantPools() {}
+
+ void emitAll(MCStreamer &Streamer);
+ void emitForCurrentSection(MCStreamer &Streamer);
+ const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr);
+
+private:
+ ConstantPool *getConstantPool(const MCSection *Section);
+ ConstantPool &getOrCreateConstantPool(const MCSection *Section);
+};
+}
+
+//
+// ConstantPool implementation
+//
+// Emit the contents of the constant pool using the provided streamer.
+void ConstantPool::emitEntries(MCStreamer &Streamer) {
+ if (Entries.empty())
+ return;
+ Streamer.EmitCodeAlignment(4); // align to 4-byte address
+ Streamer.EmitDataRegion(MCDR_DataRegion);
+ for (EntryVecTy::const_iterator I = Entries.begin(), E = Entries.end();
+ I != E; ++I) {
+ Streamer.EmitLabel(I->first);
+ Streamer.EmitValue(I->second, 4);
+ }
+ Streamer.EmitDataRegion(MCDR_DataRegionEnd);
+ Entries.clear();
+}
+
+const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context) {
+ MCSymbol *CPEntryLabel = Context.CreateTempSymbol();
+
+ Entries.push_back(std::make_pair(CPEntryLabel, Value));
+ return MCSymbolRefExpr::Create(CPEntryLabel, Context);
+}
+
+bool ConstantPool::empty() { return Entries.empty(); }
+
+//
+// AssemblerConstantPools implementation
+//
+ConstantPool *
+AssemblerConstantPools::getConstantPool(const MCSection *Section) {
+ ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
+ if (CP == ConstantPools.end())
+ return 0;
+
+ return &CP->second;
+}
+
+ConstantPool &
+AssemblerConstantPools::getOrCreateConstantPool(const MCSection *Section) {
+ return ConstantPools[Section];
+}
+
+static void emitConstantPool(MCStreamer &Streamer, const MCSection *Section,
+ ConstantPool &CP) {
+ if (!CP.empty()) {
+ Streamer.SwitchSection(Section);
+ CP.emitEntries(Streamer);
+ }
+}
+
+void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
+ // Dump contents of assembler constant pools.
+ for (ConstantPoolMapTy::iterator CPI = ConstantPools.begin(),
+ CPE = ConstantPools.end();
+ CPI != CPE; ++CPI) {
+ const MCSection *Section = CPI->first;
+ ConstantPool &CP = CPI->second;
+
+ emitConstantPool(Streamer, Section, CP);
+ }
+}
+
+void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
+ const MCSection *Section = Streamer.getCurrentSection().first;
+ if (ConstantPool *CP = getConstantPool(Section)) {
+ emitConstantPool(Streamer, Section, *CP);
+ }
+}
+
+const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
+ const MCExpr *Expr) {
+ const MCSection *Section = Streamer.getCurrentSection().first;
+ return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext());
+}
+
+//
+// ARMTargetStreamer Implemenation
+//
+ARMTargetStreamer::ARMTargetStreamer(MCStreamer &S)
+ : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {}
+
+ARMTargetStreamer::~ARMTargetStreamer() {}
+
+// The constant pool handling is shared by all ARMTargetStreamer
+// implementations.
+const MCExpr *ARMTargetStreamer::addConstantPoolEntry(const MCExpr *Expr) {
+ return ConstantPools->addEntry(Streamer, Expr);
+}
+
+void ARMTargetStreamer::emitCurrentConstantPool() {
+ ConstantPools->emitForCurrentSection(Streamer);
+}
+
+// finish() - write out any non-empty assembler constant pools.
+void ARMTargetStreamer::finish() { ConstantPools->emitAll(Streamer); }
+
+// The remaining callbacks should be handled separately by each
+// streamer.
+void ARMTargetStreamer::emitFnStart() {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitFnEnd() {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitCantUnwind() {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitHandlerData() {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
+ int64_t Offset) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitPad(int64_t Offset) {
+ llvm_unreachable("unimplemented");
+}
+void
+ARMTargetStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
+ bool isVector) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitUnwindRaw(
+ int64_t StackOffset, const SmallVectorImpl<uint8_t> &Opcodes) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::switchVendor(StringRef Vendor) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitTextAttribute(unsigned Attribute,
+ StringRef String) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute,
+ unsigned IntValue,
+ StringRef StringValue) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitArch(unsigned Arch) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitObjectArch(unsigned Arch) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitFPU(unsigned FPU) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::finishAttributeSection() {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {
+ llvm_unreachable("unimplemented");
+}
+void ARMTargetStreamer::AnnotateTLSDescriptorSequence(
+ const MCSymbolRefExpr *SRE) {
+ llvm_unreachable("unimplemented");
+}
diff --git a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
index 162de7d21e..06812d4503 100644
--- a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
@@ -8,6 +8,7 @@ add_llvm_library(LLVMARMDesc
ARMMCTargetDesc.cpp
ARMMachObjectWriter.cpp
ARMELFObjectWriter.cpp
+ ARMTargetStreamer.cpp
ARMUnwindOpAsm.cpp
ARMMachORelocationInfo.cpp
)
diff --git a/test/CodeGen/ARM/inlineasm-ldr-pseudo.ll b/test/CodeGen/ARM/inlineasm-ldr-pseudo.ll
new file mode 100644
index 0000000000..f63e4b0b3a
--- /dev/null
+++ b/test/CodeGen/ARM/inlineasm-ldr-pseudo.ll
@@ -0,0 +1,17 @@
+; PR18354
+; We actually need to use -filetype=obj in this test because if we output
+; assembly, the current code path will bypass the parser and just write the
+; raw text out to the Streamer. We need to actually parse the inlineasm to
+; demonstrate the bug. Going the asm->obj route does not show the issue.
+; RUN: llc -mtriple=arm-none-linux < %s -filetype=obj | llvm-objdump -d - | FileCheck %s
+; RUN: llc -mtriple=arm-apple-darwin < %s -filetype=obj | llvm-objdump -d - | FileCheck %s
+; CHECK-LABEL: foo:
+; CHECK: 0: 00 00 9f e5 ldr r0, [pc]
+; CHECK: 4: 0e f0 a0 e1 mov pc, lr
+; Make sure the constant pool entry comes after the return
+; CHECK: 8: 01 00 00 00
+define i32 @foo() nounwind {
+entry:
+ %0 = tail call i32 asm sideeffect "ldr $0,=1", "=r"() nounwind
+ ret i32 %0
+}