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