1193323Sed//===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// Implements the info about Mips target spec.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14234353Sdim#include "MipsTargetMachine.h"
15193323Sed#include "Mips.h"
16239462Sdim#include "MipsFrameLowering.h"
17239462Sdim#include "MipsInstrInfo.h"
18251662Sdim#include "MipsModuleISelDAGToDAG.h"
19251662Sdim#include "MipsOs16.h"
20251662Sdim#include "MipsSEFrameLowering.h"
21251662Sdim#include "MipsSEInstrInfo.h"
22251662Sdim#include "MipsSEISelLowering.h"
23251662Sdim#include "MipsSEISelDAGToDAG.h"
24251662Sdim#include "Mips16FrameLowering.h"
25263508Sdim#include "Mips16HardFloat.h"
26251662Sdim#include "Mips16InstrInfo.h"
27251662Sdim#include "Mips16ISelDAGToDAG.h"
28251662Sdim#include "Mips16ISelLowering.h"
29251662Sdim#include "llvm/Analysis/TargetTransformInfo.h"
30249423Sdim#include "llvm/CodeGen/Passes.h"
31193323Sed#include "llvm/PassManager.h"
32251662Sdim#include "llvm/Support/Debug.h"
33251662Sdim#include "llvm/Support/raw_ostream.h"
34226633Sdim#include "llvm/Support/TargetRegistry.h"
35263508Sdim#include "llvm/Transforms/Scalar.h"
36193323Sedusing namespace llvm;
37193323Sed
38251662Sdim
39251662Sdim
40198090Srdivackyextern "C" void LLVMInitializeMipsTarget() {
41198090Srdivacky  // Register the target.
42226633Sdim  RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget);
43198090Srdivacky  RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget);
44239462Sdim  RegisterTargetMachine<MipsebTargetMachine> A(TheMips64Target);
45239462Sdim  RegisterTargetMachine<MipselTargetMachine> B(TheMips64elTarget);
46193323Sed}
47193323Sed
48193323Sed// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment
49193323Sed// The stack is always 8 byte aligned
50193323Sed// On function prologue, the stack is created by decrementing
51193323Sed// its pointer. Once decremented, all references are done with positive
52218893Sdim// offset from the stack/frame pointer, using StackGrowsUp enables
53193323Sed// an easier handling.
54193323Sed// Using CodeModel::Large enables different CALL behavior.
55193323SedMipsTargetMachine::
56226633SdimMipsTargetMachine(const Target &T, StringRef TT,
57234353Sdim                  StringRef CPU, StringRef FS, const TargetOptions &Options,
58226633Sdim                  Reloc::Model RM, CodeModel::Model CM,
59234353Sdim                  CodeGenOpt::Level OL,
60234353Sdim                  bool isLittle)
61234353Sdim  : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
62251662Sdim    Subtarget(TT, CPU, FS, isLittle, RM, this),
63243830Sdim    DL(isLittle ?
64234353Sdim               (Subtarget.isABI_N64() ?
65249423Sdim                "e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-"
66249423Sdim                "n32:64-S128" :
67249423Sdim                "e-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32-S64") :
68234353Sdim               (Subtarget.isABI_N64() ?
69249423Sdim                "E-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-"
70249423Sdim                "n32:64-S128" :
71249423Sdim                "E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32-S64")),
72239462Sdim    InstrInfo(MipsInstrInfo::create(*this)),
73239462Sdim    FrameLowering(MipsFrameLowering::create(*this, Subtarget)),
74263508Sdim    TLInfo(MipsTargetLowering::create(*this)), TSInfo(*this),
75263508Sdim    InstrItins(Subtarget.getInstrItineraryData()), JITInfo() {
76263508Sdim  initAsmInfo();
77193323Sed}
78193323Sed
79251662Sdim
80251662Sdimvoid MipsTargetMachine::setHelperClassesMips16() {
81251662Sdim  InstrInfoSE.swap(InstrInfo);
82251662Sdim  FrameLoweringSE.swap(FrameLowering);
83251662Sdim  TLInfoSE.swap(TLInfo);
84251662Sdim  if (!InstrInfo16) {
85251662Sdim    InstrInfo.reset(MipsInstrInfo::create(*this));
86251662Sdim    FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget));
87251662Sdim    TLInfo.reset(MipsTargetLowering::create(*this));
88251662Sdim  } else {
89251662Sdim    InstrInfo16.swap(InstrInfo);
90251662Sdim    FrameLowering16.swap(FrameLowering);
91251662Sdim    TLInfo16.swap(TLInfo);
92251662Sdim  }
93251662Sdim  assert(TLInfo && "null target lowering 16");
94251662Sdim  assert(InstrInfo && "null instr info 16");
95251662Sdim  assert(FrameLowering && "null frame lowering 16");
96251662Sdim}
97251662Sdim
98251662Sdimvoid MipsTargetMachine::setHelperClassesMipsSE() {
99251662Sdim  InstrInfo16.swap(InstrInfo);
100251662Sdim  FrameLowering16.swap(FrameLowering);
101251662Sdim  TLInfo16.swap(TLInfo);
102251662Sdim  if (!InstrInfoSE) {
103251662Sdim    InstrInfo.reset(MipsInstrInfo::create(*this));
104251662Sdim    FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget));
105251662Sdim    TLInfo.reset(MipsTargetLowering::create(*this));
106251662Sdim  } else {
107251662Sdim    InstrInfoSE.swap(InstrInfo);
108251662Sdim    FrameLoweringSE.swap(FrameLowering);
109251662Sdim    TLInfoSE.swap(TLInfo);
110251662Sdim  }
111251662Sdim  assert(TLInfo && "null target lowering in SE");
112251662Sdim  assert(InstrInfo && "null instr info SE");
113251662Sdim  assert(FrameLowering && "null frame lowering SE");
114251662Sdim}
115234353Sdimvoid MipsebTargetMachine::anchor() { }
116234353Sdim
117226633SdimMipsebTargetMachine::
118226633SdimMipsebTargetMachine(const Target &T, StringRef TT,
119234353Sdim                    StringRef CPU, StringRef FS, const TargetOptions &Options,
120234353Sdim                    Reloc::Model RM, CodeModel::Model CM,
121234353Sdim                    CodeGenOpt::Level OL)
122234353Sdim  : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
123226633Sdim
124234353Sdimvoid MipselTargetMachine::anchor() { }
125234353Sdim
126193323SedMipselTargetMachine::
127226633SdimMipselTargetMachine(const Target &T, StringRef TT,
128234353Sdim                    StringRef CPU, StringRef FS, const TargetOptions &Options,
129234353Sdim                    Reloc::Model RM, CodeModel::Model CM,
130234353Sdim                    CodeGenOpt::Level OL)
131234353Sdim  : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
132193323Sed
133234353Sdimnamespace {
134234353Sdim/// Mips Code Generator Pass Configuration Options.
135234353Sdimclass MipsPassConfig : public TargetPassConfig {
136234353Sdimpublic:
137234353Sdim  MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM)
138263508Sdim    : TargetPassConfig(TM, PM) {
139263508Sdim    // The current implementation of long branch pass requires a scratch
140263508Sdim    // register ($at) to be available before branch instructions. Tail merging
141263508Sdim    // can break this requirement, so disable it when long branch pass is
142263508Sdim    // enabled.
143263508Sdim    EnableTailMerge = !getMipsSubtarget().enableLongBranchPass();
144263508Sdim  }
145234353Sdim
146234353Sdim  MipsTargetMachine &getMipsTargetMachine() const {
147234353Sdim    return getTM<MipsTargetMachine>();
148234353Sdim  }
149234353Sdim
150234353Sdim  const MipsSubtarget &getMipsSubtarget() const {
151234353Sdim    return *getMipsTargetMachine().getSubtargetImpl();
152234353Sdim  }
153234353Sdim
154251662Sdim  virtual void addIRPasses();
155234353Sdim  virtual bool addInstSelector();
156234353Sdim  virtual bool addPreEmitPass();
157234353Sdim};
158234353Sdim} // namespace
159234353Sdim
160234353SdimTargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
161234353Sdim  return new MipsPassConfig(this, PM);
162234353Sdim}
163234353Sdim
164251662Sdimvoid MipsPassConfig::addIRPasses() {
165251662Sdim  TargetPassConfig::addIRPasses();
166251662Sdim  if (getMipsSubtarget().os16())
167251662Sdim    addPass(createMipsOs16(getMipsTargetMachine()));
168263508Sdim  if (getMipsSubtarget().inMips16HardFloat())
169263508Sdim    addPass(createMips16HardFloat(getMipsTargetMachine()));
170263508Sdim  addPass(createPartiallyInlineLibCallsPass());
171251662Sdim}
172218893Sdim// Install an instruction selector pass using
173193323Sed// the ISelDag to gen Mips code.
174234982Sdimbool MipsPassConfig::addInstSelector() {
175251662Sdim  if (getMipsSubtarget().allowMixed16_32()) {
176251662Sdim    addPass(createMipsModuleISelDag(getMipsTargetMachine()));
177251662Sdim    addPass(createMips16ISelDag(getMipsTargetMachine()));
178251662Sdim    addPass(createMipsSEISelDag(getMipsTargetMachine()));
179251662Sdim  } else {
180251662Sdim    addPass(createMipsISelDag(getMipsTargetMachine()));
181251662Sdim  }
182193323Sed  return false;
183193323Sed}
184193323Sed
185251662Sdimvoid MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
186251662Sdim  if (Subtarget.allowMixed16_32()) {
187251662Sdim    DEBUG(errs() << "No ");
188251662Sdim    //FIXME: The Basic Target Transform Info
189251662Sdim    // pass needs to become a function pass instead of
190251662Sdim    // being an immutable pass and then this method as it exists now
191251662Sdim    // would be unnecessary.
192251662Sdim    PM.add(createNoTargetTransformInfoPass());
193251662Sdim  } else
194251662Sdim    LLVMTargetMachine::addAnalysisPasses(PM);
195251662Sdim  DEBUG(errs() << "Target Transform Info Pass Added\n");
196251662Sdim}
197251662Sdim
198218893Sdim// Implemented by targets that want to run passes immediately before
199218893Sdim// machine code is emitted. return true if -print-machineinstrs should
200193323Sed// print out the code after the passes.
201234982Sdimbool MipsPassConfig::addPreEmitPass() {
202239462Sdim  MipsTargetMachine &TM = getMipsTargetMachine();
203251662Sdim  const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>();
204239462Sdim  addPass(createMipsDelaySlotFillerPass(TM));
205221345Sdim
206263508Sdim  if (Subtarget.enableLongBranchPass())
207239462Sdim    addPass(createMipsLongBranchPass(TM));
208251662Sdim  if (Subtarget.inMips16Mode() ||
209251662Sdim      Subtarget.allowMixed16_32())
210249423Sdim    addPass(createMipsConstantIslandPass(TM));
211223017Sdim
212221345Sdim  return true;
213221345Sdim}
214226633Sdim
215226633Sdimbool MipsTargetMachine::addCodeEmitter(PassManagerBase &PM,
216234353Sdim                                       JITCodeEmitter &JCE) {
217226633Sdim  // Machine code emitter pass for Mips.
218226633Sdim  PM.add(createMipsJITCodeEmitterPass(*this, JCE));
219226633Sdim  return false;
220226633Sdim}
221