13ca95b02SDimitry Andric //===-- AVRTargetMachine.cpp - Define TargetMachine for AVR ---------------===//
23ca95b02SDimitry Andric //
33ca95b02SDimitry Andric //                     The LLVM Compiler Infrastructure
43ca95b02SDimitry Andric //
53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source
63ca95b02SDimitry Andric // License. See LICENSE.TXT for details.
73ca95b02SDimitry Andric //
83ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
93ca95b02SDimitry Andric //
103ca95b02SDimitry Andric // This file defines the AVR specific subclass of TargetMachine.
113ca95b02SDimitry Andric //
123ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
133ca95b02SDimitry Andric 
143ca95b02SDimitry Andric #include "AVRTargetMachine.h"
153ca95b02SDimitry Andric 
163ca95b02SDimitry Andric #include "llvm/CodeGen/Passes.h"
173ca95b02SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
183ca95b02SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
19db17bf38SDimitry Andric #include "llvm/IR/Module.h"
203ca95b02SDimitry Andric #include "llvm/Support/TargetRegistry.h"
213ca95b02SDimitry Andric 
223ca95b02SDimitry Andric #include "AVR.h"
23db17bf38SDimitry Andric #include "AVRTargetObjectFile.h"
243ca95b02SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h"
253ca95b02SDimitry Andric 
263ca95b02SDimitry Andric namespace llvm {
273ca95b02SDimitry Andric 
284ba319b5SDimitry Andric static const char *AVRDataLayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8";
29d88c1a5aSDimitry Andric 
303ca95b02SDimitry Andric /// Processes a CPU name.
getCPU(StringRef CPU)313ca95b02SDimitry Andric static StringRef getCPU(StringRef CPU) {
323ca95b02SDimitry Andric   if (CPU.empty() || CPU == "generic") {
333ca95b02SDimitry Andric     return "avr2";
343ca95b02SDimitry Andric   }
353ca95b02SDimitry Andric 
363ca95b02SDimitry Andric   return CPU;
373ca95b02SDimitry Andric }
383ca95b02SDimitry Andric 
getEffectiveRelocModel(Optional<Reloc::Model> RM)393ca95b02SDimitry Andric static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
403ca95b02SDimitry Andric   return RM.hasValue() ? *RM : Reloc::Static;
413ca95b02SDimitry Andric }
423ca95b02SDimitry Andric 
AVRTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,Optional<Reloc::Model> RM,Optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)433ca95b02SDimitry Andric AVRTargetMachine::AVRTargetMachine(const Target &T, const Triple &TT,
443ca95b02SDimitry Andric                                    StringRef CPU, StringRef FS,
453ca95b02SDimitry Andric                                    const TargetOptions &Options,
462cab237bSDimitry Andric                                    Optional<Reloc::Model> RM,
472cab237bSDimitry Andric                                    Optional<CodeModel::Model> CM,
482cab237bSDimitry Andric                                    CodeGenOpt::Level OL, bool JIT)
492cab237bSDimitry Andric     : LLVMTargetMachine(T, AVRDataLayout, TT, getCPU(CPU), FS, Options,
50*b5893f02SDimitry Andric                         getEffectiveRelocModel(RM),
51*b5893f02SDimitry Andric                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
523ca95b02SDimitry Andric       SubTarget(TT, getCPU(CPU), FS, *this) {
533ca95b02SDimitry Andric   this->TLOF = make_unique<AVRTargetObjectFile>();
543ca95b02SDimitry Andric   initAsmInfo();
553ca95b02SDimitry Andric }
563ca95b02SDimitry Andric 
573ca95b02SDimitry Andric namespace {
583ca95b02SDimitry Andric /// AVR Code Generator Pass Configuration Options.
593ca95b02SDimitry Andric class AVRPassConfig : public TargetPassConfig {
603ca95b02SDimitry Andric public:
AVRPassConfig(AVRTargetMachine & TM,PassManagerBase & PM)61f9448bf3SDimitry Andric   AVRPassConfig(AVRTargetMachine &TM, PassManagerBase &PM)
623ca95b02SDimitry Andric       : TargetPassConfig(TM, PM) {}
633ca95b02SDimitry Andric 
getAVRTargetMachine() const643ca95b02SDimitry Andric   AVRTargetMachine &getAVRTargetMachine() const {
653ca95b02SDimitry Andric     return getTM<AVRTargetMachine>();
663ca95b02SDimitry Andric   }
673ca95b02SDimitry Andric 
683ca95b02SDimitry Andric   bool addInstSelector() override;
693ca95b02SDimitry Andric   void addPreSched2() override;
70c4394386SDimitry Andric   void addPreEmitPass() override;
713ca95b02SDimitry Andric   void addPreRegAlloc() override;
723ca95b02SDimitry Andric };
733ca95b02SDimitry Andric } // namespace
743ca95b02SDimitry Andric 
createPassConfig(PassManagerBase & PM)753ca95b02SDimitry Andric TargetPassConfig *AVRTargetMachine::createPassConfig(PassManagerBase &PM) {
76f9448bf3SDimitry Andric   return new AVRPassConfig(*this, PM);
773ca95b02SDimitry Andric }
787d523365SDimitry Andric 
LLVMInitializeAVRTarget()797d523365SDimitry Andric extern "C" void LLVMInitializeAVRTarget() {
803ca95b02SDimitry Andric   // Register the target.
81d88c1a5aSDimitry Andric   RegisterTargetMachine<AVRTargetMachine> X(getTheAVRTarget());
82d88c1a5aSDimitry Andric 
83d88c1a5aSDimitry Andric   auto &PR = *PassRegistry::getPassRegistry();
84d88c1a5aSDimitry Andric   initializeAVRExpandPseudoPass(PR);
85d88c1a5aSDimitry Andric   initializeAVRRelaxMemPass(PR);
867d523365SDimitry Andric }
873ca95b02SDimitry Andric 
getSubtargetImpl() const883ca95b02SDimitry Andric const AVRSubtarget *AVRTargetMachine::getSubtargetImpl() const {
893ca95b02SDimitry Andric   return &SubTarget;
903ca95b02SDimitry Andric }
913ca95b02SDimitry Andric 
getSubtargetImpl(const Function &) const923ca95b02SDimitry Andric const AVRSubtarget *AVRTargetMachine::getSubtargetImpl(const Function &) const {
933ca95b02SDimitry Andric   return &SubTarget;
943ca95b02SDimitry Andric }
953ca95b02SDimitry Andric 
963ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
973ca95b02SDimitry Andric // Pass Pipeline Configuration
983ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
993ca95b02SDimitry Andric 
addInstSelector()1003ca95b02SDimitry Andric bool AVRPassConfig::addInstSelector() {
101d88c1a5aSDimitry Andric   // Install an instruction selector.
102d88c1a5aSDimitry Andric   addPass(createAVRISelDag(getAVRTargetMachine(), getOptLevel()));
103d88c1a5aSDimitry Andric   // Create the frame analyzer pass used by the PEI pass.
104d88c1a5aSDimitry Andric   addPass(createAVRFrameAnalyzerPass());
105d88c1a5aSDimitry Andric 
1063ca95b02SDimitry Andric   return false;
1073ca95b02SDimitry Andric }
1083ca95b02SDimitry Andric 
addPreRegAlloc()1093ca95b02SDimitry Andric void AVRPassConfig::addPreRegAlloc() {
110d88c1a5aSDimitry Andric   // Create the dynalloc SP save/restore pass to handle variable sized allocas.
111d88c1a5aSDimitry Andric   addPass(createAVRDynAllocaSRPass());
1123ca95b02SDimitry Andric }
1133ca95b02SDimitry Andric 
addPreSched2()114d88c1a5aSDimitry Andric void AVRPassConfig::addPreSched2() {
115d88c1a5aSDimitry Andric   addPass(createAVRRelaxMemPass());
116d88c1a5aSDimitry Andric   addPass(createAVRExpandPseudoPass());
1173ca95b02SDimitry Andric }
1183ca95b02SDimitry Andric 
addPreEmitPass()119c4394386SDimitry Andric void AVRPassConfig::addPreEmitPass() {
120c4394386SDimitry Andric   // Must run branch selection immediately preceding the asm printer.
121c4394386SDimitry Andric   addPass(&BranchRelaxationPassID);
122c4394386SDimitry Andric }
123c4394386SDimitry Andric 
1243ca95b02SDimitry Andric } // end of namespace llvm
125