summaryrefslogtreecommitdiff
path: root/lib/CodeGen/MachOWriter.cpp
blob: cab71cea0d52d648203b788c552a576aa66d9693 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//===-- 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/Mangler.h"
#include "llvm/Support/raw_ostream.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) {
  Mang = new Mangler(M, MAI->getGlobalPrefix(), MAI->getPrivateGlobalPrefix(),
                     MAI->getLinkerPrivateGlobalPrefix());
  
  if (MAI->doesAllowQuotesInName())
    Mang->setUseQuotes(true);
  
  if (MAI->doesAllowNameToStartWithDigit())
    Mang->setSymbolsCanStartWithDigit(true);
  
  // 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) {
  // Release the name mangler object.
  delete Mang; Mang = 0;

  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;
}