#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Target/TargetAsmBackend.h"
+#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
+#include <cctype>
using namespace llvm;
namespace {
const MCAsmInfo &MAI;
OwningPtr<MCInstPrinter> InstPrinter;
OwningPtr<MCCodeEmitter> Emitter;
+ OwningPtr<TargetAsmBackend> AsmBackend;
SmallString<128> CommentToEmit;
raw_svector_ostream CommentStream;
- const TargetLoweringObjectFile *TLOF;
- int PointerSize;
-
- unsigned IsLittleEndian : 1;
unsigned IsVerboseAsm : 1;
unsigned ShowInst : 1;
+ unsigned UseLoc : 1;
+
+ bool needsSet(const MCExpr *Value);
public:
MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
- bool isLittleEndian, bool isVerboseAsm,
- const TargetLoweringObjectFile *tlof, int pointerSize,
- MCInstPrinter *printer, MCCodeEmitter *emitter, bool showInst)
+ bool isVerboseAsm,
+ bool useLoc,
+ MCInstPrinter *printer, MCCodeEmitter *emitter,
+ TargetAsmBackend *asmbackend,
+ bool showInst)
: MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()),
- InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit),
- TLOF(tlof), PointerSize(pointerSize),
- IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm),
- ShowInst(showInst) {
+ InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend),
+ CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
+ ShowInst(showInst), UseLoc(useLoc) {
if (InstPrinter && IsVerboseAsm)
InstPrinter->setCommentStream(CommentStream);
}
~MCAsmStreamer() {}
- bool isLittleEndian() const { return IsLittleEndian; }
-
inline void EmitEOL() {
// If we don't have any comments, just emit a \n.
if (!IsVerboseAsm) {
virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
- virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace,
- bool UseSet = false);
+ virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
+ bool isPCRel, unsigned AddrSpace);
+ virtual void EmitIntValue(uint64_t Value, unsigned Size,
+ unsigned AddrSpace = 0);
virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
virtual bool EmitCFIDefCfaOffset(int64_t Offset);
virtual bool EmitCFIDefCfaRegister(int64_t Register);
virtual bool EmitCFIOffset(int64_t Register, int64_t Offset);
- virtual bool EmitCFIPersonality(const MCSymbol *Sym);
- virtual bool EmitCFILsda(const MCSymbol *Sym);
+ virtual bool EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding);
+ virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding);
virtual void EmitInstruction(const MCInst &Inst);
void MCAsmStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
const MCSymbol *LastLabel,
const MCSymbol *Label) {
- EmitDwarfSetLineAddr(LineDelta, Label, PointerSize);
+ EmitDwarfSetLineAddr(LineDelta, Label,
+ getContext().getTargetAsmInfo().getPointerSize());
}
void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
EmitEOL();
}
-void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size,
- unsigned AddrSpace, bool UseSet) {
+void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size,
+ unsigned AddrSpace) {
+ EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace);
+}
+
+void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
+ bool isPCRel, unsigned AddrSpace) {
assert(CurSection && "Cannot emit contents before setting section!");
+ assert(!isPCRel && "Cannot emit pc relative relocations!");
const char *Directive = 0;
switch (Size) {
default: break;
int64_t IntValue;
if (!Value->EvaluateAsAbsolute(IntValue))
report_fatal_error("Don't know how to emit this value.");
- if (isLittleEndian()) {
+ if (getContext().getTargetAsmInfo().isLittleEndian()) {
EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace);
EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace);
} else {
}
assert(Directive && "Invalid size for machine code value!");
- if (UseSet && MAI.hasSetDirective()) {
- MCSymbol *SetLabel = getContext().CreateTempSymbol();
- EmitAssignment(SetLabel, Value);
- OS << Directive << *SetLabel;
- EmitEOL();
- return;
- }
-
OS << Directive << *Value;
EmitEOL();
}
void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace) {
int64_t IntValue;
if (Value->EvaluateAsAbsolute(IntValue)) {
- SmallString<32> Tmp;
- raw_svector_ostream OSE(Tmp);
- MCObjectWriter::EncodeULEB128(IntValue, OSE);
- EmitBytes(OSE.str(), AddrSpace);
+ EmitULEB128IntValue(IntValue, AddrSpace);
return;
}
assert(MAI.hasLEB128() && "Cannot print a .uleb");
void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace) {
int64_t IntValue;
if (Value->EvaluateAsAbsolute(IntValue)) {
- SmallString<32> Tmp;
- raw_svector_ostream OSE(Tmp);
- MCObjectWriter::EncodeSLEB128(IntValue, OSE);
- EmitBytes(OSE.str(), AddrSpace);
+ EmitSLEB128IntValue(IntValue, AddrSpace);
return;
}
assert(MAI.hasLEB128() && "Cannot print a .sleb");
}
bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){
- if (!TLOF) {
+ if (UseLoc) {
OS << "\t.file\t" << FileNo << ' ';
PrintQuotedString(Filename, OS);
EmitEOL();
unsigned Discriminator) {
this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
Isa, Discriminator);
- if (TLOF)
+ if (!UseLoc)
return;
OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
if (this->MCStreamer::EmitCFIStartProc())
return true;
- OS << ".cfi_startproc";
+ OS << "\t.cfi_startproc";
EmitEOL();
return false;
if (this->MCStreamer::EmitCFIEndProc())
return true;
- OS << ".cfi_endproc";
+ OS << "\t.cfi_endproc";
EmitEOL();
return false;
if (this->MCStreamer::EmitCFIDefCfaOffset(Offset))
return true;
- OS << ".cfi_def_cfa_offset " << Offset;
+ OS << "\t.cfi_def_cfa_offset " << Offset;
EmitEOL();
return false;
if (this->MCStreamer::EmitCFIDefCfaRegister(Register))
return true;
- OS << ".cfi_def_cfa_register " << Register;
+ OS << "\t.cfi_def_cfa_register " << Register;
EmitEOL();
return false;
if (this->MCStreamer::EmitCFIOffset(Register, Offset))
return true;
- OS << ".cfi_offset " << Register << ", " << Offset;
+ OS << "\t.cfi_offset " << Register << ", " << Offset;
EmitEOL();
return false;
}
-bool MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym) {
- if (this->MCStreamer::EmitCFIPersonality(Sym))
+bool MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym,
+ unsigned Encoding) {
+ if (this->MCStreamer::EmitCFIPersonality(Sym, Encoding))
return true;
- OS << ".cfi_personality 0, " << *Sym;
+ OS << "\t.cfi_personality " << Encoding << ", " << *Sym;
EmitEOL();
return false;
}
-bool MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym) {
- if (this->MCStreamer::EmitCFILsda(Sym))
+bool MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
+ if (this->MCStreamer::EmitCFILsda(Sym, Encoding))
return true;
- OS << ".cfi_lsda 0, " << *Sym;
+ OS << "\t.cfi_lsda " << Encoding << ", " << *Sym;
EmitEOL();
return false;
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
MCFixup &F = Fixups[i];
- const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind());
+ const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind());
for (unsigned j = 0; j != Info.TargetSize; ++j) {
unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
}
}
+ // FIXME: Node the fixup comments for Thumb2 are completely bogus since the
+ // high order halfword of a 32-bit Thumb2 instruction is emitted first.
OS << "encoding: [";
for (unsigned i = 0, e = Code.size(); i != e; ++i) {
if (i)
if (MapEntry == 0) {
OS << format("0x%02x", uint8_t(Code[i]));
} else {
- assert(Code[i] == 0 && "Encoder wrote into fixed up bit!");
- OS << char('A' + MapEntry - 1);
+ if (Code[i]) {
+ // FIXME: Some of the 8 bits require fix up.
+ OS << format("0x%02x", uint8_t(Code[i])) << '\''
+ << char('A' + MapEntry - 1) << '\'';
+ } else
+ OS << char('A' + MapEntry - 1);
}
} else {
// Otherwise, write out in binary.
unsigned Bit = (Code[i] >> j) & 1;
unsigned FixupBit;
- if (IsLittleEndian)
+ if (getContext().getTargetAsmInfo().isLittleEndian())
FixupBit = i * 8 + j;
else
FixupBit = i * 8 + (7-j);
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
MCFixup &F = Fixups[i];
- const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind());
+ const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind());
OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
<< ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
}
void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
assert(CurSection && "Cannot emit contents before setting section!");
- if (TLOF)
+ if (!UseLoc)
MCLineEntry::Make(this, getCurrentSection());
// Show the encoding in a comment if we have a code emitter.
void MCAsmStreamer::Finish() {
// Dump out the dwarf file & directory tables and line tables.
- if (getContext().hasDwarfFiles() && TLOF)
- MCDwarfFileTable::Emit(this, TLOF->getDwarfLineSection(),
- TLOF->getTextSection());
+ if (getContext().hasDwarfFiles() && !UseLoc)
+ MCDwarfFileTable::Emit(this);
}
MCStreamer *llvm::createAsmStreamer(MCContext &Context,
formatted_raw_ostream &OS,
- bool isLittleEndian,
- bool isVerboseAsm, MCInstPrinter *IP,
- MCCodeEmitter *CE, bool ShowInst) {
- return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm,
- NULL, 0, IP, CE, ShowInst);
-}
-
-
-MCStreamer *llvm::createAsmStreamerNoLoc(MCContext &Context,
- formatted_raw_ostream &OS,
- bool isLittleEndian,
- bool isVerboseAsm,
- const TargetLoweringObjectFile *TLOF,
- int PointerSize,
- MCInstPrinter *IP,
- MCCodeEmitter *CE, bool ShowInst) {
- return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm,
- TLOF, PointerSize, IP, CE, ShowInst);
+ bool isVerboseAsm, bool useLoc,
+ MCInstPrinter *IP, MCCodeEmitter *CE,
+ TargetAsmBackend *TAB, bool ShowInst) {
+ return new MCAsmStreamer(Context, OS, isVerboseAsm, useLoc,
+ IP, CE, TAB, ShowInst);
}