summaryrefslogtreecommitdiffstats
path: root/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/CMakeLists.txt19
-rw-r--r--lib/MC/MCAsmInfo.cpp107
-rw-r--r--lib/MC/MCAsmInfoCOFF.cpp37
-rw-r--r--lib/MC/MCAsmInfoDarwin.cpp52
-rw-r--r--lib/MC/MCAsmLexer.cpp23
-rw-r--r--lib/MC/MCAsmParser.cpp18
-rw-r--r--lib/MC/MCAsmStreamer.cpp311
-rw-r--r--lib/MC/MCAssembler.cpp1190
-rw-r--r--lib/MC/MCCodeEmitter.cpp18
-rw-r--r--lib/MC/MCContext.cpp33
-rw-r--r--lib/MC/MCDisassembler.cpp14
-rw-r--r--lib/MC/MCExpr.cpp286
-rw-r--r--lib/MC/MCInst.cpp50
-rw-r--r--lib/MC/MCInstPrinter.cpp14
-rw-r--r--lib/MC/MCMachOStreamer.cpp379
-rw-r--r--lib/MC/MCNullStreamer.cpp70
-rw-r--r--lib/MC/MCSection.cpp45
-rw-r--r--lib/MC/MCSectionELF.cpp138
-rw-r--r--lib/MC/MCSectionMachO.cpp271
-rw-r--r--lib/MC/MCStreamer.cpp2
-rw-r--r--lib/MC/MCSymbol.cpp110
-rw-r--r--lib/MC/MCValue.cpp34
-rw-r--r--lib/MC/TargetAsmParser.cpp19
23 files changed, 3100 insertions, 140 deletions
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt
index 6307ffe..8a1a058 100644
--- a/lib/MC/CMakeLists.txt
+++ b/lib/MC/CMakeLists.txt
@@ -1,5 +1,24 @@
add_llvm_library(LLVMMC
+ MCAsmInfo.cpp
+ MCAsmInfoCOFF.cpp
+ MCAsmInfoDarwin.cpp
+ MCAsmLexer.cpp
+ MCAsmParser.cpp
MCAsmStreamer.cpp
+ MCAssembler.cpp
+ MCCodeEmitter.cpp
MCContext.cpp
+ MCDisassembler.cpp
+ MCExpr.cpp
+ MCInst.cpp
+ MCInstPrinter.cpp
+ MCMachOStreamer.cpp
+ MCNullStreamer.cpp
+ MCSection.cpp
+ MCSectionELF.cpp
+ MCSectionMachO.cpp
MCStreamer.cpp
+ MCSymbol.cpp
+ MCValue.cpp
+ TargetAsmParser.cpp
)
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
new file mode 100644
index 0000000..74fb930
--- /dev/null
+++ b/lib/MC/MCAsmInfo.cpp
@@ -0,0 +1,107 @@
+//===-- MCAsmInfo.cpp - Asm Info -------------------------------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines target asm properties related what form asm statements
+// should take.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/Support/DataTypes.h"
+#include <cctype>
+#include <cstring>
+using namespace llvm;
+
+MCAsmInfo::MCAsmInfo() {
+ ZeroFillDirective = 0;
+ NonexecutableStackDirective = 0;
+ NeedsSet = false;
+ MaxInstLength = 4;
+ PCSymbol = "$";
+ SeparatorChar = ';';
+ CommentColumn = 60;
+ CommentString = "#";
+ GlobalPrefix = "";
+ PrivateGlobalPrefix = ".";
+ LinkerPrivateGlobalPrefix = "";
+ InlineAsmStart = "APP";
+ InlineAsmEnd = "NO_APP";
+ AssemblerDialect = 0;
+ AllowQuotesInName = false;
+ AllowNameToStartWithDigit = false;
+ ZeroDirective = "\t.zero\t";
+ ZeroDirectiveSuffix = 0;
+ AsciiDirective = "\t.ascii\t";
+ AscizDirective = "\t.asciz\t";
+ Data8bitsDirective = "\t.byte\t";
+ Data16bitsDirective = "\t.short\t";
+ Data32bitsDirective = "\t.long\t";
+ Data64bitsDirective = "\t.quad\t";
+ SunStyleELFSectionSwitchSyntax = false;
+ UsesELFSectionDirectiveForBSS = false;
+ AlignDirective = "\t.align\t";
+ AlignmentIsInBytes = true;
+ TextAlignFillValue = 0;
+ JumpTableDirective = 0;
+ PICJumpTableDirective = 0;
+ GlobalDirective = "\t.globl\t";
+ SetDirective = 0;
+ LCOMMDirective = 0;
+ COMMDirective = "\t.comm\t";
+ COMMDirectiveTakesAlignment = true;
+ HasDotTypeDotSizeDirective = true;
+ HasSingleParameterDotFile = true;
+ UsedDirective = 0;
+ WeakRefDirective = 0;
+ WeakDefDirective = 0;
+ // FIXME: These are ELFish - move to ELFMAI.
+ HiddenDirective = "\t.hidden\t";
+ ProtectedDirective = "\t.protected\t";
+ AbsoluteDebugSectionOffsets = false;
+ AbsoluteEHSectionOffsets = false;
+ HasLEB128 = false;
+ HasDotLocAndDotFile = false;
+ SupportsDebugInformation = false;
+ ExceptionsType = ExceptionHandling::None;
+ DwarfRequiresFrameSection = true;
+ DwarfUsesInlineInfoSection = false;
+ Is_EHSymbolPrivate = true;
+ GlobalEHDirective = 0;
+ SupportsWeakOmittedEHFrame = true;
+ DwarfSectionOffsetDirective = 0;
+
+ AsmTransCBE = 0;
+}
+
+MCAsmInfo::~MCAsmInfo() {
+}
+
+
+unsigned MCAsmInfo::getULEB128Size(unsigned Value) {
+ unsigned Size = 0;
+ do {
+ Value >>= 7;
+ Size += sizeof(int8_t);
+ } while (Value);
+ return Size;
+}
+
+unsigned MCAsmInfo::getSLEB128Size(int Value) {
+ unsigned Size = 0;
+ int Sign = Value >> (8 * sizeof(Value) - 1);
+ bool IsMore;
+
+ do {
+ unsigned Byte = Value & 0x7f;
+ Value >>= 7;
+ IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
+ Size += sizeof(int8_t);
+ } while (IsMore);
+ return Size;
+}
diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp
new file mode 100644
index 0000000..23b0dd7
--- /dev/null
+++ b/lib/MC/MCAsmInfoCOFF.cpp
@@ -0,0 +1,37 @@
+//===-- MCAsmInfoCOFF.cpp - COFF asm properties -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines target asm properties related what form asm statements
+// should take in general on COFF-based targets
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmInfoCOFF.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace llvm;
+
+MCAsmInfoCOFF::MCAsmInfoCOFF() {
+ GlobalPrefix = "_";
+ LCOMMDirective = "\t.lcomm\t";
+ COMMDirectiveTakesAlignment = false;
+ HasDotTypeDotSizeDirective = false;
+ HasSingleParameterDotFile = false;
+ HiddenDirective = NULL;
+ PrivateGlobalPrefix = "L"; // Prefix for private global symbols
+ WeakRefDirective = "\t.weak\t";
+ SetDirective = "\t.set\t";
+
+ // Set up DWARF directives
+ HasLEB128 = true; // Target asm supports leb128 directives (little-endian)
+ AbsoluteDebugSectionOffsets = true;
+ AbsoluteEHSectionOffsets = false;
+ SupportsDebugInformation = true;
+ DwarfSectionOffsetDirective = "\t.secrel32\t";
+}
+
diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp
new file mode 100644
index 0000000..d99120d
--- /dev/null
+++ b/lib/MC/MCAsmInfoDarwin.cpp
@@ -0,0 +1,52 @@
+//===-- MCAsmInfoDarwin.cpp - Darwin asm properties -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines target asm properties related what form asm statements
+// should take in general on Darwin-based targets
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmInfoDarwin.h"
+using namespace llvm;
+
+MCAsmInfoDarwin::MCAsmInfoDarwin() {
+ // Common settings for all Darwin targets.
+ // Syntax:
+ GlobalPrefix = "_";
+ PrivateGlobalPrefix = "L";
+ LinkerPrivateGlobalPrefix = "l";
+ NeedsSet = true;
+ AllowQuotesInName = true;
+ HasSingleParameterDotFile = false;
+
+ AlignmentIsInBytes = false;
+ InlineAsmStart = " InlineAsm Start";
+ InlineAsmEnd = " InlineAsm End";
+
+ // Directives:
+ WeakDefDirective = "\t.weak_definition ";
+ WeakRefDirective = "\t.weak_reference ";
+ HiddenDirective = "\t.private_extern ";
+ LCOMMDirective = "\t.lcomm\t";
+ ZeroDirective = "\t.space\t"; // ".space N" emits N zeros.
+ ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill
+ SetDirective = "\t.set";
+ ProtectedDirective = "\t.globl\t";
+ HasDotTypeDotSizeDirective = false;
+ UsedDirective = "\t.no_dead_strip\t";
+
+ // _foo.eh symbols are currently always exported so that the linker knows
+ // about them. This is not necessary on 10.6 and later, but it
+ // doesn't hurt anything.
+ // FIXME: I need to get this from Triple.
+ Is_EHSymbolPrivate = false;
+ GlobalEHDirective = "\t.globl\t";
+ SupportsWeakOmittedEHFrame = false;
+}
+
diff --git a/lib/MC/MCAsmLexer.cpp b/lib/MC/MCAsmLexer.cpp
new file mode 100644
index 0000000..1e34ed6
--- /dev/null
+++ b/lib/MC/MCAsmLexer.cpp
@@ -0,0 +1,23 @@
+//===-- MCAsmLexer.cpp - Abstract Asm Lexer Interface ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmLexer.h"
+#include "llvm/Support/SourceMgr.h"
+
+using namespace llvm;
+
+MCAsmLexer::MCAsmLexer() : CurTok(AsmToken::Error, StringRef()) {
+}
+
+MCAsmLexer::~MCAsmLexer() {
+}
+
+SMLoc AsmToken::getLoc() const {
+ return SMLoc::getFromPointer(Str.data());
+}
diff --git a/lib/MC/MCAsmParser.cpp b/lib/MC/MCAsmParser.cpp
new file mode 100644
index 0000000..2287e89
--- /dev/null
+++ b/lib/MC/MCAsmParser.cpp
@@ -0,0 +1,18 @@
+//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmParser.h"
+
+using namespace llvm;
+
+MCAsmParser::MCAsmParser() {
+}
+
+MCAsmParser::~MCAsmParser() {
+}
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 7d94464..e56e968 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -8,118 +8,121 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCStreamer.h"
-
+#include "llvm/ADT/SmallString.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
- class MCAsmStreamer : public MCStreamer {
- raw_ostream &OS;
+class MCAsmStreamer : public MCStreamer {
+ raw_ostream &OS;
+ const MCAsmInfo &MAI;
+ MCInstPrinter *InstPrinter;
+ MCCodeEmitter *Emitter;
+public:
+ MCAsmStreamer(MCContext &Context, raw_ostream &_OS, const MCAsmInfo &tai,
+ MCInstPrinter *_Printer, MCCodeEmitter *_Emitter)
+ : MCStreamer(Context), OS(_OS), MAI(tai), InstPrinter(_Printer),
+ Emitter(_Emitter) {}
+ ~MCAsmStreamer() {}
- MCSection *CurSection;
+ /// @name MCStreamer Interface
+ /// @{
- public:
- MCAsmStreamer(MCContext &Context, raw_ostream &_OS)
- : MCStreamer(Context), OS(_OS), CurSection(0) {}
- ~MCAsmStreamer() {}
+ virtual void SwitchSection(const MCSection *Section);
- /// @name MCStreamer Interface
- /// @{
+ virtual void EmitLabel(MCSymbol *Symbol);
- virtual void SwitchSection(MCSection *Section);
+ virtual void EmitAssemblerFlag(AssemblerFlag Flag);
- virtual void EmitLabel(MCSymbol *Symbol);
+ virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
- virtual void EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
- bool MakeAbsolute = false);
+ virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute);
- virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute);
+ virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
- virtual void EmitBytes(const char *Data, unsigned Length);
+ virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ unsigned ByteAlignment);
- virtual void EmitValue(const MCValue &Value, unsigned Size);
+ virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
+ unsigned Size = 0, unsigned ByteAlignment = 0);
- virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
- unsigned ValueSize = 1,
- unsigned MaxBytesToEmit = 0);
+ virtual void EmitBytes(const StringRef &Data);
- virtual void EmitValueToOffset(const MCValue &Offset,
- unsigned char Value = 0);
-
- virtual void EmitInstruction(const MCInst &Inst);
+ virtual void EmitValue(const MCExpr *Value, unsigned Size);
- virtual void Finish();
-
- /// @}
- };
-
-}
-
-/// Allow printing values directly to a raw_ostream.
-static inline raw_ostream &operator<<(raw_ostream &os, const MCValue &Value) {
- if (Value.getSymA()) {
- os << Value.getSymA()->getName();
- if (Value.getSymB())
- os << " - " << Value.getSymB()->getName();
- if (Value.getConstant())
- os << " + " << Value.getConstant();
- } else {
- assert(!Value.getSymB() && "Invalid machine code value!");
- os << Value.getConstant();
- }
+ virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
+ unsigned ValueSize = 1,
+ unsigned MaxBytesToEmit = 0);
- return os;
-}
+ virtual void EmitValueToOffset(const MCExpr *Offset,
+ unsigned char Value = 0);
+
+ virtual void EmitInstruction(const MCInst &Inst);
+
+ virtual void Finish();
+
+ /// @}
+};
+
+} // end anonymous namespace.
static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
assert(Bytes && "Invalid size!");
return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
}
-static inline MCValue truncateToSize(const MCValue &Value, unsigned Bytes) {
- return MCValue::get(Value.getSymA(), Value.getSymB(),
- truncateToSize(Value.getConstant(), Bytes));
+static inline const MCExpr *truncateToSize(const MCExpr *Value,
+ unsigned Bytes) {
+ // FIXME: Do we really need this routine?
+ return Value;
}
-void MCAsmStreamer::SwitchSection(MCSection *Section) {
+void MCAsmStreamer::SwitchSection(const MCSection *Section) {
+ assert(Section && "Cannot switch to a null section!");
if (Section != CurSection) {
CurSection = Section;
-
- // FIXME: Really we would like the segment, flags, etc. to be separate
- // values instead of embedded in the name. Not all assemblers understand all
- // this stuff though.
- OS << ".section " << Section->getName() << "\n";
+ Section->PrintSwitchToSection(MAI, OS);
}
}
void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
- assert(Symbol->getSection() == 0 && "Cannot emit a symbol twice!");
+ assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
assert(CurSection && "Cannot emit before setting section!");
- assert(!getContext().GetSymbolValue(Symbol) &&
- "Cannot emit symbol which was directly assigned to!");
- OS << Symbol->getName() << ":\n";
- Symbol->setSection(CurSection);
- Symbol->setExternal(false);
+ Symbol->print(OS, &MAI);
+ OS << ":\n";
+ Symbol->setSection(*CurSection);
}
-void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
- bool MakeAbsolute) {
- assert(!Symbol->getSection() && "Cannot assign to a label!");
-
- if (MakeAbsolute) {
- OS << ".set " << Symbol->getName() << ", " << Value << '\n';
- } else {
- OS << Symbol->getName() << " = " << Value << '\n';
+void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
+ switch (Flag) {
+ default: assert(0 && "Invalid flag!");
+ case SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
}
+ OS << '\n';
+}
- getContext().SetSymbolValue(Symbol, Value);
+void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
+ // Only absolute symbols can be redefined.
+ assert((Symbol->isUndefined() || Symbol->isAbsolute()) &&
+ "Cannot define a symbol twice!");
+
+ Symbol->print(OS, &MAI);
+ OS << " = ";
+ Value->print(OS, &MAI);
+ OS << '\n';
}
void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
@@ -139,93 +142,165 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case WeakReference: OS << ".weak_reference"; break;
}
- OS << ' ' << Symbol->getName() << '\n';
+ OS << ' ';
+ Symbol->print(OS, &MAI);
+ OS << '\n';
+}
+
+void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
+ OS << ".desc" << ' ';
+ Symbol->print(OS, &MAI);
+ OS << ',' << DescValue << '\n';
+}
+
+void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ unsigned ByteAlignment) {
+ OS << ".comm ";
+ Symbol->print(OS, &MAI);
+ OS << ',' << Size;
+ if (ByteAlignment != 0)
+ OS << ',' << Log2_32(ByteAlignment);
+ OS << '\n';
}
-void MCAsmStreamer::EmitBytes(const char *Data, unsigned Length) {
+void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
+ unsigned Size, unsigned ByteAlignment) {
+ // Note: a .zerofill directive does not switch sections.
+ OS << ".zerofill ";
+
+ // This is a mach-o specific directive.
+ const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
+ OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
+
+ if (Symbol != NULL) {
+ OS << ',';
+ Symbol->print(OS, &MAI);
+ OS << ',' << Size;
+ if (ByteAlignment != 0)
+ OS << ',' << Log2_32(ByteAlignment);
+ }
+ OS << '\n';
+}
+
+void MCAsmStreamer::EmitBytes(const StringRef &Data) {
assert(CurSection && "Cannot emit contents before setting section!");
- for (unsigned i = 0; i != Length; ++i)
- OS << ".byte " << (unsigned) Data[i] << '\n';
+ for (unsigned i = 0, e = Data.size(); i != e; ++i)
+ OS << ".byte " << (unsigned) (unsigned char) Data[i] << '\n';
}
-void MCAsmStreamer::EmitValue(const MCValue &Value, unsigned Size) {
+void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size) {
assert(CurSection && "Cannot emit contents before setting section!");
// Need target hooks to know how to print this.
switch (Size) {
default:
- assert(0 && "Invalid size for machine code value!");
+ llvm_unreachable("Invalid size for machine code value!");
case 1: OS << ".byte"; break;
case 2: OS << ".short"; break;
case 4: OS << ".long"; break;
case 8: OS << ".quad"; break;
}
- OS << ' ' << truncateToSize(Value, Size) << '\n';
+ OS << ' ';
+ truncateToSize(Value, Size)->print(OS, &MAI);
+ OS << '\n';
}
void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {
- // Some assemblers don't support .balign, so we always emit as .p2align if
- // this is a power of two. Otherwise we assume the client knows the target
- // supports .balign and use that.
- unsigned Pow2 = Log2_32(ByteAlignment);
- bool IsPow2 = (1U << Pow2) == ByteAlignment;
-
+ // Some assemblers don't support non-power of two alignments, so we always
+ // emit alignments as a power of two if possible.
+ if (isPowerOf2_32(ByteAlignment)) {
+ switch (ValueSize) {
+ default: llvm_unreachable("Invalid size for machine code value!");
+ case 1: OS << MAI.getAlignDirective(); break;
+ // FIXME: use MAI for this!
+ case 2: OS << ".p2alignw "; break;
+ case 4: OS << ".p2alignl "; break;
+ case 8: llvm_unreachable("Unsupported alignment size!");
+ }
+
+ if (MAI.getAlignmentIsInBytes())
+ OS << ByteAlignment;
+ else
+ OS << Log2_32(ByteAlignment);
+
+ if (Value || MaxBytesToEmit) {
+ OS << ", 0x";
+ OS.write_hex(truncateToSize(Value, ValueSize));
+
+ if (MaxBytesToEmit)
+ OS << ", " << MaxBytesToEmit;
+ }
+ OS << '\n';
+ return;
+ }
+
+ // Non-power of two alignment. This is not widely supported by assemblers.
+ // FIXME: Parameterize this based on MAI.
switch (ValueSize) {
- default:
- assert(0 && "Invalid size for machine code value!");
- case 8:
- assert(0 && "Unsupported alignment size!");
- case 1: OS << (IsPow2 ? ".p2align" : ".balign"); break;
- case 2: OS << (IsPow2 ? ".p2alignw" : ".balignw"); break;
- case 4: OS << (IsPow2 ? ".p2alignl" : ".balignl"); break;
+ default: llvm_unreachable("Invalid size for machine code value!");
+ case 1: OS << ".balign"; break;
+ case 2: OS << ".balignw"; break;
+ case 4: OS << ".balignl"; break;
+ case 8: llvm_unreachable("Unsupported alignment size!");
}
- OS << ' ' << (IsPow2 ? Pow2 : ByteAlignment);
-
+ OS << ' ' << ByteAlignment;
OS << ", " << truncateToSize(Value, ValueSize);
if (MaxBytesToEmit)
OS << ", " << MaxBytesToEmit;
OS << '\n';
}
-void MCAsmStreamer::EmitValueToOffset(const MCValue &Offset,
+void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset,
unsigned char Value) {
// FIXME: Verify that Offset is associated with the current section.
- OS << ".org " << Offset << ", " << (unsigned) Value << '\n';
-}
-
-static raw_ostream &operator<<(raw_ostream &OS, const MCOperand &Op) {
- if (Op.isReg())
- return OS << "reg:" << Op.getReg();
- if (Op.isImm())
- return OS << "imm:" << Op.getImm();
- if (Op.isMBBLabel())
- return OS << "mbblabel:("
- << Op.getMBBLabelFunction() << ", " << Op.getMBBLabelBlock();
- assert(Op.isMCValue() && "Invalid operand!");
- return OS << "val:" << Op.getMCValue();
+ OS << ".org ";
+ Offset->print(OS, &MAI);
+ OS << ", " << (unsigned) Value << '\n';
}
void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
assert(CurSection && "Cannot emit contents before setting section!");
- // FIXME: Implement proper printing.
- OS << "MCInst("
- << "opcode=" << Inst.getOpcode() << ", "
- << "operands=[";
- for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
- if (i)
- OS << ", ";
- OS << Inst.getOperand(i);
+
+ // If we have an AsmPrinter, use that to print.
+ if (InstPrinter) {
+ InstPrinter->printInst(&Inst);
+ OS << '\n';
+
+ // Show the encoding if we have a code emitter.
+ if (Emitter) {
+ SmallString<256> Code;
+ raw_svector_ostream VecOS(Code);
+ Emitter->EncodeInstruction(Inst, VecOS);
+ VecOS.flush();
+
+ OS.indent(20);
+ OS << " # encoding: [";
+ for (unsigned i = 0, e = Code.size(); i != e; ++i) {
+ if (i)
+ OS << ',';
+ OS << format("%#04x", uint8_t(Code[i]));
+ }
+ OS << "]\n";
+ }
+
+ return;
}
- OS << "])\n";
+
+ // Otherwise fall back to a structural printing for now. Eventually we should
+ // always have access to the target specific printer.
+ Inst.print(OS, &MAI);
+ OS << '\n';
}
void MCAsmStreamer::Finish() {
OS.flush();
}
-MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS) {
- return new MCAsmStreamer(Context, OS);
+MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS,
+ const MCAsmInfo &MAI, MCInstPrinter *IP,
+ MCCodeEmitter *CE) {
+ return new MCAsmStreamer(Context, OS, MAI, IP, CE);
}
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
new file mode 100644
index 0000000..0afdf98
--- /dev/null
+++ b/lib/MC/MCAssembler.cpp
@@ -0,0 +1,1190 @@
+//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "assembler"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/Target/TargetMachOWriterInfo.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+using namespace llvm;
+
+class MachObjectWriter;
+
+STATISTIC(EmittedFragments, "Number of emitted assembler fragments");
+
+// FIXME FIXME FIXME: There are number of places in this file where we convert
+// what is a 64-bit assembler value used for computation into a value in the
+// object file, which may truncate it. We should detect that truncation where
+// invalid and report errors back.
+
+static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
+ MachObjectWriter &MOW);
+
+/// isVirtualSection - Check if this is a section which does not actually exist
+/// in the object file.
+static bool isVirtualSection(const MCSection &Section) {
+ // FIXME: Lame.
+ const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
+ unsigned Type = SMO.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
+ return (Type == MCSectionMachO::S_ZEROFILL);
+}
+
+class MachObjectWriter {
+ // See <mach-o/loader.h>.
+ enum {
+ Header_Magic32 = 0xFEEDFACE,
+ Header_Magic64 = 0xFEEDFACF
+ };
+
+ static const unsigned Header32Size = 28;
+ static const unsigned Header64Size = 32;
+ static const unsigned SegmentLoadCommand32Size = 56;
+ static const unsigned Section32Size = 68;
+ static const unsigned SymtabLoadCommandSize = 24;
+ static const unsigned DysymtabLoadCommandSize = 80;
+ static const unsigned Nlist32Size = 12;
+ static const unsigned RelocationInfoSize = 8;
+
+ enum HeaderFileType {
+ HFT_Object = 0x1
+ };
+
+ enum HeaderFlags {
+ HF_SubsectionsViaSymbols = 0x2000
+ };
+
+ enum LoadCommandType {
+ LCT_Segment = 0x1,
+ LCT_Symtab = 0x2,
+ LCT_Dysymtab = 0xb
+ };
+
+ // See <mach-o/nlist.h>.
+ enum SymbolTypeType {
+ STT_Undefined = 0x00,
+ STT_Absolute = 0x02,
+ STT_Section = 0x0e
+ };
+
+ enum SymbolTypeFlags {
+ // If any of these bits are set, then the entry is a stab entry number (see
+ // <mach-o/stab.h>. Otherwise the other masks apply.
+ STF_StabsEntryMask = 0xe0,
+
+ STF_TypeMask = 0x0e,
+ STF_External = 0x01,
+ STF_PrivateExtern = 0x10
+ };
+
+ /// IndirectSymbolFlags - Flags for encoding special values in the indirect
+ /// symbol entry.
+ enum IndirectSymbolFlags {
+ ISF_Local = 0x80000000,
+ ISF_Absolute = 0x40000000
+ };
+
+ /// RelocationFlags - Special flags for addresses.
+ enum RelocationFlags {
+ RF_Scattered = 0x80000000
+ };
+
+ enum RelocationInfoType {
+ RIT_Vanilla = 0,
+ RIT_Pair = 1,
+ RIT_Difference = 2,
+ RIT_PreboundLazyPointer = 3,
+ RIT_LocalDifference = 4
+ };
+
+ /// MachSymbolData - Helper struct for containing some precomputed information
+ /// on symbols.
+ struct MachSymbolData {
+ MCSymbolData *SymbolData;
+ uint64_t StringIndex;
+ uint8_t SectionIndex;
+
+ // Support lexicographic sorting.
+ bool operator<(const MachSymbolData &RHS) const {
+ const std::string &Name = SymbolData->getSymbol().getName();
+ return Name < RHS.SymbolData->getSymbol().getName();
+ }
+ };
+
+ raw_ostream &OS;
+ bool IsLSB;
+
+public:
+ MachObjectWriter(raw_ostream &_OS, bool _IsLSB = true)
+ : OS(_OS), IsLSB(_IsLSB) {
+ }
+
+ /// @name Helper Methods
+ /// @{
+
+ void Write8(uint8_t Value) {
+ OS << char(Value);
+ }
+
+ void Write16(uint16_t Value) {
+ if (IsLSB) {
+ Write8(uint8_t(Value >> 0));
+ Write8(uint8_t(Value >> 8));
+ } else {
+ Write8(uint8_t(Value >> 8));
+ Write8(uint8_t(Value >> 0));
+ }
+ }
+
+ void Write32(uint32_t Value) {
+ if (IsLSB) {
+ Write16(uint16_t(Value >> 0));
+ Write16(uint16_t(Value >> 16));
+ } else {
+ Write16(uint16_t(Value >> 16));
+ Write16(uint16_t(Value >> 0));
+ }
+ }
+
+ void Write64(uint64_t Value) {
+ if (IsLSB) {
+ Write32(uint32_t(Value >> 0));
+ Write32(uint32_t(Value >> 32));
+ } else {
+ Write32(uint32_t(Value >> 32));
+ Write32(uint32_t(Value >> 0));
+ }
+ }
+
+ void WriteZeros(unsigned N) {
+ const char Zeros[16] = { 0 };
+
+ for (unsigned i = 0, e = N / 16; i != e; ++i)
+ OS << StringRef(Zeros, 16);
+
+ OS << StringRef(Zeros, N % 16);
+ }
+
+ void WriteString(const StringRef &Str, unsigned ZeroFillSize = 0) {
+ OS << Str;
+ if (ZeroFillSize)
+ WriteZeros(ZeroFillSize - Str.size());
+ }
+
+ /// @}
+
+ void WriteHeader32(unsigned NumLoadCommands, unsigned LoadCommandsSize,
+ bool SubsectionsViaSymbols) {
+ uint32_t Flags = 0;
+
+ if (SubsectionsViaSymbols)
+ Flags |= HF_SubsectionsViaSymbols;
+
+ // struct mach_header (28 bytes)
+
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ Write32(Header_Magic32);
+
+ // FIXME: Support cputype.
+ Write32(TargetMachOWriterInfo::HDR_CPU_TYPE_I386);
+ // FIXME: Support cpusubtype.
+ Write32(TargetMachOWriterInfo::HDR_CPU_SUBTYPE_I386_ALL);
+ Write32(HFT_Object);
+ Write32(NumLoadCommands); // Object files have a single load command, the
+ // segment.
+ Write32(LoadCommandsSize);
+ Write32(Flags);
+
+ assert(OS.tell() - Start == Header32Size);
+ }
+
+ /// WriteSegmentLoadCommand32 - Write a 32-bit segment load command.
+ ///
+ /// \arg NumSections - The number of sections in this segment.
+ /// \arg SectionDataSize - The total size of the sections.
+ void WriteSegmentLoadCommand32(unsigned NumSections,
+ uint64_t VMSize,
+ uint64_t SectionDataStartOffset,
+ uint64_t SectionDataSize) {
+ // struct segment_command (56 bytes)
+
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ Write32(LCT_Segment);
+ Write32(SegmentLoadCommand32Size + NumSections * Section32Size);
+
+ WriteString("", 16);
+ Write32(0); // vmaddr
+ Write32(VMSize); // vmsize
+ Write32(SectionDataStartOffset); // file offset
+ Write32(SectionDataSize); // file size
+ Write32(0x7); // maxprot
+ Write32(0x7); // initprot
+ Write32(NumSections);
+ Write32(0); // flags
+
+ assert(OS.tell() - Start == SegmentLoadCommand32Size);
+ }
+
+ void WriteSection32(const MCSectionData &SD, uint64_t FileOffset,
+ uint64_t RelocationsStart, unsigned NumRelocations) {
+ // The offset is unused for virtual sections.
+ if (isVirtualSection(SD.getSection())) {
+ assert(SD.getFileSize() == 0 && "Invalid file size!");
+ FileOffset = 0;
+ }
+
+ // struct section (68 bytes)
+
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ // FIXME: cast<> support!
+ const MCSectionMachO &Section =
+ static_cast<const MCSectionMachO&>(SD.getSection());
+ WriteString(Section.getSectionName(), 16);
+ WriteString(Section.getSegmentName(), 16);
+ Write32(SD.getAddress()); // address
+ Write32(SD.getSize()); // size
+ Write32(FileOffset);
+
+ assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
+ Write32(Log2_32(SD.getAlignment()));
+ Write32(NumRelocations ? RelocationsStart : 0);
+ Write32(NumRelocations);
+ Write32(Section.getTypeAndAttributes());
+ Write32(0); // reserved1
+ Write32(Section.getStubSize()); // reserved2
+
+ assert(OS.tell() - Start == Section32Size);
+ }
+
+ void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
+ uint32_t StringTableOffset,
+ uint32_t StringTableSize) {
+ // struct symtab_command (24 bytes)
+
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ Write32(LCT_Symtab);
+ Write32(SymtabLoadCommandSize);
+ Write32(SymbolOffset);
+ Write32(NumSymbols);
+ Write32(StringTableOffset);
+ Write32(StringTableSize);
+
+ assert(OS.tell() - Start == SymtabLoadCommandSize);
+ }
+
+ void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
+ uint32_t NumLocalSymbols,
+ uint32_t FirstExternalSymbol,
+ uint32_t NumExternalSymbols,
+ uint32_t FirstUndefinedSymbol,
+ uint32_t NumUndefinedSymbols,
+ uint32_t IndirectSymbolOffset,
+ uint32_t NumIndirectSymbols) {
+ // struct dysymtab_command (80 bytes)
+
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ Write32(LCT_Dysymtab);
+ Write32(DysymtabLoadCommandSize);
+ Write32(FirstLocalSymbol);
+ Write32(NumLocalSymbols);
+ Write32(FirstExternalSymbol);
+ Write32(NumExternalSymbols);
+ Write32(FirstUndefinedSymbol);
+ Write32(NumUndefinedSymbols);
+ Write32(0); // tocoff
+ Write32(0); // ntoc
+ Write32(0); // modtaboff
+ Write32(0); // nmodtab
+ Write32(0); // extrefsymoff
+ Write32(0); // nextrefsyms
+ Write32(IndirectSymbolOffset);
+ Write32(NumIndirectSymbols);
+ Write32(0); // extreloff
+ Write32(0); // nextrel
+ Write32(0); // locreloff
+ Write32(0); // nlocrel
+
+ assert(OS.tell() - Start == DysymtabLoadCommandSize);
+ }
+
+ void WriteNlist32(MachSymbolData &MSD) {
+ MCSymbolData &Data = *MSD.SymbolData;
+ const MCSymbol &Symbol = Data.getSymbol();
+ uint8_t Type = 0;
+ uint16_t Flags = Data.getFlags();
+ uint32_t Address = 0;
+
+ // Set the N_TYPE bits. See <mach-o/nlist.h>.
+ //
+ // FIXME: Are the prebound or indirect fields possible here?
+ if (Symbol.isUndefined())
+ Type = STT_Undefined;
+ else if (Symbol.isAbsolute())
+ Type = STT_Absolute;
+ else
+ Type = STT_Section;
+
+ // FIXME: Set STAB bits.
+
+ if (Data.isPrivateExtern())
+ Type |= STF_PrivateExtern;
+
+ // Set external bit.
+ if (Data.isExternal() || Symbol.isUndefined())
+ Type |= STF_External;
+
+ // Compute the symbol address.
+ if (Symbol.isDefined()) {
+ if (Symbol.isAbsolute()) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+ } else {
+ Address = Data.getFragment()->getAddress() + Data.getOffset();
+ }
+ } else if (Data.isCommon()) {
+ // Common symbols are encoded with the size in the address
+ // field, and their alignment in the flags.
+ Address = Data.getCommonSize();
+
+ // Common alignment is packed into the 'desc' bits.
+ if (unsigned Align = Data.getCommonAlignment()) {
+ unsigned Log2Size = Log2_32(Align);
+ assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
+ if (Log2Size > 15)
+ llvm_report_error("invalid 'common' alignment '" +
+ Twine(Align) + "'");
+ // FIXME: Keep this mask with the SymbolFlags enumeration.
+ Flags = (Flags & 0xF0FF) | (Log2Size << 8);
+ }
+ }
+
+ // struct nlist (12 bytes)
+
+ Write32(MSD.StringIndex);
+ Write8(Type);
+ Write8(MSD.SectionIndex);
+
+ // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
+ // value.
+ Write16(Flags);
+ Write32(Address);
+ }
+
+ struct MachRelocationEntry {
+ uint32_t Word0;
+ uint32_t Word1;
+ };
+ void ComputeScatteredRelocationInfo(MCAssembler &Asm,
+ MCSectionData::Fixup &Fixup,
+ DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
+ std::vector<MachRelocationEntry> &Relocs) {
+ uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
+ unsigned IsPCRel = 0;
+ unsigned Type = RIT_Vanilla;
+
+ // See <reloc.h>.
+
+ const MCSymbol *A = Fixup.Value.getSymA();
+ MCSymbolData *SD = SymbolMap.lookup(A);
+ uint32_t Value = SD->getFragment()->getAddress() + SD->getOffset();
+ uint32_t Value2 = 0;
+
+ if (const MCSymbol *B = Fixup.Value.getSymB()) {
+ Type = RIT_LocalDifference;
+
+ MCSymbolData *SD = SymbolMap.lookup(B);
+ Value2 = SD->getFragment()->getAddress() + SD->getOffset();
+ }
+
+ unsigned Log2Size = Log2_32(Fixup.Size);
+ assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!");
+
+ // The value which goes in the fixup is current value of the expression.
+ Fixup.FixedValue = Value - Value2 + Fixup.Value.getConstant();
+
+ MachRelocationEntry MRE;
+ MRE.Word0 = ((Address << 0) |
+ (Type << 24) |
+ (Log2Size << 28) |
+ (IsPCRel << 30) |
+ RF_Scattered);
+ MRE.Word1 = Value;
+ Relocs.push_back(MRE);
+
+ if (Type == RIT_LocalDifference) {
+ Type = RIT_Pair;
+
+ MachRelocationEntry MRE;
+ MRE.Word0 = ((0 << 0) |
+ (Type << 24) |
+ (Log2Size << 28) |
+ (0 << 30) |
+ RF_Scattered);
+ MRE.Word1 = Value2;
+ Relocs.push_back(MRE);
+ }
+ }
+
+ void ComputeRelocationInfo(MCAssembler &Asm,
+ MCSectionData::Fixup &Fixup,
+ DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
+ std::vector<MachRelocationEntry> &Relocs) {
+ // If this is a local symbol plus an offset or a difference, then we need a
+ // scattered relocation entry.
+ if (Fixup.Value.getSymB()) // a - b
+ return ComputeScatteredRelocationInfo(Asm, Fixup, SymbolMap, Relocs);
+ if (Fixup.Value.getSymA() && Fixup.Value.getConstant())
+ if (!Fixup.Value.getSymA()->isUndefined())
+ return ComputeScatteredRelocationInfo(Asm, Fixup, SymbolMap, Relocs);
+
+ // See <reloc.h>.
+ uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
+ uint32_t Value = 0;
+ unsigned Index = 0;
+ unsigned IsPCRel = 0;
+ unsigned IsExtern = 0;
+ unsigned Type = 0;
+
+ if (Fixup.Value.isAbsolute()) { // constant
+ // SymbolNum of 0 indicates the absolute section.
+ Type = RIT_Vanilla;
+ Value = 0;
+ llvm_unreachable("FIXME: Not yet implemented!");
+ } else {
+ const MCSymbol *Symbol = Fixup.Value.getSymA();
+ MCSymbolData *SD = SymbolMap.lookup(Symbol);
+
+ if (Symbol->isUndefined()) {
+ IsExtern = 1;
+ Index = SD->getIndex();
+ Value = 0;
+ } else {
+ // The index is the section ordinal.
+ //
+ // FIXME: O(N)
+ Index = 1;
+ for (MCAssembler::iterator it = Asm.begin(),
+ ie = Asm.end(); it != ie; ++it, ++Index)
+ if (&*it == SD->getFragment()->getParent())
+ break;
+ Value = SD->getFragment()->getAddress() + SD->getOffset();
+ }
+
+ Type = RIT_Vanilla;
+ }
+
+ // The value which goes in the fixup is current value of the expression.
+ Fixup.FixedValue = Value + Fixup.Value.getConstant();
+
+ unsigned Log2Size = Log2_32(Fixup.Size);
+ assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!");
+
+ // struct relocation_info (8 bytes)
+ MachRelocationEntry MRE;
+ MRE.Word0 = Address;
+ MRE.Word1 = ((Index << 0) |
+ (IsPCRel << 24) |
+ (Log2Size << 25) |
+ (IsExtern << 27) |
+ (Type << 28));
+ Relocs.push_back(MRE);
+ }
+
+ void BindIndirectSymbols(MCAssembler &Asm,
+ DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap) {
+ // This is the point where 'as' creates actual symbols for indirect symbols
+ // (in the following two passes). It would be easier for us to do this
+ // sooner when we see the attribute, but that makes getting the order in the
+ // symbol table much more complicated than it is worth.
+ //
+ // FIXME: Revisit this when the dust settles.
+
+ // Bind non lazy symbol pointers first.
+ for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
+ ie = Asm.indirect_symbol_end(); it != ie; ++it) {
+ // FIXME: cast<> support!
+ const MCSectionMachO &Section =
+ static_cast<const MCSectionMachO&>(it->SectionData->getSection());
+
+ unsigned Type =
+ Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
+ if (Type != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS)
+ continue;
+
+ MCSymbolData *&Entry = SymbolMap[it->Symbol];
+ if (!Entry)
+ Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm);
+ }
+
+ // Then lazy symbol pointers and symbol stubs.
+ for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
+ ie = Asm.indirect_symbol_end(); it != ie; ++it) {
+ // FIXME: cast<> support!
+ const MCSectionMachO &Section =
+ static_cast<const MCSectionMachO&>(it->SectionData->getSection());
+
+ unsigned Type =
+ Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
+ if (Type != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
+ Type != MCSectionMachO::S_SYMBOL_STUBS)
+ continue;
+
+ MCSymbolData *&Entry = SymbolMap[it->Symbol];
+ if (!Entry) {
+ Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm);
+
+ // Set the symbol type to undefined lazy, but only on construction.
+ //
+ // FIXME: Do not hardcode.
+ Entry->setFlags(Entry->getFlags() | 0x0001);
+ }
+ }
+ }
+
+ /// ComputeSymbolTable - Compute the symbol table data
+ ///
+ /// \param StringTable [out] - The string table data.
+ /// \param StringIndexMap [out] - Map from symbol names to offsets in the
+ /// string table.
+ void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
+ std::vector<MachSymbolData> &LocalSymbolData,
+ std::vector<MachSymbolData> &ExternalSymbolData,
+ std::vector<MachSymbolData> &UndefinedSymbolData) {
+ // Build section lookup table.
+ DenseMap<const MCSection*, uint8_t> SectionIndexMap;
+ unsigned Index = 1;
+ for (MCAssembler::iterator it = Asm.begin(),
+ ie = Asm.end(); it != ie; ++it, ++Index)
+ SectionIndexMap[&it->getSection()] = Index;
+ assert(Index <= 256 && "Too many sections!");
+
+ // Index 0 is always the empty string.
+ StringMap<uint64_t> StringIndexMap;
+ StringTable += '\x00';
+
+ // Build the symbol arrays and the string table, but only for non-local
+ // symbols.
+ //
+ // The particular order that we collect the symbols and create the string
+ // table, then sort the symbols is chosen to match 'as'. Even though it
+ // doesn't matter for correctness, this is important for letting us diff .o
+ // files.
+ for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
+ ie = Asm.symbol_end(); it != ie; ++it) {
+ const MCSymbol &Symbol = it->getSymbol();
+
+ // Ignore assembler temporaries.
+ if (it->getSymbol().isTemporary())
+ continue;
+
+ if (!it->isExternal() && !Symbol.isUndefined())
+ continue;
+
+ uint64_t &Entry = StringIndexMap[Symbol.getName()];
+ if (!Entry) {
+ Entry = StringTable.size();
+ StringTable += Symbol.getName();
+ StringTable += '\x00';
+ }
+
+ MachSymbolData MSD;
+ MSD.SymbolData = it;
+ MSD.StringIndex = Entry;
+
+ if (Symbol.isUndefined()) {
+ MSD.SectionIndex = 0;
+ UndefinedSymbolData.push_back(MSD);
+ } else if (Symbol.isAbsolute()) {
+ MSD.SectionIndex = 0;
+ ExternalSymbolData.push_back(MSD);
+ } else {
+ MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
+ assert(MSD.SectionIndex && "Invalid section index!");
+ ExternalSymbolData.push_back(MSD);
+ }
+ }
+
+ // Now add the data for local symbols.
+ for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
+ ie = Asm.symbol_end(); it != ie; ++it) {
+ const MCSymbol &Symbol = it->getSymbol();
+
+ // Ignore assembler temporaries.
+ if (it->getSymbol().isTemporary())
+ continue;
+
+ if (it->isExternal() || Symbol.isUndefined())
+ continue;
+
+ uint64_t &Entry = StringIndexMap[Symbol.getName()];
+ if (!Entry) {
+ Entry = StringTable.size();
+ StringTable += Symbol.getName();
+ StringTable += '\x00';
+ }
+
+ MachSymbolData MSD;
+ MSD.SymbolData = it;
+ MSD.StringIndex = Entry;
+
+ if (Symbol.isAbsolute()) {
+ MSD.SectionIndex = 0;
+ LocalSymbolData.push_back(MSD);
+ } else {
+ MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
+ assert(MSD.SectionIndex && "Invalid section index!");
+ LocalSymbolData.push_back(MSD);
+ }
+ }
+
+ // External and undefined symbols are required to be in lexicographic order.
+ std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
+ std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
+
+ // Set the symbol indices.
+ Index = 0;
+ for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
+ LocalSymbolData[i].SymbolData->setIndex(Index++);
+ for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
+ ExternalSymbolData[i].SymbolData->setIndex(Index++);
+ for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
+ UndefinedSymbolData[i].SymbolData->setIndex(Index++);
+
+ // The string table is padded to a multiple of 4.
+ //
+ // FIXME: Check to see if this varies per arch.
+ while (StringTable.size() % 4)
+ StringTable += '\x00';
+ }
+
+ void WriteObject(MCAssembler &Asm) {
+ unsigned NumSections = Asm.size();
+
+ // Compute the symbol -> symbol data map.
+ //
+ // FIXME: This should not be here.
+ DenseMap<const MCSymbol*, MCSymbolData *> SymbolMap;
+ for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
+ ie = Asm.symbol_end(); it != ie; ++it)
+ SymbolMap[&it->getSymbol()] = it;
+
+ // Create symbol data for any indirect symbols.
+ BindIndirectSymbols(Asm, SymbolMap);
+
+ // Compute symbol table information.
+ SmallString<256> StringTable;
+ std::vector<MachSymbolData> LocalSymbolData;
+ std::vector<MachSymbolData> ExternalSymbolData;
+ std::vector<MachSymbolData> UndefinedSymbolData;
+ unsigned NumSymbols = Asm.symbol_size();
+
+ // No symbol table command is written if there are no symbols.
+ if (NumSymbols)
+ ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData,
+ UndefinedSymbolData);
+
+ // The section data starts after the header, the segment load command (and
+ // section headers) and the symbol table.
+ unsigned NumLoadCommands = 1;
+ uint64_t LoadCommandsSize =
+ SegmentLoadCommand32Size + NumSections * Section32Size;
+
+ // Add the symbol table load command sizes, if used.
+ if (NumSymbols) {
+ NumLoadCommands += 2;
+ LoadCommandsSize += SymtabLoadCommandSize + DysymtabLoadCommandSize;
+ }
+
+ // Compute the total size of the section data, as well as its file size and
+ // vm size.
+ uint64_t SectionDataStart = Header32Size + LoadCommandsSize;
+ uint64_t SectionDataSize = 0;
+ uint64_t SectionDataFileSize = 0;
+ uint64_t VMSize = 0;
+ for (MCAssembler::iterator it = Asm.begin(),
+ ie = Asm.end(); it != ie; ++it) {
+ MCSectionData &SD = *it;
+
+ VMSize = std::max(VMSize, SD.getAddress() + SD.getSize());
+
+ if (isVirtualSection(SD.getSection()))
+ continue;
+
+ SectionDataSize = std::max(SectionDataSize,
+ SD.getAddress() + SD.getSize());
+ SectionDataFileSize = std::max(SectionDataFileSize,
+ SD.getAddress() + SD.getFileSize());
+ }
+
+ // The section data is passed to 4 bytes.
+ //
+ // FIXME: Is this machine dependent?
+ unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
+ SectionDataFileSize += SectionDataPadding;
+
+ // Write the prolog, starting with the header and load command...
+ WriteHeader32(NumLoadCommands, LoadCommandsSize,
+ Asm.getSubsectionsViaSymbols());
+ WriteSegmentLoadCommand32(NumSections, VMSize,
+ SectionDataStart, SectionDataSize);
+
+ // ... and then the section headers.
+ //
+ // We also compute the section relocations while we do this. Note that
+ // compute relocation info will also update the fixup to have the correct
+ // value; this will be overwrite the appropriate data in the fragment when
+ // it is written.
+ std::vector<MachRelocationEntry> RelocInfos;
+ uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
+ for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie;
+ ++it) {
+ MCSectionData &SD = *it;
+
+ // The assembler writes relocations in the reverse order they were seen.
+ //
+ // FIXME: It is probably more complicated than this.
+ unsigned NumRelocsStart = RelocInfos.size();
+ for (unsigned i = 0, e = SD.fixup_size(); i != e; ++i)
+ ComputeRelocationInfo(Asm, SD.getFixups()[e - i - 1], SymbolMap,
+ RelocInfos);
+
+ unsigned NumRelocs = RelocInfos.size() - NumRelocsStart;
+ uint64_t SectionStart = SectionDataStart + SD.getAddress();
+ WriteSection32(SD, SectionStart, RelocTableEnd, NumRelocs);
+ RelocTableEnd += NumRelocs * RelocationInfoSize;
+ }
+
+ // Write the symbol table load command, if used.
+ if (NumSymbols) {
+ unsigned FirstLocalSymbol = 0;
+ unsigned NumLocalSymbols = LocalSymbolData.size();
+ unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
+ unsigned NumExternalSymbols = ExternalSymbolData.size();
+ unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
+ unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
+ unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
+ unsigned NumSymTabSymbols =
+ NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
+ uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
+ uint64_t IndirectSymbolOffset = 0;
+
+ // If used, the indirect symbols are written after the section data.
+ if (NumIndirectSymbols)
+ IndirectSymbolOffset = RelocTableEnd;
+
+ // The symbol table is written after the indirect symbol data.
+ uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
+
+ // The string table is written after symbol table.
+ uint64_t StringTableOffset =
+ SymbolTableOffset + NumSymTabSymbols * Nlist32Size;
+ WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
+ StringTableOffset, StringTable.size());
+
+ WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
+ FirstExternalSymbol, NumExternalSymbols,
+ FirstUndefinedSymbol, NumUndefinedSymbols,
+ IndirectSymbolOffset, NumIndirectSymbols);
+ }
+
+ // Write the actual section data.
+ for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
+ WriteFileData(OS, *it, *this);
+
+ // Write the extra padding.
+ WriteZeros(SectionDataPadding);
+
+ // Write the relocation entries.
+ for (unsigned i = 0, e = RelocInfos.size(); i != e; ++i) {
+ Write32(RelocInfos[i].Word0);
+ Write32(RelocInfos[i].Word1);
+ }
+
+ // Write the symbol table data, if used.
+ if (NumSymbols) {
+ // Write the indirect symbol entries.
+ for (MCAssembler::indirect_symbol_iterator
+ it = Asm.indirect_symbol_begin(),
+ ie = Asm.indirect_symbol_end(); it != ie; ++it) {
+ // Indirect symbols in the non lazy symbol pointer section have some
+ // special handling.
+ const MCSectionMachO &Section =
+ static_cast<const MCSectionMachO&>(it->SectionData->getSection());
+ unsigned Type =
+ Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
+ if (Type == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) {
+ // If this symbol is defined and internal, mark it as such.
+ if (it->Symbol->isDefined() &&
+ !SymbolMap.lookup(it->Symbol)->isExternal()) {
+ uint32_t Flags = ISF_Local;
+ if (it->Symbol->isAbsolute())
+ Flags |= ISF_Absolute;
+ Write32(Flags);
+ continue;
+ }
+ }
+
+ Write32(SymbolMap[it->Symbol]->getIndex());
+ }
+
+ // FIXME: Check that offsets match computed ones.
+
+ // Write the symbol table entries.
+ for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
+ WriteNlist32(LocalSymbolData[i]);
+ for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
+ WriteNlist32(ExternalSymbolData[i]);
+ for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
+ WriteNlist32(UndefinedSymbolData[i]);
+
+ // Write the string table.
+ OS << StringTable.str();
+ }
+ }
+};
+
+/* *** */
+
+MCFragment::MCFragment() : Kind(FragmentType(~0)) {
+}
+
+MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent)
+ : Kind(_Kind),
+ Parent(_Parent),
+ FileSize(~UINT64_C(0))
+{
+ if (Parent)
+ Parent->getFragmentList().push_back(this);
+}
+
+MCFragment::~MCFragment() {
+}
+
+uint64_t MCFragment::getAddress() const {
+ assert(getParent() && "Missing Section!");
+ return getParent()->getAddress() + Offset;
+}
+
+/* *** */
+
+MCSectionData::MCSectionData() : Section(0) {}
+
+MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
+ : Section(&_Section),
+ Alignment(1),
+ Address(~UINT64_C(0)),
+ Size(~UINT64_C(0)),
+ FileSize(~UINT64_C(0)),
+ LastFixupLookup(~0)
+{
+ if (A)
+ A->getSectionList().push_back(this);
+}
+
+const MCSectionData::Fixup *
+MCSectionData::LookupFixup(const MCFragment *Fragment, uint64_t Offset) const {
+ // Use a one level cache to turn the common case of accessing the fixups in
+ // order into O(1) instead of O(N).
+ unsigned i = LastFixupLookup, Count = Fixups.size(), End = Fixups.size();
+ if (i >= End)
+ i = 0;
+ while (Count--) {
+ const Fixup &F = Fixups[i];
+ if (F.Fragment == Fragment && F.Offset == Offset) {
+ LastFixupLookup = i;
+ return &F;
+ }
+
+ ++i;
+ if (i == End)
+ i = 0;
+ }
+
+ return 0;
+}
+
+/* *** */
+
+MCSymbolData::MCSymbolData() : Symbol(0) {}
+
+MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment,
+ uint64_t _Offset, MCAssembler *A)
+ : Symbol(&_Symbol), Fragment(_Fragment), Offset(_Offset),
+ IsExternal(false), IsPrivateExtern(false),
+ CommonSize(0), CommonAlign(0), Flags(0), Index(0)
+{
+ if (A)
+ A->getSymbolList().push_back(this);
+}
+
+/* *** */
+
+MCAssembler::MCAssembler(MCContext &_Context, raw_ostream &_OS)
+ : Context(_Context), OS(_OS), SubsectionsViaSymbols(false)
+{
+}
+
+MCAssembler::~MCAssembler() {
+}
+
+void MCAssembler::LayoutSection(MCSectionData &SD) {
+ uint64_t Address = SD.getAddress();
+
+ for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) {
+ MCFragment &F = *it;
+
+ F.setOffset(Address - SD.getAddress());
+
+ // Evaluate fragment size.
+ switch (F.getKind()) {
+ case MCFragment::FT_Align: {
+ MCAlignFragment &AF = cast<MCAlignFragment>(F);
+
+ uint64_t Size = OffsetToAlignment(Address, AF.getAlignment());
+ if (Size > AF.getMaxBytesToEmit())
+ AF.setFileSize(0);
+ else
+ AF.setFileSize(Size);
+ break;
+ }
+
+ case MCFragment::FT_Data:
+ F.setFileSize(F.getMaxFileSize());
+ break;
+
+ case MCFragment::FT_Fill: {
+ MCFillFragment &FF = cast<MCFillFragment>(F);
+
+ F.setFileSize(F.getMaxFileSize());
+
+ // If the fill value is constant, thats it.
+ if (FF.getValue().isAbsolute())
+ break;
+
+ // Otherwise, add fixups for the values.
+ for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
+ MCSectionData::Fixup Fix(F, i * FF.getValueSize(),
+ FF.getValue(),FF.getValueSize());
+ SD.getFixups().push_back(Fix);
+ }
+ break;
+ }
+
+ case MCFragment::FT_Org: {
+ MCOrgFragment &OF = cast<MCOrgFragment>(F);
+
+ if (!OF.getOffset().isAbsolute())
+ llvm_unreachable("FIXME: Not yet implemented!");
+ uint64_t OrgOffset = OF.getOffset().getConstant();
+ uint64_t Offset = Address - SD.getAddress();
+
+ // FIXME: We need a way to communicate this error.
+ if (OrgOffset < Offset)
+ llvm_report_error("invalid .org offset '" + Twine(OrgOffset) +
+ "' (at offset '" + Twine(Offset) + "'");
+
+ F.setFileSize(OrgOffset - Offset);
+ break;
+ }
+
+ case MCFragment::FT_ZeroFill: {
+ MCZeroFillFragment &ZFF = cast<MCZeroFillFragment>(F);
+
+ // Align the fragment offset; it is safe to adjust the offset freely since
+ // this is only in virtual sections.
+ uint64_t Aligned = RoundUpToAlignment(Address, ZFF.getAlignment());
+ F.setOffset(Aligned - SD.getAddress());
+
+ // FIXME: This is misnamed.
+ F.setFileSize(ZFF.getSize());
+ break;
+ }
+ }
+
+ Address += F.getFileSize();
+ }
+
+ // Set the section sizes.
+ SD.setSize(Address - SD.getAddress());
+ if (isVirtualSection(SD.getSection()))
+ SD.setFileSize(0);
+ else
+ SD.setFileSize(Address - SD.getAddress());
+}
+
+/// WriteFileData - Write the \arg F data to the output file.
+static void WriteFileData(raw_ostream &OS, const MCFragment &F,
+ MachObjectWriter &MOW) {
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ ++EmittedFragments;
+
+ // FIXME: Embed in fragments instead?
+ switch (F.getKind()) {
+ case MCFragment::FT_Align: {
+ MCAlignFragment &AF = cast<MCAlignFragment>(F);
+ uint64_t Count = AF.getFileSize() / AF.getValueSize();
+
+ // FIXME: This error shouldn't actually occur (the front end should emit
+ // multiple .align directives to enforce the semantics it wants), but is
+ // severe enough that we want to report it. How to handle this?
+ if (Count * AF.getValueSize() != AF.getFileSize())
+ llvm_report_error("undefined .align directive, value size '" +
+ Twine(AF.getValueSize()) +
+ "' is not a divisor of padding size '" +
+ Twine(AF.getFileSize()) + "'");
+
+ for (uint64_t i = 0; i != Count; ++i) {
+ switch (AF.getValueSize()) {
+ default:
+ assert(0 && "Invalid size!");
+ case 1: MOW.Write8 (uint8_t (AF.getValue())); break;
+ case 2: MOW.Write16(uint16_t(AF.getValue())); break;
+ case 4: MOW.Write32(uint32_t(AF.getValue())); break;
+ case 8: MOW.Write64(uint64_t(AF.getValue())); break;
+ }
+ }
+ break;
+ }
+
+ case MCFragment::FT_Data:
+ OS << cast<MCDataFragment>(F).getContents().str();
+ break;
+
+ case MCFragment::FT_Fill: {
+ MCFillFragment &FF = cast<MCFillFragment>(F);
+
+ int64_t Value = 0;
+ if (FF.getValue().isAbsolute())
+ Value = FF.getValue().getConstant();
+ for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
+ if (!FF.getValue().isAbsolute()) {
+ // Find the fixup.
+ //
+ // FIXME: Find a better way to write in the fixes.
+ const MCSectionData::Fixup *Fixup =
+ F.getParent()->LookupFixup(&F, i * FF.getValueSize());
+ assert(Fixup && "Missing fixup for fill value!");
+ Value = Fixup->FixedValue;
+ }
+
+ switch (FF.getValueSize()) {
+ default:
+ assert(0 && "Invalid size!");
+ case 1: MOW.Write8 (uint8_t (Value)); break;
+ case 2: MOW.Write16(uint16_t(Value)); break;
+ case 4: MOW.Write32(uint32_t(Value)); break;
+ case 8: MOW.Write64(uint64_t(Value)); break;
+ }
+ }
+ break;
+ }
+
+ case MCFragment::FT_Org: {
+ MCOrgFragment &OF = cast<MCOrgFragment>(F);
+
+ for (uint64_t i = 0, e = OF.getFileSize(); i != e; ++i)
+ MOW.Write8(uint8_t(OF.getValue()));
+
+ break;
+ }
+
+ case MCFragment::FT_ZeroFill: {
+ assert(0 && "Invalid zero fill fragment in concrete section!");
+ break;
+ }
+ }
+
+ assert(OS.tell() - Start == F.getFileSize());
+}
+
+/// WriteFileData - Write the \arg SD data to the output file.
+static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
+ MachObjectWriter &MOW) {
+ // Ignore virtual sections.
+ if (isVirtualSection(SD.getSection())) {
+ assert(SD.getFileSize() == 0);
+ return;
+ }
+
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ for (MCSectionData::const_iterator it = SD.begin(),
+ ie = SD.end(); it != ie; ++it)
+ WriteFileData(OS, *it, MOW);
+
+ // Add section padding.
+ assert(SD.getFileSize() >= SD.getSize() && "Invalid section sizes!");
+ MOW.WriteZeros(SD.getFileSize() - SD.getSize());
+
+ assert(OS.tell() - Start == SD.getFileSize());
+}
+
+void MCAssembler::Finish() {
+ // Layout the concrete sections and fragments.
+ uint64_t Address = 0;
+ MCSectionData *Prev = 0;
+ for (iterator it = begin(), ie = end(); it != ie; ++it) {
+ MCSectionData &SD = *it;
+
+ // Skip virtual sections.
+ if (isVirtualSection(SD.getSection()))
+ continue;
+
+ // Align this section if necessary by adding padding bytes to the previous
+ // section.
+ if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment())) {
+ assert(Prev && "Missing prev section!");
+ Prev->setFileSize(Prev->getFileSize() + Pad);
+ Address += Pad;
+ }
+
+ // Layout the section fragments and its size.
+ SD.setAddress(Address);
+ LayoutSection(SD);
+ Address += SD.getFileSize();
+
+ Prev = &SD;
+ }
+
+ // Layout the virtual sections.
+ for (iterator it = begin(), ie = end(); it != ie; ++it) {
+ MCSectionData &SD = *it;
+
+ if (!isVirtualSection(SD.getSection()))
+ continue;
+
+ SD.setAddress(Address);
+ LayoutSection(SD);
+ Address += SD.getSize();
+ }
+
+ // Write the object file.
+ MachObjectWriter MOW(OS);
+ MOW.WriteObject(*this);
+
+ OS.flush();
+}
diff --git a/lib/MC/MCCodeEmitter.cpp b/lib/MC/MCCodeEmitter.cpp
new file mode 100644
index 0000000..c122763
--- /dev/null
+++ b/lib/MC/MCCodeEmitter.cpp
@@ -0,0 +1,18 @@
+//===-- MCCodeEmitter.cpp - Instruction Encoding --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCCodeEmitter.h"
+
+using namespace llvm;
+
+MCCodeEmitter::MCCodeEmitter() {
+}
+
+MCCodeEmitter::~MCCodeEmitter() {
+}
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index 6c6019c..f36564a 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -14,23 +14,15 @@
#include "llvm/MC/MCValue.h"
using namespace llvm;
-MCContext::MCContext()
-{
+MCContext::MCContext() {
}
MCContext::~MCContext() {
+ // NOTE: The sections are all allocated out of a bump pointer allocator,
+ // we don't need to free them here.
}
-MCSection *MCContext::GetSection(const char *Name) {
- MCSection *&Entry = Sections[Name];
-
- if (!Entry)
- Entry = new (*this) MCSection(Name);
-
- return Entry;
-}
-
-MCSymbol *MCContext::CreateSymbol(const char *Name) {
+MCSymbol *MCContext::CreateSymbol(const StringRef &Name) {
assert(Name[0] != '\0' && "Normal symbols cannot be unnamed!");
// Create and bind the symbol, and ensure that names are unique.
@@ -39,17 +31,16 @@ MCSymbol *MCContext::CreateSymbol(const char *Name) {
return Entry = new (*this) MCSymbol(Name, false);
}
-MCSymbol *MCContext::GetOrCreateSymbol(const char *Name) {
+MCSymbol *MCContext::GetOrCreateSymbol(const StringRef &Name) {
MCSymbol *&Entry = Symbols[Name];
if (Entry) return Entry;
return Entry = new (*this) MCSymbol(Name, false);
}
-
-MCSymbol *MCContext::CreateTemporarySymbol(const char *Name) {
+MCSymbol *MCContext::CreateTemporarySymbol(const StringRef &Name) {
// If unnamed, just create a symbol.
- if (Name[0] == '\0')
+ if (Name.empty())
new (*this) MCSymbol("", true);
// Otherwise create as usual.
@@ -58,20 +49,20 @@ MCSymbol *MCContext::CreateTemporarySymbol(const char *Name) {
return Entry = new (*this) MCSymbol(Name, true);
}
-MCSymbol *MCContext::LookupSymbol(const char *Name) const {
+MCSymbol *MCContext::LookupSymbol(const StringRef &Name) const {
return Symbols.lookup(Name);
}
-void MCContext::ClearSymbolValue(MCSymbol *Sym) {
+void MCContext::ClearSymbolValue(const MCSymbol *Sym) {
SymbolValues.erase(Sym);
}
-void MCContext::SetSymbolValue(MCSymbol *Sym, const MCValue &Value) {
+void MCContext::SetSymbolValue(const MCSymbol *Sym, const MCValue &Value) {
SymbolValues[Sym] = Value;
}
-const MCValue *MCContext::GetSymbolValue(MCSymbol *Sym) const {
- DenseMap<MCSymbol*, MCValue>::iterator it = SymbolValues.find(Sym);
+const MCValue *MCContext::GetSymbolValue(const MCSymbol *Sym) const {
+ DenseMap<const MCSymbol*, MCValue>::iterator it = SymbolValues.find(Sym);
if (it == SymbolValues.end())
return 0;
diff --git a/lib/MC/MCDisassembler.cpp b/lib/MC/MCDisassembler.cpp
new file mode 100644
index 0000000..0809690
--- /dev/null
+++ b/lib/MC/MCDisassembler.cpp
@@ -0,0 +1,14 @@
+//===-- lib/MC/MCDisassembler.cpp - Disassembler interface ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCDisassembler.h"
+using namespace llvm;
+
+MCDisassembler::~MCDisassembler() {
+}
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
new file mode 100644
index 0000000..0f3e053
--- /dev/null
+++ b/lib/MC/MCExpr.cpp
@@ -0,0 +1,286 @@
+//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
+ switch (getKind()) {
+ case MCExpr::Constant:
+ OS << cast<MCConstantExpr>(*this).getValue();
+ return;
+
+ case MCExpr::SymbolRef: {
+ const MCSymbol &Sym = cast<MCSymbolRefExpr>(*this).getSymbol();
+
+ // Parenthesize names that start with $ so that they don't look like
+ // absolute names.
+ if (Sym.getName()[0] == '$') {
+ OS << '(';
+ Sym.print(OS, MAI);
+ OS << ')';
+ } else {
+ Sym.print(OS, MAI);
+ }
+ return;
+ }
+
+ case MCExpr::Unary: {
+ const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this);
+ switch (UE.getOpcode()) {
+ default: assert(0 && "Invalid opcode!");
+ case MCUnaryExpr::LNot: OS << '!'; break;
+ case MCUnaryExpr::Minus: OS << '-'; break;
+ case MCUnaryExpr::Not: OS << '~'; break;
+ case MCUnaryExpr::Plus: OS << '+'; break;
+ }
+ UE.getSubExpr()->print(OS, MAI);
+ return;
+ }
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);
+
+ // Only print parens around the LHS if it is non-trivial.
+ if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
+ BE.getLHS()->print(OS, MAI);
+ } else {
+ OS << '(';
+ BE.getLHS()->print(OS, MAI);
+ OS << ')';
+ }
+
+ switch (BE.getOpcode()) {
+ default: assert(0 && "Invalid opcode!");
+ case MCBinaryExpr::Add:
+ // Print "X-42" instead of "X+-42".
+ if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {
+ if (RHSC->getValue() < 0) {
+ OS << RHSC->getValue();
+ return;
+ }
+ }
+
+ OS << '+';
+ break;
+ case MCBinaryExpr::And: OS << '&'; break;
+ case MCBinaryExpr::Div: OS << '/'; break;
+ case MCBinaryExpr::EQ: OS << "=="; break;
+ case MCBinaryExpr::GT: OS << '>'; break;
+ case MCBinaryExpr::GTE: OS << ">="; break;
+ case MCBinaryExpr::LAnd: OS << "&&"; break;
+ case MCBinaryExpr::LOr: OS << "||"; break;
+ case MCBinaryExpr::LT: OS << '<'; break;
+ case MCBinaryExpr::LTE: OS << "<="; break;
+ case MCBinaryExpr::Mod: OS << '%'; break;
+ case MCBinaryExpr::Mul: OS << '*'; break;
+ case MCBinaryExpr::NE: OS << "!="; break;
+ case MCBinaryExpr::Or: OS << '|'; break;
+ case MCBinaryExpr::Shl: OS << "<<"; break;
+ case MCBinaryExpr::Shr: OS << ">>"; break;
+ case MCBinaryExpr::Sub: OS << '-'; break;
+ case MCBinaryExpr::Xor: OS << '^'; break;
+ }
+
+ // Only print parens around the LHS if it is non-trivial.
+ if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
+ BE.getRHS()->print(OS, MAI);
+ } else {
+ OS << '(';
+ BE.getRHS()->print(OS, MAI);
+ OS << ')';
+ }
+ return;
+ }
+ }
+
+ assert(0 && "Invalid expression kind!");
+}
+
+void MCExpr::dump() const {
+ print(errs(), 0);
+ errs() << '\n';
+}
+
+/* *** */
+
+const MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS,
+ const MCExpr *RHS, MCContext &Ctx) {
+ return new (Ctx) MCBinaryExpr(Opc, LHS, RHS);
+}
+
+const MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr,
+ MCContext &Ctx) {
+ return new (Ctx) MCUnaryExpr(Opc, Expr);
+}
+
+const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) {
+ return new (Ctx) MCConstantExpr(Value);
+}
+
+const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym,
+ MCContext &Ctx) {
+ return new (Ctx) MCSymbolRefExpr(Sym);
+}
+
+const MCSymbolRefExpr *MCSymbolRefExpr::Create(const StringRef &Name,
+ MCContext &Ctx) {
+ return Create(Ctx.GetOrCreateSymbol(Name), Ctx);
+}
+
+
+/* *** */
+
+bool MCExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
+ MCValue Value;
+
+ if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isAbsolute())
+ return false;
+
+ Res = Value.getConstant();
+ return true;
+}
+
+static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A,
+ const MCSymbol *RHS_B, int64_t RHS_Cst,
+ MCValue &Res) {
+ // We can't add or subtract two symbols.
+ if ((LHS.getSymA() && RHS_A) ||
+ (LHS.getSymB() && RHS_B))
+ return false;
+
+ const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
+ const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
+ if (B) {
+ // If we have a negated symbol, then we must have also have a non-negated
+ // symbol in order to encode the expression. We can do this check later to
+ // permit expressions which eventually fold to a representable form -- such
+ // as (a + (0 - b)) -- if necessary.
+ if (!A)
+ return false;
+ }
+ Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
+ return true;
+}
+
+bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
+ switch (getKind()) {
+ case Constant:
+ Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
+ return true;
+
+ case SymbolRef: {
+ const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol();
+ if (const MCValue *Value = Ctx.GetSymbolValue(&Sym))
+ Res = *Value;
+ else
+ Res = MCValue::get(&Sym, 0, 0);
+ return true;
+ }
+
+ case Unary: {
+ const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
+ MCValue Value;
+
+ if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
+ return false;
+
+ switch (AUE->getOpcode()) {
+ case MCUnaryExpr::LNot:
+ if (!Value.isAbsolute())
+ return false;
+ Res = MCValue::get(!Value.getConstant());
+ break;
+ case MCUnaryExpr::Minus:
+ /// -(a - b + const) ==> (b - a - const)
+ if (Value.getSymA() && !Value.getSymB())
+ return false;
+ Res = MCValue::get(Value.getSymB(), Value.getSymA(),
+ -Value.getConstant());
+ break;
+ case MCUnaryExpr::Not:
+ if (!Value.isAbsolute())
+ return false;
+ Res = MCValue::get(~Value.getConstant());
+ break;
+ case MCUnaryExpr::Plus:
+ Res = Value;
+ break;
+ }
+
+ return true;
+ }
+
+ case Binary: {
+ const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
+ MCValue LHSValue, RHSValue;
+
+ if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) ||
+ !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue))
+ return false;
+
+ // We only support a few operations on non-constant expressions, handle
+ // those first.
+ if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
+ switch (ABE->getOpcode()) {
+ default:
+ return false;
+ case MCBinaryExpr::Sub:
+ // Negate RHS and add.
+ return EvaluateSymbolicAdd(LHSValue,
+ RHSValue.getSymB(), RHSValue.getSymA(),
+ -RHSValue.getConstant(),
+ Res);
+
+ case MCBinaryExpr::Add:
+ return EvaluateSymbolicAdd(LHSValue,
+ RHSValue.getSymA(), RHSValue.getSymB(),
+ RHSValue.getConstant(),
+ Res);
+ }
+ }
+
+ // FIXME: We need target hooks for the evaluation. It may be limited in
+ // width, and gas defines the result of comparisons differently from Apple
+ // as (the result is sign extended).
+ int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
+ int64_t Result = 0;
+ switch (ABE->getOpcode()) {
+ case MCBinaryExpr::Add: Result = LHS + RHS; break;
+ case MCBinaryExpr::And: Result = LHS & RHS; break;
+ case MCBinaryExpr::Div: Result = LHS / RHS; break;
+ case MCBinaryExpr::EQ: Result = LHS == RHS; break;
+ case MCBinaryExpr::GT: Result = LHS > RHS; break;
+ case MCBinaryExpr::GTE: Result = LHS >= RHS; break;
+ case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
+ case MCBinaryExpr::LOr: Result = LHS || RHS; break;
+ case MCBinaryExpr::LT: Result = LHS < RHS; break;
+ case MCBinaryExpr::LTE: Result = LHS <= RHS; break;
+ case MCBinaryExpr::Mod: Result = LHS % RHS; break;
+ case MCBinaryExpr::Mul: Result = LHS * RHS; break;
+ case MCBinaryExpr::NE: Result = LHS != RHS; break;
+ case MCBinaryExpr::Or: Result = LHS | RHS; break;
+ case MCBinaryExpr::Shl: Result = LHS << RHS; break;
+ case MCBinaryExpr::Shr: Result = LHS >> RHS; break;
+ case MCBinaryExpr::Sub: Result = LHS - RHS; break;
+ case MCBinaryExpr::Xor: Result = LHS ^ RHS; break;
+ }
+
+ Res = MCValue::get(Result);
+ return true;
+ }
+ }
+
+ assert(0 && "Invalid assembly expression kind!");
+ return false;
+}
diff --git a/lib/MC/MCInst.cpp b/lib/MC/MCInst.cpp
new file mode 100644
index 0000000..d050318
--- /dev/null
+++ b/lib/MC/MCInst.cpp
@@ -0,0 +1,50 @@
+//===- lib/MC/MCInst.cpp - MCInst implementation --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void MCOperand::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
+ OS << "<MCOperand ";
+ if (!isValid())
+ OS << "INVALID";
+ else if (isReg())
+ OS << "Reg:" << getReg();
+ else if (isImm())
+ OS << "Imm:" << getImm();
+ else if (isExpr()) {
+ OS << "Expr:(";
+ getExpr()->print(OS, MAI);
+ OS << ")";
+ } else
+ OS << "UNDEFINED";
+ OS << ">";
+}
+
+void MCOperand::dump() const {
+ print(errs(), 0);
+ errs() << "\n";
+}
+
+void MCInst::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
+ OS << "<MCInst " << getOpcode();
+ for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
+ OS << " ";
+ getOperand(i).print(OS, MAI);
+ }
+ OS << ">";
+}
+
+void MCInst::dump() const {
+ print(errs(), 0);
+ errs() << "\n";
+}
diff --git a/lib/MC/MCInstPrinter.cpp b/lib/MC/MCInstPrinter.cpp
new file mode 100644
index 0000000..e90c03c
--- /dev/null
+++ b/lib/MC/MCInstPrinter.cpp
@@ -0,0 +1,14 @@
+//===-- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCInstPrinter.h"
+using namespace llvm;
+
+MCInstPrinter::~MCInstPrinter() {
+}
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
new file mode 100644
index 0000000..e04bd1f
--- /dev/null
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -0,0 +1,379 @@
+//===- lib/MC/MCMachOStreamer.cpp - Mach-O Object Output ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCStreamer.h"
+
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+
+class MCMachOStreamer : public MCStreamer {
+ /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest
+ /// 16 bits of the implementation defined flags.
+ enum SymbolFlags { // See <mach-o/nlist.h>.
+ SF_DescFlagsMask = 0xFFFF,
+
+ // Reference type flags.
+ SF_ReferenceTypeMask = 0x0007,
+ SF_ReferenceTypeUndefinedNonLazy = 0x0000,
+ SF_ReferenceTypeUndefinedLazy = 0x0001,
+ SF_ReferenceTypeDefined = 0x0002,
+ SF_ReferenceTypePrivateDefined = 0x0003,
+ SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004,
+ SF_ReferenceTypePrivateUndefinedLazy = 0x0005,
+
+ // Other 'desc' flags.
+ SF_NoDeadStrip = 0x0020,
+ SF_WeakReference = 0x0040,
+ SF_WeakDefinition = 0x0080
+ };
+
+private:
+ MCAssembler Assembler;
+
+ MCCodeEmitter *Emitter;
+
+ MCSectionData *CurSectionData;
+
+ DenseMap<const MCSection*, MCSectionData*> SectionMap;
+
+ DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap;
+
+private:
+ MCFragment *getCurrentFragment() const {
+ assert(CurSectionData && "No current section!");
+
+ if (!CurSectionData->empty())
+ return &CurSectionData->getFragmentList().back();
+
+ return 0;
+ }
+
+ MCSectionData &getSectionData(const MCSection &Section) {
+ MCSectionData *&Entry = SectionMap[&Section];
+
+ if (!Entry)
+ Entry = new MCSectionData(Section, &Assembler);
+
+ return *Entry;
+ }
+
+ MCSymbolData &getSymbolData(const MCSymbol &Symbol) {
+ MCSymbolData *&Entry = SymbolMap[&Symbol];
+
+ if (!Entry)
+ Entry = new MCSymbolData(Symbol, 0, 0, &Assembler);
+
+ return *Entry;
+ }
+
+public:
+ MCMachOStreamer(MCContext &Context, raw_ostream &_OS, MCCodeEmitter *_Emitter)
+ : MCStreamer(Context), Assembler(Context, _OS), Emitter(_Emitter),
+ CurSectionData(0) {}
+ ~MCMachOStreamer() {}
+
+ const MCExpr *AddValueSymbols(const MCExpr *Value) {
+ switch (Value->getKind()) {
+ case MCExpr::Constant:
+ break;
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
+ AddValueSymbols(BE->getLHS());
+ AddValueSymbols(BE->getRHS());
+ break;
+ }
+
+ case MCExpr::SymbolRef:
+ getSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
+ break;
+
+ case MCExpr::Unary:
+ AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr());
+ break;
+ }
+
+ return Value;
+ }
+
+ /// @name MCStreamer Interface
+ /// @{
+
+ virtual void SwitchSection(const MCSection *Section);
+
+ virtual void EmitLabel(MCSymbol *Symbol);
+
+ virtual void EmitAssemblerFlag(AssemblerFlag Flag);
+
+ virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
+
+ virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute);
+
+ virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
+
+ virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ unsigned ByteAlignment);
+
+ virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
+ unsigned Size = 0, unsigned ByteAlignment = 0);
+
+ virtual void EmitBytes(const StringRef &Data);
+
+ virtual void EmitValue(const MCExpr *Value, unsigned Size);
+
+ virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
+ unsigned ValueSize = 1,
+ unsigned MaxBytesToEmit = 0);
+
+ virtual void EmitValueToOffset(const MCExpr *Offset,
+ unsigned char Value = 0);
+
+ virtual void EmitInstruction(const MCInst &Inst);
+
+ virtual void Finish();
+
+ /// @}
+};
+
+} // end anonymous namespace.
+
+void MCMachOStreamer::SwitchSection(const MCSection *Section) {
+ assert(Section && "Cannot switch to a null section!");
+
+ // If already in this section, then this is a noop.
+ if (Section == CurSection) return;
+
+ CurSection = Section;
+ CurSectionData = &getSectionData(*Section);
+}
+
+void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
+ assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+
+ // FIXME: We should also use offsets into Fill fragments.
+ MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
+ if (!F)
+ F = new MCDataFragment(CurSectionData);
+
+ MCSymbolData &SD = getSymbolData(*Symbol);
+ assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
+ SD.setFragment(F);
+ SD.setOffset(F->getContents().size());
+
+ // This causes the reference type and weak reference flags to be cleared.
+ SD.setFlags(SD.getFlags() & ~(SF_WeakReference | SF_ReferenceTypeMask));
+
+ Symbol->setSection(*CurSection);
+}
+
+void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
+ switch (Flag) {
+ case SubsectionsViaSymbols:
+ Assembler.setSubsectionsViaSymbols(true);
+ return;
+ }
+
+ assert(0 && "invalid assembler flag!");
+}
+
+void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
+ // Only absolute symbols can be redefined.
+ assert((Symbol->isUndefined() || Symbol->isAbsolute()) &&
+ "Cannot define a symbol twice!");
+
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
+ SymbolAttr Attribute) {
+ // Indirect symbols are handled differently, to match how 'as' handles
+ // them. This makes writing matching .o files easier.
+ if (Attribute == MCStreamer::IndirectSymbol) {
+ // Note that we intentionally cannot use the symbol data here; this is
+ // important for matching the string table that 'as' generates.
+ IndirectSymbolData ISD;
+ ISD.Symbol = Symbol;
+ ISD.SectionData = CurSectionData;
+ Assembler.getIndirectSymbols().push_back(ISD);
+ return;
+ }
+
+ // Adding a symbol attribute always introduces the symbol, note that an
+ // important side effect of calling getSymbolData here is to register the
+ // symbol with the assembler.
+ MCSymbolData &SD = getSymbolData(*Symbol);
+
+ // The implementation of symbol attributes is designed to match 'as', but it
+ // leaves much to desired. It doesn't really make sense to arbitrarily add and
+ // remove flags, but 'as' allows this (in particular, see .desc).
+ //
+ // In the future it might be worth trying to make these operations more well
+ // defined.
+ switch (Attribute) {
+ case MCStreamer::IndirectSymbol:
+ case MCStreamer::Hidden:
+ case MCStreamer::Internal:
+ case MCStreamer::Protected:
+ case MCStreamer::Weak:
+ assert(0 && "Invalid symbol attribute for Mach-O!");
+ break;
+
+ case MCStreamer::Global:
+ SD.setExternal(true);
+ break;
+
+ case MCStreamer::LazyReference:
+ // FIXME: This requires -dynamic.
+ SD.setFlags(SD.getFlags() | SF_NoDeadStrip);
+ if (Symbol->isUndefined())
+ SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy);
+ break;
+
+ // Since .reference sets the no dead strip bit, it is equivalent to
+ // .no_dead_strip in practice.
+ case MCStreamer::Reference:
+ case MCStreamer::NoDeadStrip:
+ SD.setFlags(SD.getFlags() | SF_NoDeadStrip);
+ break;
+
+ case MCStreamer::PrivateExtern:
+ SD.setExternal(true);
+ SD.setPrivateExtern(true);
+ break;
+
+ case MCStreamer::WeakReference:
+ // FIXME: This requires -dynamic.
+ if (Symbol->isUndefined())
+ SD.setFlags(SD.getFlags() | SF_WeakReference);
+ break;
+
+ case MCStreamer::WeakDefinition:
+ // FIXME: 'as' enforces that this is defined and global. The manual claims
+ // it has to be in a coalesced section, but this isn't enforced.
+ SD.setFlags(SD.getFlags() | SF_WeakDefinition);
+ break;
+ }
+}
+
+void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
+ // Encode the 'desc' value into the lowest implementation defined bits.
+ assert(DescValue == (DescValue & SF_DescFlagsMask) &&
+ "Invalid .desc value!");
+ getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask);
+}
+
+void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ unsigned ByteAlignment) {
+ // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.
+ assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+
+ MCSymbolData &SD = getSymbolData(*Symbol);
+ SD.setExternal(true);
+ SD.setCommon(Size, ByteAlignment);
+}
+
+void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
+ unsigned Size, unsigned ByteAlignment) {
+ MCSectionData &SectData = getSectionData(*Section);
+
+ // The symbol may not be present, which only creates the section.
+ if (!Symbol)
+ return;
+
+ // FIXME: Assert that this section has the zerofill type.
+
+ assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+
+ MCSymbolData &SD = getSymbolData(*Symbol);
+
+ MCFragment *F = new MCZeroFillFragment(Size, ByteAlignment, &SectData);
+ SD.setFragment(F);
+
+ Symbol->setSection(*Section);
+
+ // Update the maximum alignment on the zero fill section if necessary.
+ if (ByteAlignment > SectData.getAlignment())
+ SectData.setAlignment(ByteAlignment);
+}
+
+void MCMachOStreamer::EmitBytes(const StringRef &Data) {
+ MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
+ if (!DF)
+ DF = new MCDataFragment(CurSectionData);
+ DF->getContents().append(Data.begin(), Data.end());
+}
+
+void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size) {
+ MCValue RelocValue;
+
+ if (!AddValueSymbols(Value)->EvaluateAsRelocatable(getContext(), RelocValue))
+ return llvm_report_error("expected relocatable expression");
+
+ new MCFillFragment(RelocValue, Size, 1, CurSectionData);
+}
+
+void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment,
+ int64_t Value, unsigned ValueSize,
+ unsigned MaxBytesToEmit) {
+ if (MaxBytesToEmit == 0)
+ MaxBytesToEmit = ByteAlignment;
+ new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit,
+ CurSectionData);
+
+ // Update the maximum alignment on the current section if necessary.
+ if (ByteAlignment > CurSectionData->getAlignment())
+ CurSectionData->setAlignment(ByteAlignment);
+}
+
+void MCMachOStreamer::EmitValueToOffset(const MCExpr *Offset,
+ unsigned char Value) {
+ MCValue RelocOffset;
+
+ if (!AddValueSymbols(Offset)->EvaluateAsRelocatable(getContext(),
+ RelocOffset))
+ return llvm_report_error("expected relocatable expression");
+
+ new MCOrgFragment(RelocOffset, Value, CurSectionData);
+}
+
+void MCMachOStreamer::EmitInstruction(const MCInst &Inst) {
+ // Scan for values.
+ for (unsigned i = 0; i != Inst.getNumOperands(); ++i)
+ if (Inst.getOperand(i).isExpr())
+ AddValueSymbols(Inst.getOperand(i).getExpr());
+
+ if (!Emitter)
+ llvm_unreachable("no code emitter available!");
+
+ // FIXME: Relocations!
+ SmallString<256> Code;
+ raw_svector_ostream VecOS(Code);
+ Emitter->EncodeInstruction(Inst, VecOS);
+ EmitBytes(VecOS.str());
+}
+
+void MCMachOStreamer::Finish() {
+ Assembler.Finish();
+}
+
+MCStreamer *llvm::createMachOStreamer(MCContext &Context, raw_ostream &OS,
+ MCCodeEmitter *CE) {
+ return new MCMachOStreamer(Context, OS, CE);
+}
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
new file mode 100644
index 0000000..3cd22ca
--- /dev/null
+++ b/lib/MC/MCNullStreamer.cpp
@@ -0,0 +1,70 @@
+//===- lib/MC/MCNullStreamer.cpp - Dummy Streamer Implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCStreamer.h"
+
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCSymbol.h"
+
+using namespace llvm;
+
+namespace {
+
+ class MCNullStreamer : public MCStreamer {
+ public:
+ MCNullStreamer(MCContext &Context) : MCStreamer(Context) {}
+
+ /// @name MCStreamer Interface
+ /// @{
+
+ virtual void SwitchSection(const MCSection *Section) {
+ CurSection = Section;
+ }
+
+ virtual void EmitLabel(MCSymbol *Symbol) {}
+
+ virtual void EmitAssemblerFlag(AssemblerFlag Flag) {}
+
+ virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
+
+ virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute) {}
+
+ virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
+
+ virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ unsigned ByteAlignment) {}
+
+ virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
+ unsigned Size = 0, unsigned ByteAlignment = 0) {}
+
+ virtual void EmitBytes(const StringRef &Data) {}
+
+ virtual void EmitValue(const MCExpr *Value, unsigned Size) {}
+
+ virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
+ unsigned ValueSize = 1,
+ unsigned MaxBytesToEmit = 0) {}
+
+ virtual void EmitValueToOffset(const MCExpr *Offset,
+ unsigned char Value = 0) {}
+
+ virtual void EmitInstruction(const MCInst &Inst) {}
+
+ virtual void Finish() {}
+
+ /// @}
+ };
+
+}
+
+MCStreamer *llvm::createNullStreamer(MCContext &Context) {
+ return new MCNullStreamer(Context);
+}
diff --git a/lib/MC/MCSection.cpp b/lib/MC/MCSection.cpp
new file mode 100644
index 0000000..333a471
--- /dev/null
+++ b/lib/MC/MCSection.cpp
@@ -0,0 +1,45 @@
+//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// MCSection
+//===----------------------------------------------------------------------===//
+
+MCSection::~MCSection() {
+}
+
+//===----------------------------------------------------------------------===//
+// MCSectionCOFF
+//===----------------------------------------------------------------------===//
+
+MCSectionCOFF *MCSectionCOFF::
+Create(const StringRef &Name, bool IsDirective, SectionKind K, MCContext &Ctx) {
+ return new (Ctx) MCSectionCOFF(Name, IsDirective, K);
+}
+
+void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI,
+ raw_ostream &OS) const {
+
+ if (isDirective()) {
+ OS << getName() << '\n';
+ return;
+ }
+ OS << "\t.section\t" << getName() << ",\"";
+ if (getKind().isText())
+ OS << 'x';
+ if (getKind().isWriteable())
+ OS << 'w';
+ OS << "\"\n";
+}
diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp
new file mode 100644
index 0000000..660a8c9
--- /dev/null
+++ b/lib/MC/MCSectionELF.cpp
@@ -0,0 +1,138 @@
+//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/MC/MCAsmInfo.h"
+
+using namespace llvm;
+
+MCSectionELF *MCSectionELF::
+Create(const StringRef &Section, unsigned Type, unsigned Flags,
+ SectionKind K, bool isExplicit, MCContext &Ctx) {
+ return new (Ctx) MCSectionELF(Section, Type, Flags, K, isExplicit);
+}
+
+// ShouldOmitSectionDirective - Decides whether a '.section' directive
+// should be printed before the section name
+bool MCSectionELF::ShouldOmitSectionDirective(const char *Name,
+ const MCAsmInfo &MAI) const {
+
+ // FIXME: Does .section .bss/.data/.text work everywhere??
+ if (strcmp(Name, ".text") == 0 ||
+ strcmp(Name, ".data") == 0 ||
+ (strcmp(Name, ".bss") == 0 &&
+ !MAI.usesELFSectionDirectiveForBSS()))
+ return true;
+
+ return false;
+}
+
+// ShouldPrintSectionType - Only prints the section type if supported
+bool MCSectionELF::ShouldPrintSectionType(unsigned Ty) const {
+
+ if (IsExplicit && !(Ty == SHT_NOBITS || Ty == SHT_PROGBITS))
+ return false;
+
+ return true;
+}
+
+void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
+ raw_ostream &OS) const {
+
+ if (ShouldOmitSectionDirective(SectionName.c_str(), MAI)) {
+ OS << '\t' << getSectionName() << '\n';
+ return;
+ }
+
+ OS << "\t.section\t" << getSectionName();
+
+ // Handle the weird solaris syntax if desired.
+ if (MAI.usesSunStyleELFSectionSwitchSyntax() &&
+ !(Flags & MCSectionELF::SHF_MERGE)) {
+ if (Flags & MCSectionELF::SHF_ALLOC)
+ OS << ",#alloc";
+ if (Flags & MCSectionELF::SHF_EXECINSTR)
+ OS << ",#execinstr";
+ if (Flags & MCSectionELF::SHF_WRITE)
+ OS << ",#write";
+ if (Flags & MCSectionELF::SHF_TLS)
+ OS << ",#tls";
+ } else {
+ OS << ",\"";
+ if (Flags & MCSectionELF::SHF_ALLOC)
+ OS << 'a';
+ if (Flags & MCSectionELF::SHF_EXECINSTR)
+ OS << 'x';
+ if (Flags & MCSectionELF::SHF_WRITE)
+ OS << 'w';
+ if (Flags & MCSectionELF::SHF_MERGE)
+ OS << 'M';
+ if (Flags & MCSectionELF::SHF_STRINGS)
+ OS << 'S';
+ if (Flags & MCSectionELF::SHF_TLS)
+ OS << 'T';
+
+ // If there are target-specific flags, print them.
+ if (Flags & ~MCSectionELF::TARGET_INDEP_SHF)
+ PrintTargetSpecificSectionFlags(MAI, OS);
+
+ OS << '"';
+
+ if (ShouldPrintSectionType(Type)) {
+ OS << ',';
+
+ // If comment string is '@', e.g. as on ARM - use '%' instead
+ if (MAI.getCommentString()[0] == '@')
+ OS << '%';
+ else
+ OS << '@';
+
+ if (Type == MCSectionELF::SHT_INIT_ARRAY)
+ OS << "init_array";
+ else if (Type == MCSectionELF::SHT_FINI_ARRAY)
+ OS << "fini_array";
+ else if (Type == MCSectionELF::SHT_PREINIT_ARRAY)
+ OS << "preinit_array";
+ else if (Type == MCSectionELF::SHT_NOBITS)
+ OS << "nobits";
+ else if (Type == MCSectionELF::SHT_PROGBITS)
+ OS << "progbits";
+
+ if (getKind().isMergeable1ByteCString()) {
+ OS << ",1";
+ } else if (getKind().isMergeable2ByteCString()) {
+ OS << ",2";
+ } else if (getKind().isMergeable4ByteCString() ||
+ getKind().isMergeableConst4()) {
+ OS << ",4";
+ } else if (getKind().isMergeableConst8()) {
+ OS << ",8";
+ } else if (getKind().isMergeableConst16()) {
+ OS << ",16";
+ }
+ }
+ }
+
+ OS << '\n';
+}
+
+// HasCommonSymbols - True if this section holds common symbols, this is
+// indicated on the ELF object file by a symbol with SHN_COMMON section
+// header index.
+bool MCSectionELF::HasCommonSymbols() const {
+
+ if (strncmp(SectionName.c_str(), ".gnu.linkonce.", 14) == 0)
+ return true;
+
+ return false;
+}
+
+
diff --git a/lib/MC/MCSectionMachO.cpp b/lib/MC/MCSectionMachO.cpp
new file mode 100644
index 0000000..b3aeb9c
--- /dev/null
+++ b/lib/MC/MCSectionMachO.cpp
@@ -0,0 +1,271 @@
+//===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+/// SectionTypeDescriptors - These are strings that describe the various section
+/// types. This *must* be kept in order with and stay synchronized with the
+/// section type list.
+static const struct {
+ const char *AssemblerName, *EnumName;
+} SectionTypeDescriptors[MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1] = {
+ { "regular", "S_REGULAR" }, // 0x00
+ { 0, "S_ZEROFILL" }, // 0x01
+ { "cstring_literals", "S_CSTRING_LITERALS" }, // 0x02
+ { "4byte_literals", "S_4BYTE_LITERALS" }, // 0x03
+ { "8byte_literals", "S_8BYTE_LITERALS" }, // 0x04
+ { "literal_pointers", "S_LITERAL_POINTERS" }, // 0x05
+ { "non_lazy_symbol_pointers", "S_NON_LAZY_SYMBOL_POINTERS" }, // 0x06
+ { "lazy_symbol_pointers", "S_LAZY_SYMBOL_POINTERS" }, // 0x07
+ { "symbol_stubs", "S_SYMBOL_STUBS" }, // 0x08
+ { "mod_init_funcs", "S_MOD_INIT_FUNC_POINTERS" }, // 0x09
+ { "mod_term_funcs", "S_MOD_TERM_FUNC_POINTERS" }, // 0x0A
+ { "coalesced", "S_COALESCED" }, // 0x0B
+ { 0, /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C
+ { "interposing", "S_INTERPOSING" }, // 0x0D
+ { "16byte_literals", "S_16BYTE_LITERALS" }, // 0x0E
+ { 0, /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F
+ { 0, /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" } // 0x10
+};
+
+
+/// SectionAttrDescriptors - This is an array of descriptors for section
+/// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed
+/// by attribute, instead it is searched. The last entry has an AttrFlagEnd
+/// AttrFlag value.
+static const struct {
+ unsigned AttrFlag;
+ const char *AssemblerName, *EnumName;
+} SectionAttrDescriptors[] = {
+#define ENTRY(ASMNAME, ENUM) \
+ { MCSectionMachO::ENUM, ASMNAME, #ENUM },
+ENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS)
+ENTRY("no_toc", S_ATTR_NO_TOC)
+ENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS)
+ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP)
+ENTRY("live_support", S_ATTR_LIVE_SUPPORT)
+ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE)
+ENTRY("debug", S_ATTR_DEBUG)
+ENTRY(0 /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS)
+ENTRY(0 /*FIXME*/, S_ATTR_EXT_RELOC)
+ENTRY(0 /*FIXME*/, S_ATTR_LOC_RELOC)
+#undef ENTRY
+ { 0, "none", 0 }, // used if section has no attributes but has a stub size
+#define AttrFlagEnd 0xffffffff // non legal value, multiple attribute bits set
+ { AttrFlagEnd, 0, 0 }
+};
+
+
+MCSectionMachO *MCSectionMachO::
+Create(const StringRef &Segment, const StringRef &Section,
+ unsigned TypeAndAttributes, unsigned Reserved2,
+ SectionKind K, MCContext &Ctx) {
+ // S_SYMBOL_STUBS must be set for Reserved2 to be non-zero.
+ return new (Ctx) MCSectionMachO(Segment, Section, TypeAndAttributes,
+ Reserved2, K);
+}
+
+void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
+ raw_ostream &OS) const {
+ OS << "\t.section\t" << getSegmentName() << ',' << getSectionName();
+
+ // Get the section type and attributes.
+ unsigned TAA = getTypeAndAttributes();
+ if (TAA == 0) {
+ OS << '\n';
+ return;
+ }
+
+ OS << ',';
+
+ unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE;
+ assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE &&
+ "Invalid SectionType specified!");
+
+ if (SectionTypeDescriptors[SectionType].AssemblerName)
+ OS << SectionTypeDescriptors[SectionType].AssemblerName;
+ else
+ OS << "<<" << SectionTypeDescriptors[SectionType].EnumName << ">>";
+
+ // If we don't have any attributes, we're done.
+ unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES;
+ if (SectionAttrs == 0) {
+ // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as
+ // the attribute specifier.
+ if (Reserved2 != 0)
+ OS << ",none," << Reserved2;
+ OS << '\n';
+ return;
+ }
+
+ // Check each attribute to see if we have it.
+ char Separator = ',';
+ for (unsigned i = 0; SectionAttrDescriptors[i].AttrFlag; ++i) {
+ // Check to see if we have this attribute.
+ if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)
+ continue;
+
+ // Yep, clear it and print it.
+ SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag;
+
+ OS << Separator;
+ if (SectionAttrDescriptors[i].AssemblerName)
+ OS << SectionAttrDescriptors[i].AssemblerName;
+ else
+ OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>";
+ Separator = '+';
+ }
+
+ assert(SectionAttrs == 0 && "Unknown section attributes!");
+
+ // If we have a S_SYMBOL_STUBS size specified, print it.
+ if (Reserved2 != 0)
+ OS << ',' << Reserved2;
+ OS << '\n';
+}
+
+/// StripSpaces - This removes leading and trailing spaces from the StringRef.
+static void StripSpaces(StringRef &Str) {
+ while (!Str.empty() && isspace(Str[0]))
+ Str = Str.substr(1);
+ while (!Str.empty() && isspace(Str.back()))
+ Str = Str.substr(0, Str.size()-1);
+}
+
+/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec".
+/// This is a string that can appear after a .section directive in a mach-o
+/// flavored .s file. If successful, this fills in the specified Out
+/// parameters and returns an empty string. When an invalid section
+/// specifier is present, this returns a string indicating the problem.
+std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
+ StringRef &Segment, // Out.
+ StringRef &Section, // Out.
+ unsigned &TAA, // Out.
+ unsigned &StubSize) { // Out.
+ // Find the first comma.
+ std::pair<StringRef, StringRef> Comma = Spec.split(',');
+
+ // If there is no comma, we fail.
+ if (Comma.second.empty())
+ return "mach-o section specifier requires a segment and section "
+ "separated by a comma";
+
+ // Capture segment, remove leading and trailing whitespace.
+ Segment = Comma.first;
+ StripSpaces(Segment);
+
+ // Verify that the segment is present and not too long.
+ if (Segment.empty() || Segment.size() > 16)
+ return "mach-o section specifier requires a segment whose length is "
+ "between 1 and 16 characters";
+
+ // Split the section name off from any attributes if present.
+ Comma = Comma.second.split(',');
+
+ // Capture section, remove leading and trailing whitespace.
+ Section = Comma.first;
+ StripSpaces(Section);
+
+ // Verify that the section is present and not too long.
+ if (Section.empty() || Section.size() > 16)
+ return "mach-o section specifier requires a section whose length is "
+ "between 1 and 16 characters";
+
+ // If there is no comma after the section, we're done.
+ TAA = 0;
+ StubSize = 0;
+ if (Comma.second.empty())
+ return "";
+
+ // Otherwise, we need to parse the section type and attributes.
+ Comma = Comma.second.split(',');
+
+ // Get the section type.
+ StringRef SectionType = Comma.first;
+ StripSpaces(SectionType);
+
+ // Figure out which section type it is.
+ unsigned TypeID;
+ for (TypeID = 0; TypeID !=MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1; ++TypeID)
+ if (SectionTypeDescriptors[TypeID].AssemblerName &&
+ SectionType == SectionTypeDescriptors[TypeID].AssemblerName)
+ break;
+
+ // If we didn't find the section type, reject it.
+ if (TypeID > MCSectionMachO::LAST_KNOWN_SECTION_TYPE)
+ return "mach-o section specifier uses an unknown section type";
+
+ // Remember the TypeID.
+ TAA = TypeID;
+
+ // If we have no comma after the section type, there are no attributes.
+ if (Comma.second.empty()) {
+ // S_SYMBOL_STUBS always require a symbol stub size specifier.
+ if (TAA == MCSectionMachO::S_SYMBOL_STUBS)
+ return "mach-o section specifier of type 'symbol_stubs' requires a size "
+ "specifier";
+ return "";
+ }
+
+ // Otherwise, we do have some attributes. Split off the size specifier if
+ // present.
+ Comma = Comma.second.split(',');
+ StringRef Attrs = Comma.first;
+
+ // The attribute list is a '+' separated list of attributes.
+ std::pair<StringRef, StringRef> Plus = Attrs.split('+');
+
+ while (1) {
+ StringRef Attr = Plus.first;
+ StripSpaces(Attr);
+
+ // Look up the attribute.
+ for (unsigned i = 0; ; ++i) {
+ if (SectionAttrDescriptors[i].AttrFlag == AttrFlagEnd)
+ return "mach-o section specifier has invalid attribute";
+
+ if (SectionAttrDescriptors[i].AssemblerName &&
+ Attr == SectionAttrDescriptors[i].AssemblerName) {
+ TAA |= SectionAttrDescriptors[i].AttrFlag;
+ break;
+ }
+ }
+
+ if (Plus.second.empty()) break;
+ Plus = Plus.second.split('+');
+ };
+
+ // Okay, we've parsed the section attributes, see if we have a stub size spec.
+ if (Comma.second.empty()) {
+ // S_SYMBOL_STUBS always require a symbol stub size specifier.
+ if (TAA == MCSectionMachO::S_SYMBOL_STUBS)
+ return "mach-o section specifier of type 'symbol_stubs' requires a size "
+ "specifier";
+ return "";
+ }
+
+ // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.
+ if ((TAA & MCSectionMachO::SECTION_TYPE) != MCSectionMachO::S_SYMBOL_STUBS)
+ return "mach-o section specifier cannot have a stub size specified because "
+ "it does not have type 'symbol_stubs'";
+
+ // Okay, if we do, it must be a number.
+ StringRef StubSizeStr = Comma.second;
+ StripSpaces(StubSizeStr);
+
+ // Convert the stub size from a string to an integer.
+ if (StubSizeStr.getAsInteger(0, StubSize))
+ return "mach-o section specifier has a malformed stub size";
+
+ return "";
+}
+
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index a634f33..8a6dcda 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -11,7 +11,7 @@
using namespace llvm;
-MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context) {
+MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context), CurSection(0) {
}
MCStreamer::~MCStreamer() {
diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp
new file mode 100644
index 0000000..86ff3f3
--- /dev/null
+++ b/lib/MC/MCSymbol.cpp
@@ -0,0 +1,110 @@
+//===- lib/MC/MCSymbol.cpp - MCSymbol implementation ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+// Sentinel value for the absolute pseudo section.
+const MCSection *MCSymbol::AbsolutePseudoSection =
+ reinterpret_cast<const MCSection *>(1);
+
+static bool isAcceptableChar(char C) {
+ if ((C < 'a' || C > 'z') &&
+ (C < 'A' || C > 'Z') &&
+ (C < '0' || C > '9') &&
+ C != '_' && C != '$' && C != '.' && C != '@')
+ return false;
+ return true;
+}
+
+static char HexDigit(int V) {
+ return V < 10 ? V+'0' : V+'A'-10;
+}
+
+static void MangleLetter(raw_ostream &OS, unsigned char C) {
+ OS << '_' << HexDigit(C >> 4) << HexDigit(C & 15) << '_';
+}
+
+/// NameNeedsEscaping - Return true if the identifier \arg Str needs quotes
+/// for this assembler.
+static bool NameNeedsEscaping(const StringRef &Str, const MCAsmInfo &MAI) {
+ assert(!Str.empty() && "Cannot create an empty MCSymbol");
+
+ // If the first character is a number and the target does not allow this, we
+ // need quotes.
+ if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9')
+ return true;
+
+ // If any of the characters in the string is an unacceptable character, force
+ // quotes.
+ for (unsigned i = 0, e = Str.size(); i != e; ++i)
+ if (!isAcceptableChar(Str[i]))
+ return true;
+ return false;
+}
+
+static void PrintMangledName(raw_ostream &OS, StringRef Str,
+ const MCAsmInfo &MAI) {
+ // The first character is not allowed to be a number unless the target
+ // explicitly allows it.
+ if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9') {
+ MangleLetter(OS, Str[0]);
+ Str = Str.substr(1);
+ }
+
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (!isAcceptableChar(Str[i]))
+ MangleLetter(OS, Str[i]);
+ else
+ OS << Str[i];
+ }
+}
+
+/// PrintMangledQuotedName - On systems that support quoted symbols, we still
+/// have to escape some (obscure) characters like " and \n which would break the
+/// assembler's lexing.
+static void PrintMangledQuotedName(raw_ostream &OS, StringRef Str) {
+ OS << '"';
+
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (Str[i] == '"')
+ OS << "_QQ_";
+ else if (Str[i] == '\n')
+ OS << "_NL_";
+ else
+ OS << Str[i];
+ }
+ OS << '"';
+}
+
+
+void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
+ if (MAI == 0 || !NameNeedsEscaping(getName(), *MAI)) {
+ OS << getName();
+ return;
+ }
+
+ // On systems that do not allow quoted names, print with mangling.
+ if (!MAI->doesAllowQuotesInName())
+ return PrintMangledName(OS, getName(), *MAI);
+
+ // If the string contains a double quote or newline, we still have to mangle
+ // it.
+ if (getName().find('"') != std::string::npos ||
+ getName().find('\n') != std::string::npos)
+ return PrintMangledQuotedName(OS, getName());
+
+ OS << '"' << getName() << '"';
+}
+
+void MCSymbol::dump() const {
+ print(errs(), 0);
+}
diff --git a/lib/MC/MCValue.cpp b/lib/MC/MCValue.cpp
new file mode 100644
index 0000000..69bd10c
--- /dev/null
+++ b/lib/MC/MCValue.cpp
@@ -0,0 +1,34 @@
+//===- lib/MC/MCValue.cpp - MCValue implementation ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void MCValue::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
+ if (isAbsolute()) {
+ OS << getConstant();
+ return;
+ }
+
+ getSymA()->print(OS, MAI);
+
+ if (getSymB()) {
+ OS << " - ";
+ getSymB()->print(OS, MAI);
+ }
+
+ if (getConstant())
+ OS << " + " << getConstant();
+}
+
+void MCValue::dump() const {
+ print(errs(), 0);
+}
diff --git a/lib/MC/TargetAsmParser.cpp b/lib/MC/TargetAsmParser.cpp
new file mode 100644
index 0000000..05760c9
--- /dev/null
+++ b/lib/MC/TargetAsmParser.cpp
@@ -0,0 +1,19 @@
+//===-- TargetAsmParser.cpp - Target Assembly Parser -----------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Target/TargetAsmParser.h"
+using namespace llvm;
+
+TargetAsmParser::TargetAsmParser(const Target &T)
+ : TheTarget(T)
+{
+}
+
+TargetAsmParser::~TargetAsmParser() {
+}
OpenPOWER on IntegriCloud