| //===-- MachOWriter.cpp - Target-independent Mach-O Writer code -----------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the target-independent Mach-O writer. This file writes |
| // out the Mach-O file in the following order: |
| // |
| // #1 FatHeader (universal-only) |
| // #2 FatArch (universal-only, 1 per universal arch) |
| // Per arch: |
| // #3 Header |
| // #4 Load Commands |
| // #5 Sections |
| // #6 Relocations |
| // #7 Symbols |
| // #8 Strings |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "MachOWriter.h" |
| #include "llvm/Function.h" |
| #include "llvm/CodeGen/FileWriters.h" |
| #include "llvm/CodeGen/MachineFunction.h" |
| #include "llvm/MC/MCAsmInfo.h" |
| #include "llvm/MC/MCContext.h" |
| #include "llvm/MC/MCCodeEmitter.h" |
| #include "llvm/MC/MCInst.h" |
| #include "llvm/MC/MCStreamer.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/FormattedStream.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include "llvm/Target/Mangler.h" |
| #include "llvm/Target/TargetData.h" |
| #include "llvm/Target/TargetLowering.h" |
| #include "llvm/Target/TargetLoweringObjectFile.h" |
| using namespace llvm; |
| |
| namespace llvm { |
| MachineFunctionPass *createMachOWriter(formatted_raw_ostream &O, |
| TargetMachine &TM, |
| const MCAsmInfo *T, |
| MCCodeEmitter *MCE) { |
| return new MachOWriter(O, TM, T, MCE); |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // MachOWriter Implementation |
| //===----------------------------------------------------------------------===// |
| |
| char MachOWriter::ID = 0; |
| |
| MachOWriter::MachOWriter(formatted_raw_ostream &o, TargetMachine &tm, |
| const MCAsmInfo *T, MCCodeEmitter *MCE) |
| : MachineFunctionPass(&ID), O(o), TM(tm), MAI(T), MCCE(MCE), |
| OutContext(*new MCContext()), |
| OutStreamer(*createMachOStreamer(OutContext, O, MCCE)) { |
| } |
| |
| MachOWriter::~MachOWriter() { |
| delete &OutStreamer; |
| delete &OutContext; |
| delete MCCE; |
| } |
| |
| bool MachOWriter::doInitialization(Module &M) { |
| // Initialize TargetLoweringObjectFile. |
| TM.getTargetLowering()->getObjFileLowering().Initialize(OutContext, TM); |
| |
| return false; |
| } |
| |
| /// doFinalization - Now that the module has been completely processed, emit |
| /// the Mach-O file to 'O'. |
| bool MachOWriter::doFinalization(Module &M) { |
| OutStreamer.Finish(); |
| return false; |
| } |
| |
| bool MachOWriter::runOnMachineFunction(MachineFunction &MF) { |
| const Function *F = MF.getFunction(); |
| TargetLoweringObjectFile &TLOF = TM.getTargetLowering()->getObjFileLowering(); |
| const MCSection *S = TLOF.SectionForGlobal(F, Mang, TM); |
| OutStreamer.SwitchSection(S); |
| |
| for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); |
| I != E; ++I) { |
| // Print a label for the basic block. |
| for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); |
| II != IE; ++II) { |
| const MachineInstr *MI = II; |
| MCInst OutMI; |
| OutMI.setOpcode(MI->getOpcode()); |
| |
| for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { |
| const MachineOperand &MO = MI->getOperand(i); |
| MCOperand MCOp; |
| |
| switch (MO.getType()) { |
| default: |
| MI->dump(); |
| llvm_unreachable("unknown operand type"); |
| case MachineOperand::MO_Register: |
| // Ignore all implicit register operands. |
| if (MO.isImplicit()) continue; |
| MCOp = MCOperand::CreateReg(MO.getReg()); |
| break; |
| case MachineOperand::MO_Immediate: |
| MCOp = MCOperand::CreateImm(MO.getImm()); |
| break; |
| } |
| OutMI.addOperand(MCOp); |
| } |
| |
| OutStreamer.EmitInstruction(OutMI); |
| } |
| } |
| |
| return false; |
| } |