llvm-6502/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
David Peixotto b92cca2228 Fix PR18345: ldr= pseudo instruction produces incorrect code when using in inline assembly
This patch fixes the ldr-pseudo implementation to work when used in
inline assembly.  The fix is to move arm assembler constant pools
from the ARMAsmParser class to the ARMTargetStreamer class.

Previously we kept the assembler generated constant pools in the
ARMAsmParser object. This does not work for inline assembly because
a new parser object is created for each blob of inline assembly.
This patch moves the constant pools to the ARMTargetStreamer class
so that the constant pool will remain alive for the entire code
generation process.

An ARMTargetStreamer class is now required for the arm backend.
There was no existing implementation for MachO, only Asm and ELF.
Instead of creating an empty MachO subclass, we decided to make the
ARMTargetStreamer a non-abstract class and provide default
(llvm_unreachable) implementations for the non constant-pool related
methods.

Differential Revision: http://llvm-reviews.chandlerc.com/D2638


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200777 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-04 17:22:40 +00:00

249 lines
8.1 KiB
C++

//===- 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");
}