1 | //===--- CSKYTargetMachine.cpp - Define TargetMachine for CSKY ------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Implements the info about CSKY target spec. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "CSKYTargetMachine.h" |
14 | #include "CSKY.h" |
15 | #include "CSKYMachineFunctionInfo.h" |
16 | #include "CSKYSubtarget.h" |
17 | #include "CSKYTargetObjectFile.h" |
18 | #include "TargetInfo/CSKYTargetInfo.h" |
19 | #include "llvm/CodeGen/MachineFrameInfo.h" |
20 | #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" |
21 | #include "llvm/CodeGen/TargetPassConfig.h" |
22 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
23 | #include "llvm/MC/TargetRegistry.h" |
24 | #include <optional> |
25 | |
26 | using namespace llvm; |
27 | |
28 | extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYTarget() { |
29 | RegisterTargetMachine<CSKYTargetMachine> X(getTheCSKYTarget()); |
30 | |
31 | PassRegistry *Registry = PassRegistry::getPassRegistry(); |
32 | initializeCSKYConstantIslandsPass(*Registry); |
33 | initializeCSKYDAGToDAGISelPass(*Registry); |
34 | } |
35 | |
36 | static std::string computeDataLayout(const Triple &TT) { |
37 | std::string Ret; |
38 | |
39 | // Only support little endian for now. |
40 | // TODO: Add support for big endian. |
41 | Ret += "e" ; |
42 | |
43 | // CSKY is always 32-bit target with the CSKYv2 ABI as prefer now. |
44 | // It's a 4-byte aligned stack with ELF mangling only. |
45 | Ret += "-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32" |
46 | "-v128:32:32-a:0:32-Fi32-n32" ; |
47 | |
48 | return Ret; |
49 | } |
50 | |
51 | CSKYTargetMachine::CSKYTargetMachine(const Target &T, const Triple &TT, |
52 | StringRef CPU, StringRef FS, |
53 | const TargetOptions &Options, |
54 | std::optional<Reloc::Model> RM, |
55 | std::optional<CodeModel::Model> CM, |
56 | CodeGenOptLevel OL, bool JIT) |
57 | : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, |
58 | RM.value_or(u: Reloc::Static), |
59 | getEffectiveCodeModel(CM, Default: CodeModel::Small), OL), |
60 | TLOF(std::make_unique<CSKYELFTargetObjectFile>()) { |
61 | initAsmInfo(); |
62 | } |
63 | |
64 | const CSKYSubtarget * |
65 | CSKYTargetMachine::getSubtargetImpl(const Function &F) const { |
66 | Attribute CPUAttr = F.getFnAttribute(Kind: "target-cpu" ); |
67 | Attribute TuneAttr = F.getFnAttribute(Kind: "tune-cpu" ); |
68 | Attribute FSAttr = F.getFnAttribute(Kind: "target-features" ); |
69 | |
70 | std::string CPU = |
71 | CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; |
72 | std::string TuneCPU = |
73 | TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; |
74 | std::string FS = |
75 | FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; |
76 | |
77 | std::string Key = CPU + TuneCPU + FS; |
78 | auto &I = SubtargetMap[Key]; |
79 | if (!I) { |
80 | // This needs to be done before we create a new subtarget since any |
81 | // creation will depend on the TM and the code generation flags on the |
82 | // function that reside in TargetOptions. |
83 | resetTargetOptions(F); |
84 | I = std::make_unique<CSKYSubtarget>(args: TargetTriple, args&: CPU, args&: TuneCPU, args&: FS, args: *this); |
85 | if (I->useHardFloat() && !I->hasAnyFloatExt()) |
86 | errs() << "Hard-float can't be used with current CPU," |
87 | " set to Soft-float\n" ; |
88 | } |
89 | return I.get(); |
90 | } |
91 | |
92 | MachineFunctionInfo *CSKYTargetMachine::createMachineFunctionInfo( |
93 | BumpPtrAllocator &Allocator, const Function &F, |
94 | const TargetSubtargetInfo *STI) const { |
95 | return CSKYMachineFunctionInfo::create<CSKYMachineFunctionInfo>(Allocator, F, |
96 | STI); |
97 | } |
98 | |
99 | namespace { |
100 | class CSKYPassConfig : public TargetPassConfig { |
101 | public: |
102 | CSKYPassConfig(CSKYTargetMachine &TM, PassManagerBase &PM) |
103 | : TargetPassConfig(TM, PM) {} |
104 | |
105 | CSKYTargetMachine &getCSKYTargetMachine() const { |
106 | return getTM<CSKYTargetMachine>(); |
107 | } |
108 | |
109 | void addIRPasses() override; |
110 | bool addInstSelector() override; |
111 | void addPreEmitPass() override; |
112 | }; |
113 | |
114 | } // namespace |
115 | |
116 | TargetPassConfig *CSKYTargetMachine::createPassConfig(PassManagerBase &PM) { |
117 | return new CSKYPassConfig(*this, PM); |
118 | } |
119 | |
120 | void CSKYPassConfig::addIRPasses() { |
121 | addPass(P: createAtomicExpandLegacyPass()); |
122 | TargetPassConfig::addIRPasses(); |
123 | } |
124 | |
125 | bool CSKYPassConfig::addInstSelector() { |
126 | addPass(P: createCSKYISelDag(TM&: getCSKYTargetMachine(), OptLevel: getOptLevel())); |
127 | |
128 | return false; |
129 | } |
130 | |
131 | void CSKYPassConfig::addPreEmitPass() { |
132 | addPass(P: createCSKYConstantIslandPass()); |
133 | } |
134 | |