16d8078f9SDylan McKay //===-- AVRTargetMachine.cpp - Define TargetMachine for AVR ---------------===//
26d8078f9SDylan McKay //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66d8078f9SDylan McKay //
76d8078f9SDylan McKay //===----------------------------------------------------------------------===//
86d8078f9SDylan McKay //
96d8078f9SDylan McKay // This file defines the AVR specific subclass of TargetMachine.
106d8078f9SDylan McKay //
116d8078f9SDylan McKay //===----------------------------------------------------------------------===//
126d8078f9SDylan McKay
136d8078f9SDylan McKay #include "AVRTargetMachine.h"
146d8078f9SDylan McKay
156d8078f9SDylan McKay #include "llvm/CodeGen/Passes.h"
1631d19d43SMatthias Braun #include "llvm/CodeGen/TargetPassConfig.h"
176d8078f9SDylan McKay #include "llvm/IR/LegacyPassManager.h"
186bda14b3SChandler Carruth #include "llvm/IR/Module.h"
1989b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
206d8078f9SDylan McKay
216d8078f9SDylan McKay #include "AVR.h"
226bda14b3SChandler Carruth #include "AVRTargetObjectFile.h"
236d8078f9SDylan McKay #include "MCTargetDesc/AVRMCTargetDesc.h"
24e982b420SRichard Trieu #include "TargetInfo/AVRTargetInfo.h"
256d8078f9SDylan McKay
266d8078f9SDylan McKay namespace llvm {
276d8078f9SDylan McKay
285449d2daSShivam Gupta static const char *AVRDataLayout =
295449d2daSShivam Gupta "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8";
30b967d16cSDylan McKay
316d8078f9SDylan McKay /// Processes a CPU name.
getCPU(StringRef CPU)32f1f1c010SDylan McKay static StringRef getCPU(StringRef CPU) {
336d8078f9SDylan McKay if (CPU.empty() || CPU == "generic") {
346d8078f9SDylan McKay return "avr2";
356d8078f9SDylan McKay }
366d8078f9SDylan McKay
376d8078f9SDylan McKay return CPU;
386d8078f9SDylan McKay }
396d8078f9SDylan McKay
getEffectiveRelocModel(Optional<Reloc::Model> RM)40be8e2e0fSDylan McKay static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
41*129b531cSKazu Hirata return RM.value_or(Reloc::Static);
42be8e2e0fSDylan McKay }
43be8e2e0fSDylan McKay
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)446d8078f9SDylan McKay AVRTargetMachine::AVRTargetMachine(const Target &T, const Triple &TT,
456d8078f9SDylan McKay StringRef CPU, StringRef FS,
466d8078f9SDylan McKay const TargetOptions &Options,
4705474478SDylan McKay Optional<Reloc::Model> RM,
4805474478SDylan McKay Optional<CodeModel::Model> CM,
4970ab7cc5SMeador Inge CodeGenOpt::Level OL, bool JIT)
50bb8507e6SMatthias Braun : LLVMTargetMachine(T, AVRDataLayout, TT, getCPU(CPU), FS, Options,
51ca29c271SDavid Green getEffectiveRelocModel(RM),
52ca29c271SDavid Green getEffectiveCodeModel(CM, CodeModel::Small), OL),
53ce70eb76SNico Weber SubTarget(TT, std::string(getCPU(CPU)), std::string(FS), *this) {
540eaee545SJonas Devlieghere this->TLOF = std::make_unique<AVRTargetObjectFile>();
556d8078f9SDylan McKay initAsmInfo();
566d8078f9SDylan McKay }
576d8078f9SDylan McKay
586d8078f9SDylan McKay namespace {
596d8078f9SDylan McKay /// AVR Code Generator Pass Configuration Options.
606d8078f9SDylan McKay class AVRPassConfig : public TargetPassConfig {
616d8078f9SDylan McKay public:
AVRPassConfig(AVRTargetMachine & TM,PassManagerBase & PM)625e394c3dSMatthias Braun AVRPassConfig(AVRTargetMachine &TM, PassManagerBase &PM)
636d8078f9SDylan McKay : TargetPassConfig(TM, PM) {}
646d8078f9SDylan McKay
getAVRTargetMachine() const656d8078f9SDylan McKay AVRTargetMachine &getAVRTargetMachine() const {
666d8078f9SDylan McKay return getTM<AVRTargetMachine>();
676d8078f9SDylan McKay }
686d8078f9SDylan McKay
696aa9e746SAyke van Laethem void addIRPasses() override;
706d8078f9SDylan McKay bool addInstSelector() override;
716d8078f9SDylan McKay void addPreSched2() override;
729cf1dc1eSDylan McKay void addPreEmitPass() override;
736d8078f9SDylan McKay };
746d8078f9SDylan McKay } // namespace
756d8078f9SDylan McKay
createPassConfig(PassManagerBase & PM)766d8078f9SDylan McKay TargetPassConfig *AVRTargetMachine::createPassConfig(PassManagerBase &PM) {
775e394c3dSMatthias Braun return new AVRPassConfig(*this, PM);
786d8078f9SDylan McKay }
79c498ba3aSDylan McKay
addIRPasses()806aa9e746SAyke van Laethem void AVRPassConfig::addIRPasses() {
816aa9e746SAyke van Laethem // Expand instructions like
826aa9e746SAyke van Laethem // %result = shl i32 %n, %amount
836aa9e746SAyke van Laethem // to a loop so that library calls are avoided.
846aa9e746SAyke van Laethem addPass(createAVRShiftExpandPass());
856aa9e746SAyke van Laethem
866aa9e746SAyke van Laethem TargetPassConfig::addIRPasses();
876aa9e746SAyke van Laethem }
886aa9e746SAyke van Laethem
LLVMInitializeAVRTarget()890dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRTarget() {
906d8078f9SDylan McKay // Register the target.
91f42454b9SMehdi Amini RegisterTargetMachine<AVRTargetMachine> X(getTheAVRTarget());
928cec7eb6SDylan McKay
938cec7eb6SDylan McKay auto &PR = *PassRegistry::getPassRegistry();
948cec7eb6SDylan McKay initializeAVRExpandPseudoPass(PR);
956aa9e746SAyke van Laethem initializeAVRShiftExpandPass(PR);
96c498ba3aSDylan McKay }
976d8078f9SDylan McKay
getSubtargetImpl() const986d8078f9SDylan McKay const AVRSubtarget *AVRTargetMachine::getSubtargetImpl() const {
996d8078f9SDylan McKay return &SubTarget;
1006d8078f9SDylan McKay }
1016d8078f9SDylan McKay
getSubtargetImpl(const Function &) const1026d8078f9SDylan McKay const AVRSubtarget *AVRTargetMachine::getSubtargetImpl(const Function &) const {
1036d8078f9SDylan McKay return &SubTarget;
1046d8078f9SDylan McKay }
1056d8078f9SDylan McKay
1066d8078f9SDylan McKay //===----------------------------------------------------------------------===//
1076d8078f9SDylan McKay // Pass Pipeline Configuration
1086d8078f9SDylan McKay //===----------------------------------------------------------------------===//
1096d8078f9SDylan McKay
addInstSelector()1106d8078f9SDylan McKay bool AVRPassConfig::addInstSelector() {
111c988b334SDylan McKay // Install an instruction selector.
112c988b334SDylan McKay addPass(createAVRISelDag(getAVRTargetMachine(), getOptLevel()));
113c988b334SDylan McKay // Create the frame analyzer pass used by the PEI pass.
114c988b334SDylan McKay addPass(createAVRFrameAnalyzerPass());
115c988b334SDylan McKay
1166d8078f9SDylan McKay return false;
1176d8078f9SDylan McKay }
1186d8078f9SDylan McKay
addPreSched2()1191e57fa48SDylan McKay void AVRPassConfig::addPreSched2() {
1201e57fa48SDylan McKay addPass(createAVRExpandPseudoPass());
1211e57fa48SDylan McKay }
1226d8078f9SDylan McKay
addPreEmitPass()1239cf1dc1eSDylan McKay void AVRPassConfig::addPreEmitPass() {
1249cf1dc1eSDylan McKay // Must run branch selection immediately preceding the asm printer.
1259cf1dc1eSDylan McKay addPass(&BranchRelaxationPassID);
1269cf1dc1eSDylan McKay }
1279cf1dc1eSDylan McKay
1286d8078f9SDylan McKay } // end of namespace llvm
129