xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AVR/AVRTargetMachine.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- AVRTargetMachine.cpp - Define TargetMachine for AVR ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the AVR specific subclass of TargetMachine.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "AVRTargetMachine.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
170b57cec5SDimitry Andric #include "llvm/IR/Module.h"
18349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "AVR.h"
21bdd1243dSDimitry Andric #include "AVRMachineFunctionInfo.h"
220b57cec5SDimitry Andric #include "AVRTargetObjectFile.h"
230b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h"
240b57cec5SDimitry Andric #include "TargetInfo/AVRTargetInfo.h"
250b57cec5SDimitry Andric 
26bdd1243dSDimitry Andric #include <optional>
27bdd1243dSDimitry Andric 
280b57cec5SDimitry Andric namespace llvm {
290b57cec5SDimitry Andric 
30349cc55cSDimitry Andric static const char *AVRDataLayout =
31349cc55cSDimitry Andric     "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8";
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric /// Processes a CPU name.
340b57cec5SDimitry Andric static StringRef getCPU(StringRef CPU) {
350b57cec5SDimitry Andric   if (CPU.empty() || CPU == "generic") {
360b57cec5SDimitry Andric     return "avr2";
370b57cec5SDimitry Andric   }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   return CPU;
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric 
42bdd1243dSDimitry Andric static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
4381ad6265SDimitry Andric   return RM.value_or(Reloc::Static);
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric AVRTargetMachine::AVRTargetMachine(const Target &T, const Triple &TT,
470b57cec5SDimitry Andric                                    StringRef CPU, StringRef FS,
480b57cec5SDimitry Andric                                    const TargetOptions &Options,
49bdd1243dSDimitry Andric                                    std::optional<Reloc::Model> RM,
50bdd1243dSDimitry Andric                                    std::optional<CodeModel::Model> CM,
515f757f3fSDimitry Andric                                    CodeGenOptLevel OL, bool JIT)
520b57cec5SDimitry Andric     : LLVMTargetMachine(T, AVRDataLayout, TT, getCPU(CPU), FS, Options,
530b57cec5SDimitry Andric                         getEffectiveRelocModel(RM),
540b57cec5SDimitry Andric                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
555ffd83dbSDimitry Andric       SubTarget(TT, std::string(getCPU(CPU)), std::string(FS), *this) {
568bcb0991SDimitry Andric   this->TLOF = std::make_unique<AVRTargetObjectFile>();
570b57cec5SDimitry Andric   initAsmInfo();
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric namespace {
610b57cec5SDimitry Andric /// AVR Code Generator Pass Configuration Options.
620b57cec5SDimitry Andric class AVRPassConfig : public TargetPassConfig {
630b57cec5SDimitry Andric public:
640b57cec5SDimitry Andric   AVRPassConfig(AVRTargetMachine &TM, PassManagerBase &PM)
650b57cec5SDimitry Andric       : TargetPassConfig(TM, PM) {}
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   AVRTargetMachine &getAVRTargetMachine() const {
680b57cec5SDimitry Andric     return getTM<AVRTargetMachine>();
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric 
71fe6060f1SDimitry Andric   void addIRPasses() override;
720b57cec5SDimitry Andric   bool addInstSelector() override;
730b57cec5SDimitry Andric   void addPreSched2() override;
740b57cec5SDimitry Andric   void addPreEmitPass() override;
750b57cec5SDimitry Andric };
760b57cec5SDimitry Andric } // namespace
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric TargetPassConfig *AVRTargetMachine::createPassConfig(PassManagerBase &PM) {
790b57cec5SDimitry Andric   return new AVRPassConfig(*this, PM);
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
82fe6060f1SDimitry Andric void AVRPassConfig::addIRPasses() {
83fe6060f1SDimitry Andric   // Expand instructions like
84fe6060f1SDimitry Andric   //   %result = shl i32 %n, %amount
85fe6060f1SDimitry Andric   // to a loop so that library calls are avoided.
86fe6060f1SDimitry Andric   addPass(createAVRShiftExpandPass());
87fe6060f1SDimitry Andric 
88fe6060f1SDimitry Andric   TargetPassConfig::addIRPasses();
89fe6060f1SDimitry Andric }
90fe6060f1SDimitry Andric 
91480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRTarget() {
920b57cec5SDimitry Andric   // Register the target.
930b57cec5SDimitry Andric   RegisterTargetMachine<AVRTargetMachine> X(getTheAVRTarget());
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   auto &PR = *PassRegistry::getPassRegistry();
960b57cec5SDimitry Andric   initializeAVRExpandPseudoPass(PR);
97fe6060f1SDimitry Andric   initializeAVRShiftExpandPass(PR);
98*0fca6ea1SDimitry Andric   initializeAVRDAGToDAGISelLegacyPass(PR);
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric const AVRSubtarget *AVRTargetMachine::getSubtargetImpl() const {
1020b57cec5SDimitry Andric   return &SubTarget;
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric const AVRSubtarget *AVRTargetMachine::getSubtargetImpl(const Function &) const {
1060b57cec5SDimitry Andric   return &SubTarget;
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
109bdd1243dSDimitry Andric MachineFunctionInfo *AVRTargetMachine::createMachineFunctionInfo(
110bdd1243dSDimitry Andric     BumpPtrAllocator &Allocator, const Function &F,
111bdd1243dSDimitry Andric     const TargetSubtargetInfo *STI) const {
112bdd1243dSDimitry Andric   return AVRMachineFunctionInfo::create<AVRMachineFunctionInfo>(Allocator, F,
113bdd1243dSDimitry Andric                                                                 STI);
114bdd1243dSDimitry Andric }
115bdd1243dSDimitry Andric 
1160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1170b57cec5SDimitry Andric // Pass Pipeline Configuration
1180b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric bool AVRPassConfig::addInstSelector() {
1210b57cec5SDimitry Andric   // Install an instruction selector.
1220b57cec5SDimitry Andric   addPass(createAVRISelDag(getAVRTargetMachine(), getOptLevel()));
1230b57cec5SDimitry Andric   // Create the frame analyzer pass used by the PEI pass.
1240b57cec5SDimitry Andric   addPass(createAVRFrameAnalyzerPass());
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   return false;
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric void AVRPassConfig::addPreSched2() {
1300b57cec5SDimitry Andric   addPass(createAVRExpandPseudoPass());
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric void AVRPassConfig::addPreEmitPass() {
1340b57cec5SDimitry Andric   // Must run branch selection immediately preceding the asm printer.
1350b57cec5SDimitry Andric   addPass(&BranchRelaxationPassID);
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric } // end of namespace llvm
139