@@ -117,6 +117,65 @@ struct TargetI386 : public GenericTarget<TargetI386> {
117
117
};
118
118
} // namespace
119
119
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
+
120
179
// ===----------------------------------------------------------------------===//
121
180
// x86_64 (x86 64 bit) linux target specifics.
122
181
// ===----------------------------------------------------------------------===//
@@ -179,6 +238,76 @@ struct TargetX86_64 : public GenericTarget<TargetX86_64> {
179
238
};
180
239
} // namespace
181
240
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
+
182
311
// ===----------------------------------------------------------------------===//
183
312
// AArch64 linux target specifics.
184
313
// ===----------------------------------------------------------------------===//
@@ -418,11 +547,19 @@ fir::CodeGenSpecifics::get(mlir::MLIRContext *ctx, llvm::Triple &&trp,
418
547
default :
419
548
break ;
420
549
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),
425
555
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));
426
563
case llvm::Triple::ArchType::aarch64:
427
564
return std::make_unique<TargetAArch64>(ctx, std::move (trp),
428
565
std::move (kindMap));
0 commit comments