@@ -117,6 +117,65 @@ struct TargetI386 : public GenericTarget<TargetI386> {
117117};
118118} // namespace
119119
120+ // ===----------------------------------------------------------------------===//
121+ // i386 (x86 32 bit) Windows target specifics.
122+ // ===----------------------------------------------------------------------===//
123+
124+ namespace {
125+ struct TargetI386Win : public GenericTarget <TargetI386Win> {
126+ using GenericTarget::GenericTarget;
127+
128+ static constexpr int defaultWidth = 32 ;
129+
130+ CodeGenSpecifics::Marshalling
131+ complexArgumentType (mlir::Location loc, mlir::Type eleTy) const override {
132+ CodeGenSpecifics::Marshalling marshal;
133+ // Use a type that will be translated into LLVM as:
134+ // { t, t } struct of 2 eleTy, byval, align 4
135+ auto structTy =
136+ mlir::TupleType::get (eleTy.getContext (), mlir::TypeRange{eleTy, eleTy});
137+ marshal.emplace_back (fir::ReferenceType::get (structTy),
138+ AT{/* align=*/ 4 , /* byval=*/ true });
139+ return marshal;
140+ }
141+
142+ CodeGenSpecifics::Marshalling
143+ complexReturnType (mlir::Location loc, mlir::Type eleTy) const override {
144+ CodeGenSpecifics::Marshalling marshal;
145+ const auto *sem = &floatToSemantics (kindMap, eleTy);
146+ if (sem == &llvm::APFloat::IEEEsingle ()) {
147+ // i64 pack both floats in a 64-bit GPR
148+ marshal.emplace_back (mlir::IntegerType::get (eleTy.getContext (), 64 ),
149+ AT{});
150+ } else if (sem == &llvm::APFloat::IEEEdouble ()) {
151+ // Use a type that will be translated into LLVM as:
152+ // { double, double } struct of 2 double, sret, align 8
153+ marshal.emplace_back (
154+ fir::ReferenceType::get (mlir::TupleType::get (
155+ eleTy.getContext (), mlir::TypeRange{eleTy, eleTy})),
156+ AT{/* align=*/ 8 , /* byval=*/ false , /* sret=*/ true });
157+ } else if (sem == &llvm::APFloat::IEEEquad ()) {
158+ // Use a type that will be translated into LLVM as:
159+ // { fp128, fp128 } struct of 2 fp128, sret, align 16
160+ marshal.emplace_back (
161+ fir::ReferenceType::get (mlir::TupleType::get (
162+ eleTy.getContext (), mlir::TypeRange{eleTy, eleTy})),
163+ AT{/* align=*/ 16 , /* byval=*/ false , /* sret=*/ true });
164+ } else if (sem == &llvm::APFloat::x87DoubleExtended ()) {
165+ // Use a type that will be translated into LLVM as:
166+ // { x86_fp80, x86_fp80 } struct of 2 x86_fp80, sret, align 4
167+ marshal.emplace_back (
168+ fir::ReferenceType::get (mlir::TupleType::get (
169+ eleTy.getContext (), mlir::TypeRange{eleTy, eleTy})),
170+ AT{/* align=*/ 4 , /* byval=*/ false , /* sret=*/ true });
171+ } else {
172+ TODO (loc, " complex for this precision" );
173+ }
174+ return marshal;
175+ }
176+ };
177+ } // namespace
178+
120179// ===----------------------------------------------------------------------===//
121180// x86_64 (x86 64 bit) linux target specifics.
122181// ===----------------------------------------------------------------------===//
@@ -179,6 +238,76 @@ struct TargetX86_64 : public GenericTarget<TargetX86_64> {
179238};
180239} // namespace
181240
241+ // ===----------------------------------------------------------------------===//
242+ // x86_64 (x86 64 bit) Windows target specifics.
243+ // ===----------------------------------------------------------------------===//
244+
245+ namespace {
246+ struct TargetX86_64Win : public GenericTarget <TargetX86_64Win> {
247+ using GenericTarget::GenericTarget;
248+
249+ static constexpr int defaultWidth = 64 ;
250+
251+ CodeGenSpecifics::Marshalling
252+ complexArgumentType (mlir::Location loc, mlir::Type eleTy) const override {
253+ CodeGenSpecifics::Marshalling marshal;
254+ const auto *sem = &floatToSemantics (kindMap, eleTy);
255+ if (sem == &llvm::APFloat::IEEEsingle ()) {
256+ // i64 pack both floats in a 64-bit GPR
257+ marshal.emplace_back (mlir::IntegerType::get (eleTy.getContext (), 64 ),
258+ AT{});
259+ } else if (sem == &llvm::APFloat::IEEEdouble ()) {
260+ // Use a type that will be translated into LLVM as:
261+ // { double, double } struct of 2 double, byval, align 8
262+ marshal.emplace_back (
263+ fir::ReferenceType::get (mlir::TupleType::get (
264+ eleTy.getContext (), mlir::TypeRange{eleTy, eleTy})),
265+ AT{/* align=*/ 8 , /* byval=*/ true });
266+ } else if (sem == &llvm::APFloat::IEEEquad () ||
267+ sem == &llvm::APFloat::x87DoubleExtended ()) {
268+ // Use a type that will be translated into LLVM as:
269+ // { t, t } struct of 2 eleTy, byval, align 16
270+ marshal.emplace_back (
271+ fir::ReferenceType::get (mlir::TupleType::get (
272+ eleTy.getContext (), mlir::TypeRange{eleTy, eleTy})),
273+ AT{/* align=*/ 16 , /* byval=*/ true });
274+ } else {
275+ TODO (loc, " complex for this precision" );
276+ }
277+ return marshal;
278+ }
279+
280+ CodeGenSpecifics::Marshalling
281+ complexReturnType (mlir::Location loc, mlir::Type eleTy) const override {
282+ CodeGenSpecifics::Marshalling marshal;
283+ const auto *sem = &floatToSemantics (kindMap, eleTy);
284+ if (sem == &llvm::APFloat::IEEEsingle ()) {
285+ // i64 pack both floats in a 64-bit GPR
286+ marshal.emplace_back (mlir::IntegerType::get (eleTy.getContext (), 64 ),
287+ AT{});
288+ } else if (sem == &llvm::APFloat::IEEEdouble ()) {
289+ // Use a type that will be translated into LLVM as:
290+ // { double, double } struct of 2 double, sret, align 8
291+ marshal.emplace_back (
292+ fir::ReferenceType::get (mlir::TupleType::get (
293+ eleTy.getContext (), mlir::TypeRange{eleTy, eleTy})),
294+ AT{/* align=*/ 8 , /* byval=*/ false , /* sret=*/ true });
295+ } else if (sem == &llvm::APFloat::IEEEquad () ||
296+ sem == &llvm::APFloat::x87DoubleExtended ()) {
297+ // Use a type that will be translated into LLVM as:
298+ // { t, t } struct of 2 eleTy, sret, align 16
299+ marshal.emplace_back (
300+ fir::ReferenceType::get (mlir::TupleType::get (
301+ eleTy.getContext (), mlir::TypeRange{eleTy, eleTy})),
302+ AT{/* align=*/ 16 , /* byval=*/ false , /* sret=*/ true });
303+ } else {
304+ TODO (loc, " complex for this precision" );
305+ }
306+ return marshal;
307+ }
308+ };
309+ } // namespace
310+
182311// ===----------------------------------------------------------------------===//
183312// AArch64 linux target specifics.
184313// ===----------------------------------------------------------------------===//
@@ -418,11 +547,19 @@ fir::CodeGenSpecifics::get(mlir::MLIRContext *ctx, llvm::Triple &&trp,
418547 default :
419548 break ;
420549 case llvm::Triple::ArchType::x86:
421- return std::make_unique<TargetI386>(ctx, std::move (trp),
422- std::move (kindMap));
423- case llvm::Triple::ArchType::x86_64:
424- return std::make_unique<TargetX86_64>(ctx, std::move (trp),
550+ if (trp.isOSWindows ())
551+ return std::make_unique<TargetI386Win>(ctx, std::move (trp),
552+ std::move (kindMap));
553+ else
554+ return std::make_unique<TargetI386>(ctx, std::move (trp),
425555 std::move (kindMap));
556+ case llvm::Triple::ArchType::x86_64:
557+ if (trp.isOSWindows ())
558+ return std::make_unique<TargetX86_64Win>(ctx, std::move (trp),
559+ std::move (kindMap));
560+ else
561+ return std::make_unique<TargetX86_64>(ctx, std::move (trp),
562+ std::move (kindMap));
426563 case llvm::Triple::ArchType::aarch64:
427564 return std::make_unique<TargetAArch64>(ctx, std::move (trp),
428565 std::move (kindMap));
0 commit comments