xref: /llvm-project/flang/lib/Optimizer/CodeGen/Target.cpp (revision 4c263ede5471a7fe3b06e8208b3f1aba1b9dcef2)
1 //===-- Target.cpp --------------------------------------------------------===//
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 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "Target.h"
14 #include "flang/Optimizer/Dialect/FIRType.h"
15 #include "flang/Optimizer/Support/KindMapping.h"
16 #include "mlir/IR/BuiltinTypes.h"
17 #include "mlir/IR/TypeRange.h"
18 
19 #define DEBUG_TYPE "flang-codegen-target"
20 
21 using namespace fir;
22 
23 namespace {
24 template <typename S>
25 struct GenericTarget : public CodeGenSpecifics {
26   using CodeGenSpecifics::CodeGenSpecifics;
27   using AT = CodeGenSpecifics::Attributes;
28 
29   Marshalling boxcharArgumentType(mlir::Type eleTy, bool sret) const override {
30     CodeGenSpecifics::Marshalling marshal;
31     auto idxTy = mlir::IntegerType::get(eleTy.getContext(), S::defaultWidth);
32     auto ptrTy = fir::ReferenceType::get(eleTy);
33     marshal.emplace_back(ptrTy, AT{});
34     // Return value arguments are grouped as a pair. Others are passed in a
35     // split format with all pointers first (in the declared position) and all
36     // LEN arguments appended after all of the dummy arguments.
37     // NB: Other conventions/ABIs can/should be supported via options.
38     marshal.emplace_back(idxTy, AT{/*append=*/!sret});
39     return marshal;
40   }
41 };
42 } // namespace
43 
44 //===----------------------------------------------------------------------===//
45 // i386 (x86 32 bit) linux target specifics.
46 //===----------------------------------------------------------------------===//
47 
48 namespace {
49 struct TargetI386 : public GenericTarget<TargetI386> {
50   using GenericTarget::GenericTarget;
51 
52   static constexpr int defaultWidth = 32;
53 };
54 } // namespace
55 
56 //===----------------------------------------------------------------------===//
57 // x86_64 (x86 64 bit) linux target specifics.
58 //===----------------------------------------------------------------------===//
59 
60 namespace {
61 struct TargetX86_64 : public GenericTarget<TargetX86_64> {
62   using GenericTarget::GenericTarget;
63 
64   static constexpr int defaultWidth = 64;
65 };
66 } // namespace
67 
68 //===----------------------------------------------------------------------===//
69 // AArch64 linux target specifics.
70 //===----------------------------------------------------------------------===//
71 
72 namespace {
73 struct TargetAArch64 : public GenericTarget<TargetAArch64> {
74   using GenericTarget::GenericTarget;
75 
76   static constexpr int defaultWidth = 64;
77 };
78 } // namespace
79 
80 //===----------------------------------------------------------------------===//
81 // PPC64le linux target specifics.
82 //===----------------------------------------------------------------------===//
83 
84 namespace {
85 struct TargetPPC64le : public GenericTarget<TargetPPC64le> {
86   using GenericTarget::GenericTarget;
87 
88   static constexpr int defaultWidth = 64;
89 };
90 } // namespace
91 
92 // Instantiate the overloaded target instance based on the triple value.
93 // Currently, the implementation only instantiates `i386-unknown-linux-gnu`,
94 // `x86_64-unknown-linux-gnu`, aarch64 and ppc64le like triples. Other targets
95 // should be added to this file as needed.
96 std::unique_ptr<fir::CodeGenSpecifics>
97 fir::CodeGenSpecifics::get(mlir::MLIRContext *ctx, llvm::Triple &&trp,
98                            KindMapping &&kindMap) {
99   switch (trp.getArch()) {
100   default:
101     break;
102   case llvm::Triple::ArchType::x86:
103     switch (trp.getOS()) {
104     default:
105       break;
106     case llvm::Triple::OSType::Linux:
107     case llvm::Triple::OSType::Darwin:
108       return std::make_unique<TargetI386>(ctx, std::move(trp),
109                                           std::move(kindMap));
110     }
111     break;
112   case llvm::Triple::ArchType::x86_64:
113     switch (trp.getOS()) {
114     default:
115       break;
116     case llvm::Triple::OSType::Linux:
117     case llvm::Triple::OSType::Darwin:
118       return std::make_unique<TargetX86_64>(ctx, std::move(trp),
119                                             std::move(kindMap));
120     }
121     break;
122   case llvm::Triple::ArchType::aarch64:
123     switch (trp.getOS()) {
124     default:
125       break;
126     case llvm::Triple::OSType::Linux:
127     case llvm::Triple::OSType::Darwin:
128       return std::make_unique<TargetAArch64>(ctx, std::move(trp),
129                                              std::move(kindMap));
130     }
131     break;
132   case llvm::Triple::ArchType::ppc64le:
133     switch (trp.getOS()) {
134     default:
135       break;
136     case llvm::Triple::OSType::Linux:
137       return std::make_unique<TargetPPC64le>(ctx, std::move(trp),
138                                              std::move(kindMap));
139     }
140     break;
141   }
142   llvm::report_fatal_error("target not implemented");
143 }
144