clang 24.0.0git
CIRTypes.cpp
Go to the documentation of this file.
1//===- CIRTypes.cpp - MLIR CIR Types --------------------------------------===//
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// This file defines the types in the CIR dialect.
10//
11//===----------------------------------------------------------------------===//
12
14
15#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
16#include "mlir/IR/BuiltinAttributes.h"
17#include "mlir/IR/DialectImplementation.h"
18#include "mlir/IR/MLIRContext.h"
19#include "mlir/Support/LLVM.h"
26#include "llvm/ADT/APFloat.h"
27#include "llvm/ADT/APInt.h"
28#include "llvm/ADT/APSInt.h"
29#include "llvm/ADT/TypeSwitch.h"
30#include "llvm/Support/MathExtras.h"
31
32//===----------------------------------------------------------------------===//
33// CIR Helpers
34//===----------------------------------------------------------------------===//
35bool cir::isSized(mlir::Type ty) {
36 if (auto sizedTy = mlir::dyn_cast<cir::SizedTypeInterface>(ty))
37 return sizedTy.isSized();
39 return false;
40}
41
42cir::FPTypeInterface cir::getFloatingPointType(const llvm::fltSemantics &sem,
43 mlir::MLIRContext *ctx) {
44 switch (llvm::APFloat::SemanticsToEnum(sem)) {
45 case llvm::APFloat::S_IEEEhalf:
46 return cir::FP16Type::get(ctx);
47 case llvm::APFloat::S_BFloat:
48 return cir::BF16Type::get(ctx);
49 case llvm::APFloat::S_IEEEsingle:
50 return cir::SingleType::get(ctx);
51 case llvm::APFloat::S_IEEEdouble:
52 return cir::DoubleType::get(ctx);
53 case llvm::APFloat::S_x87DoubleExtended:
54 return cir::FP80Type::get(ctx);
55 case llvm::APFloat::S_IEEEquad:
56 return cir::FP128Type::get(ctx);
57 default:
58 // CIR has no type for the remaining semantics (PPCDoubleDouble, the
59 // Float8 formats). Return null and let the caller report it.
60 return {};
61 }
62}
63
64static bool isPureCIRType(mlir::Type ty) {
65 if (!ty)
66 return true;
67 return !ty.walk([](mlir::Type t) {
68 if (!t)
69 return mlir::WalkResult::advance();
70 return mlir::isa<cir::CIRDialect>(t.getDialect())
71 ? mlir::WalkResult::advance()
72 : mlir::WalkResult::interrupt();
73 }).wasInterrupted();
74}
75
76//===----------------------------------------------------------------------===//
77// CIR Custom Parser/Printer Signatures
78//===----------------------------------------------------------------------===//
79
80static mlir::ParseResult
81parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &params,
82 bool &isVarArg);
83static void printFuncTypeParams(mlir::AsmPrinter &p,
84 mlir::ArrayRef<mlir::Type> params,
85 bool isVarArg);
86//===----------------------------------------------------------------------===//
87// CIR Custom Parser/Printer Signatures
88//===----------------------------------------------------------------------===//
89
90static mlir::ParseResult
91parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &params,
92 bool &isVarArg);
93
94static void printFuncTypeParams(mlir::AsmPrinter &p,
95 mlir::ArrayRef<mlir::Type> params,
96 bool isVarArg);
97
98//===----------------------------------------------------------------------===//
99// AddressSpace
100//===----------------------------------------------------------------------===//
101
102// Spells the address space of `!cir.ptr` and `cir.global` as either
103// `lang_address_space(x)` or `target_address_space(n)`.
104mlir::ParseResult parseMemorySpace(mlir::AsmParser &p,
105 mlir::ptr::MemorySpaceAttrInterface &attr);
106
107void printMemorySpace(mlir::AsmPrinter &printer,
108 mlir::ptr::MemorySpaceAttrInterface attr);
109
110//===----------------------------------------------------------------------===//
111// Get autogenerated stuff
112//===----------------------------------------------------------------------===//
113
114namespace cir {
115
116#include "clang/CIR/Dialect/IR/CIRTypeConstraints.cpp.inc"
117
118} // namespace cir
119
120#define GET_TYPEDEF_CLASSES
121#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
122
123using namespace mlir;
124using namespace cir;
125
126//===----------------------------------------------------------------------===//
127// General CIR parsing / printing
128//===----------------------------------------------------------------------===//
129
130Type CIRDialect::parseType(DialectAsmParser &parser) const {
131 llvm::SMLoc typeLoc = parser.getCurrentLocation();
132 llvm::StringRef mnemonic;
133 Type genType;
134
135 // Try to parse as a tablegen'd type.
136 OptionalParseResult parseResult =
137 generatedTypeParser(parser, &mnemonic, genType);
138 if (parseResult.has_value())
139 return genType;
140
141 // All CIR types are now tablegen'd; nothing left to dispatch here.
142 parser.emitError(typeLoc) << "unknown CIR type: " << mnemonic;
143 return Type();
144}
145
146void CIRDialect::printType(Type type, DialectAsmPrinter &os) const {
147 // Try to print as a tablegen'd type.
148 if (generatedTypePrinter(type, os).succeeded())
149 return;
150
151 // TODO(CIR) Attempt to print as a raw C++ type.
152 llvm::report_fatal_error("printer is missing a handler for this type");
153}
154
155//===----------------------------------------------------------------------===//
156// StructType
157//===----------------------------------------------------------------------===//
158
159// Shared helpers for StructType and UnionType parse/print.
160
163 return llvm::SmallVector<RecordMemberKind>(members.size(),
164 RecordMemberKind::Data);
165}
166
167/// An incomplete record has no members, so a kind for one is caught by the
168/// same check.
169static mlir::LogicalResult
170verifyRecordMemberKinds(function_ref<mlir::InFlightDiagnostic()> emitError,
171 size_t numMembers,
173 if (memberKinds.size() != numMembers)
174 return emitError() << "expected " << numMembers << " member kinds, got "
175 << memberKinds.size();
176 return mlir::success();
177}
178
179/// The keywords that spell a member kind. A union's tail-padding slot probes
180/// for one of these to reject it, since that slot is not a member.
181static const llvm::StringRef memberKindMarks[] = {"data", "pad", "empty",
182 "bitfield"};
183
184static std::optional<RecordMemberKind>
185parseMemberKind(mlir::AsmParser &parser) {
186 llvm::StringRef keyword;
187 const llvm::SMLoc loc = parser.getCurrentLocation();
188 if (parser.parseKeyword(&keyword).failed())
189 return std::nullopt;
190 std::optional<RecordMemberKind> kind = symbolizeRecordMemberKind(keyword);
191 if (!kind)
192 parser.emitError(loc, "expected a record member kind");
193 return kind;
194}
195
196/// Parse "incomplete" or "{mark type, mark type, ...}", writing results into
197/// \p incomplete, \p members and \p memberKinds. Returns failure if member
198/// parsing fails.
199static mlir::ParseResult
200parseRecordBody(mlir::AsmParser &parser, bool &incomplete,
203 assert(incomplete && "caller must pre-initialize incomplete to true");
204 if (parser.parseOptionalKeyword("incomplete").succeeded())
205 return mlir::success();
206 incomplete = false;
207 return parser.parseCommaSeparatedList(
208 AsmParser::Delimiter::Braces,
209 [&parser, &members, &memberKinds]() -> mlir::ParseResult {
210 std::optional<RecordMemberKind> kind = parseMemberKind(parser);
211 if (!kind)
212 return mlir::failure();
213 memberKinds.push_back(*kind);
214 return parser.parseType(members.emplace_back());
215 });
216}
217
218/// Print a complete CIR record body:
219/// '<' ['class '] [name] ['packed '] body '>'
220/// where body is "incomplete" or "{[mark] members}[, padding = {type}]".
221/// RecordTy must be a mutable MLIR type (StructType or UnionType).
222template <typename RecordTy>
223static void
224printRecordBody(mlir::AsmPrinter &printer, RecordTy self, mlir::StringAttr name,
225 bool hasClassPrefix, bool isPacked, bool isIncomplete,
226 llvm::ArrayRef<mlir::Type> members, mlir::Type padding,
228 printer << '<';
229 if (hasClassPrefix)
230 printer << "class ";
231 if (name)
232 printer << name;
233
234 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrintGuard =
235 printer.tryStartCyclicPrint(self);
236 if (failed(cyclicPrintGuard)) {
237 printer << '>';
238 return;
239 }
240
241 if (hasClassPrefix || name)
242 printer << ' ';
243 if (isPacked)
244 printer << "packed ";
245 if (isIncomplete) {
246 printer << "incomplete";
247 } else {
248 printer << "{";
249 for (auto [idx, member] : llvm::enumerate(members)) {
250 if (idx)
251 printer << ", ";
252 printer << stringifyRecordMemberKind(memberKinds[idx]) << ' ';
253 printer.printType(member);
254 }
255 printer << "}";
256 if (padding) {
257 printer << ", padding = {";
258 printer.printType(padding);
259 printer << '}';
260 }
261 }
262 printer << '>';
263}
264
265/// Parse the body of a !cir.struct<...> type.
266Type StructType::parse(mlir::AsmParser &parser) {
267 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
268 const llvm::SMLoc loc = parser.getCurrentLocation();
269 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
270 bool packed = false;
271 mlir::MLIRContext *context = parser.getContext();
272
273 if (parser.parseLess())
274 return {};
275
276 // An optional "class" keyword distinguishes class from struct.
277 bool is_class = parser.parseOptionalKeyword("class").succeeded();
278
279 mlir::StringAttr name;
280 parser.parseOptionalAttribute(name);
281
282 // Self-reference: ensure the referenced type was already parsed.
283 if (name && parser.parseOptionalGreater().succeeded()) {
284 StructType type = StructType::getChecked(eLoc, context, name, is_class);
285 if (succeeded(parser.tryStartCyclicParse(type))) {
286 parser.emitError(loc, "invalid self-reference within record");
287 return {};
288 }
289 return type;
290 }
291
292 // Named definition: ensure name has not been parsed yet.
293 if (name) {
294 StructType type = StructType::getChecked(eLoc, context, name, is_class);
295 cyclicParseGuard = parser.tryStartCyclicParse(type);
296 if (failed(cyclicParseGuard)) {
297 parser.emitError(loc, "record already defined");
298 return {};
299 }
300 }
301
302 if (parser.parseOptionalKeyword("packed").succeeded())
303 packed = true;
304
305 bool incomplete = true;
306 llvm::SmallVector<mlir::Type> members;
307 llvm::SmallVector<RecordMemberKind> memberKinds;
308 if (parseRecordBody(parser, incomplete, members, memberKinds).failed())
309 return {};
310
311 if (parser.parseGreater())
312 return {};
313
314 ArrayRef<mlir::Type> membersRef(members);
315 ArrayRef<RecordMemberKind> kindsRef(memberKinds);
316 mlir::Type type = {};
317 if (name && incomplete) {
318 type = StructType::getChecked(eLoc, context, name, is_class);
319 } else if (!name && !incomplete) {
320 type = StructType::getChecked(eLoc, context, membersRef, packed, is_class,
321 kindsRef);
322 if (!type)
323 return {};
324 } else if (!incomplete) {
325 type = StructType::getChecked(eLoc, context, membersRef, name, packed,
326 is_class, kindsRef);
327 if (!type)
328 return {};
329 if (auto structTy = mlir::dyn_cast<StructType>(type))
330 if (structTy.isIncomplete())
331 structTy.complete(membersRef, packed, kindsRef);
333 } else {
334 parser.emitError(loc, "anonymous records must be complete");
335 return {};
336 }
337
338 return type;
339}
340
341void StructType::print(mlir::AsmPrinter &printer) const {
342 printRecordBody(printer, *this, getName(), isClass(), getPacked(),
343 isIncomplete(), getMembers(), /*padding=*/{},
344 getMemberKinds());
345}
346
347mlir::LogicalResult StructType::verify(
348 function_ref<mlir::InFlightDiagnostic()> emitError,
349 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name, bool incomplete,
350 bool packed, llvm::ArrayRef<RecordMemberKind> member_kinds, bool is_class) {
351 if (name && name.getValue().empty())
352 return emitError() << "identified records cannot have an empty name";
353 return verifyRecordMemberKinds(emitError, members.size(), member_kinds);
354}
355
356// Accessors are hand-written because genStorageClass = 0 suppresses generated
357// implementations.
358llvm::ArrayRef<mlir::Type> StructType::getMembers() const {
359 return getImpl()->members;
360}
361mlir::StringAttr StructType::getName() const { return getImpl()->name; }
362bool StructType::isIncomplete() const { return getImpl()->incomplete; }
363bool StructType::getIncomplete() const { return getImpl()->incomplete; }
364bool StructType::getPacked() const { return getImpl()->packed; }
365llvm::ArrayRef<RecordMemberKind> StructType::getMemberKinds() const {
366 return getImpl()->member_kinds;
367}
368bool StructType::getIsClass() const { return getImpl()->is_class; }
369
370bool StructType::getPadded() const {
371 return llvm::is_contained(getMemberKinds(), RecordMemberKind::Pad);
372}
373
374bool StructType::isABIConvertedRecord() const {
375 return getName() && getName().getValue().starts_with(abi_conversion_prefix);
376}
377
378mlir::StringAttr StructType::getABIConvertedName() const {
379 assert(!isABIConvertedRecord());
380 return StringAttr::get(getContext(),
381 abi_conversion_prefix + getName().getValue());
382}
383
384void StructType::removeABIConversionNamePrefix() {
385 mlir::StringAttr recordName = getName();
386 if (recordName && recordName.getValue().starts_with(abi_conversion_prefix))
387 getImpl()->name = mlir::StringAttr::get(
388 recordName.getValue().drop_front(sizeof(abi_conversion_prefix) - 1),
389 recordName.getType());
390}
391
392void StructType::complete(ArrayRef<Type> members, bool packed,
393 ArrayRef<RecordMemberKind> memberKinds) {
395 if (mutate(members, packed, memberKinds).failed())
396 llvm_unreachable("failed to complete struct");
397}
398
399bool StructType::isLayoutIdentical(const StructType &other) {
400 if (getImpl() == other.getImpl())
401 return true;
402 if (getPacked() != other.getPacked())
403 return false;
404 return getMembers() == other.getMembers();
405}
406
407//===----------------------------------------------------------------------===//
408// UnionType
409//===----------------------------------------------------------------------===//
410
411Type UnionType::parse(mlir::AsmParser &parser) {
412 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
413 const llvm::SMLoc loc = parser.getCurrentLocation();
414 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
415 bool packed = false;
416 mlir::Type padding;
417 mlir::MLIRContext *context = parser.getContext();
418
419 if (parser.parseLess())
420 return {};
421
422 mlir::StringAttr name;
423 parser.parseOptionalAttribute(name);
424
425 // Self-reference.
426 if (name && parser.parseOptionalGreater().succeeded()) {
427 UnionType type = UnionType::getChecked(eLoc, context, name);
428 if (succeeded(parser.tryStartCyclicParse(type))) {
429 parser.emitError(loc, "invalid self-reference within record");
430 return {};
431 }
432 return type;
433 }
434
435 // Named definition.
436 if (name) {
437 UnionType type = UnionType::getChecked(eLoc, context, name);
438 cyclicParseGuard = parser.tryStartCyclicParse(type);
439 if (failed(cyclicParseGuard)) {
440 parser.emitError(loc, "record already defined");
441 return {};
442 }
443 }
444
445 if (parser.parseOptionalKeyword("packed").succeeded())
446 packed = true;
447
448 bool incomplete = true;
449 llvm::SmallVector<mlir::Type> members;
450 llvm::SmallVector<RecordMemberKind> memberKinds;
451 if (parseRecordBody(parser, incomplete, members, memberKinds).failed())
452 return {};
453
454 // Optional tail-padding slot: ", padding = { <type> }". It is not a variant
455 // and so takes no mark.
456 if (!incomplete && parser.parseOptionalComma().succeeded()) {
457 if (parser.parseKeyword("padding").failed())
458 return {};
459 if (parser.parseEqual().failed())
460 return {};
461 if (parser.parseLBrace().failed())
462 return {};
463 const llvm::SMLoc paddingLoc = parser.getCurrentLocation();
464 llvm::StringRef paddingKeyword;
465 if (parser.parseOptionalKeyword(&paddingKeyword, memberKindMarks)
466 .succeeded()) {
467 parser.emitError(paddingLoc, "a union's tail padding takes no kind mark");
468 return {};
469 }
470 if (parser.parseType(padding).failed())
471 return {};
472 if (parser.parseRBrace().failed())
473 return {};
474 }
475
476 if (parser.parseGreater())
477 return {};
478
479 ArrayRef<mlir::Type> membersRef(members);
480 ArrayRef<RecordMemberKind> kindsRef(memberKinds);
481 mlir::Type type = {};
482 if (name && incomplete) {
483 type = UnionType::getChecked(eLoc, context, name);
484 } else if (!name && !incomplete) {
485 type = UnionType::getChecked(eLoc, context, membersRef, packed, padding,
486 kindsRef);
487 if (!type)
488 return {};
489 } else if (!incomplete) {
490 type = UnionType::getChecked(eLoc, context, membersRef, name, packed,
491 padding, kindsRef);
492 if (!type)
493 return {};
494 if (auto unionTy = mlir::dyn_cast<UnionType>(type))
495 if (unionTy.isIncomplete())
496 unionTy.complete(membersRef, packed, padding, kindsRef);
498 } else {
499 parser.emitError(loc, "anonymous records must be complete");
500 return {};
501 }
502
503 return type;
504}
505
506void UnionType::print(mlir::AsmPrinter &printer) const {
507 printRecordBody(printer, *this, getName(), /*hasClassPrefix=*/false,
508 getPacked(), isIncomplete(), getMembers(), getPadding(),
509 getMemberKinds());
510}
511
512mlir::LogicalResult
513UnionType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
514 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
515 bool incomplete, bool packed, mlir::Type padding,
516 llvm::ArrayRef<RecordMemberKind> member_kinds) {
517 if (name && name.getValue().empty())
518 return emitError() << "identified records cannot have an empty name";
519 // A union's variants all start at offset zero, so there is no inter-member
520 // padding for a pad mark to describe. Its tail padding lives in the separate
521 // padding slot.
522 if (llvm::is_contained(member_kinds, RecordMemberKind::Pad))
523 return emitError() << "a union member cannot be marked pad";
524 // Every variant starts at offset zero, so a bit-field variant is an access
525 // unit of its own. There is no run for a zero-width bit-field to end, so a
526 // variant always has storage.
527 for (auto [idx, memberTy] : llvm::enumerate(members))
528 if (auto bfTy = mlir::dyn_cast<cir::BitFieldType>(memberTy);
529 bfTy && !bfTy.ownsBytes())
530 return emitError() << "union bit-field member at index " << idx
531 << " must own its access unit storage";
532 return verifyRecordMemberKinds(emitError, members.size(), member_kinds);
533}
534
535// Accessors.
536llvm::ArrayRef<mlir::Type> UnionType::getMembers() const {
537 return getImpl()->members;
538}
539mlir::StringAttr UnionType::getName() const { return getImpl()->name; }
540bool UnionType::isIncomplete() const { return getImpl()->incomplete; }
541bool UnionType::getIncomplete() const { return getImpl()->incomplete; }
542bool UnionType::getPacked() const { return getImpl()->packed; }
543bool UnionType::getPadded() const { return getPadding() ? true : false; }
544mlir::Type UnionType::getPadding() const { return getImpl()->padding; }
545llvm::ArrayRef<RecordMemberKind> UnionType::getMemberKinds() const {
546 return getImpl()->member_kinds;
547}
548
549bool UnionType::isABIConvertedRecord() const {
550 return getName() && getName().getValue().starts_with(abi_conversion_prefix);
551}
552
553mlir::StringAttr UnionType::getABIConvertedName() const {
554 assert(!isABIConvertedRecord());
555 return StringAttr::get(getContext(),
556 abi_conversion_prefix + getName().getValue());
557}
558
559void UnionType::removeABIConversionNamePrefix() {
560 mlir::StringAttr recordName = getName();
561 if (recordName && recordName.getValue().starts_with(abi_conversion_prefix))
562 getImpl()->name = mlir::StringAttr::get(
563 recordName.getValue().drop_front(sizeof(abi_conversion_prefix) - 1),
564 recordName.getType());
565}
566
567void UnionType::complete(ArrayRef<Type> members, bool packed,
568 mlir::Type padding,
569 ArrayRef<RecordMemberKind> memberKinds) {
571 if (mutate(members, packed, padding, memberKinds).failed())
572 llvm_unreachable("failed to complete union");
573}
574
575mlir::Type
576UnionType::getUnionStorageType(const mlir::DataLayout &dataLayout) const {
577 return getUnionStorageType(dataLayout, getMembers());
578}
579
580mlir::Type UnionType::getUnionStorageType(const mlir::DataLayout &dataLayout,
581 llvm::ArrayRef<mlir::Type> members) {
582 if (members.empty())
583 return {};
584 mlir::Type largest = *std::max_element(
585 members.begin(), members.end(), [&](mlir::Type lhs, mlir::Type rhs) {
586 return dataLayout.getTypeABIAlignment(lhs) <
587 dataLayout.getTypeABIAlignment(rhs) ||
588 (dataLayout.getTypeABIAlignment(lhs) ==
589 dataLayout.getTypeABIAlignment(rhs) &&
590 dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
591 });
592 // A union's storage is bytes, and stands in for every variant rather than
593 // for the one bit-field that happened to be widest, so a bit-field variant
594 // contributes its access unit rather than itself.
595 return memberStorageType(largest);
596}
597
598bool UnionType::isLayoutIdentical(const UnionType &other) {
599 if (getImpl() == other.getImpl())
600 return true;
601 return getMembers() == other.getMembers() &&
602 getPadding() == other.getPadding();
603}
604
605//===----------------------------------------------------------------------===//
606// RecordType view-class method implementations
607//===----------------------------------------------------------------------===//
608
610 if (auto s = mlir::dyn_cast<StructType>(*this))
611 return s.getMembers();
612 return mlir::cast<UnionType>(*this).getMembers();
613}
614mlir::StringAttr RecordType::getName() const {
615 if (auto s = mlir::dyn_cast<StructType>(*this))
616 return s.getName();
617 return mlir::cast<UnionType>(*this).getName();
618}
620 if (auto s = mlir::dyn_cast<StructType>(*this))
621 return s.isIncomplete();
622 return mlir::cast<UnionType>(*this).isIncomplete();
623}
625 if (auto s = mlir::dyn_cast<StructType>(*this))
626 return s.getPacked();
627 return mlir::cast<UnionType>(*this).getPacked();
628}
630 if (auto s = mlir::dyn_cast<StructType>(*this))
631 return s.getPadded();
632 return mlir::cast<UnionType>(*this).getPadded();
633}
635 if (auto s = mlir::dyn_cast<StructType>(*this))
636 return s.getMemberKinds();
637 return mlir::cast<UnionType>(*this).getMemberKinds();
638}
640 if (auto s = mlir::dyn_cast<StructType>(*this))
641 return s.isClass();
642 return false;
643}
645 if (auto s = mlir::dyn_cast<StructType>(*this))
646 return s.isStruct();
647 return false;
648}
649std::string RecordType::getKindAsStr() const {
650 if (mlir::isa<UnionType>(*this))
651 return "union";
652 return mlir::cast<StructType>(*this).getKindAsStr();
653}
654std::string RecordType::getPrefixedName() const {
655 return getKindAsStr() + "." + getName().getValue().str();
656}
657void RecordType::complete(ArrayRef<Type> members, bool packed,
658 mlir::Type padding,
659 ArrayRef<RecordMemberKind> memberKinds) {
660 if (auto s = mlir::dyn_cast<StructType>(*this)) {
661 assert(!padding && "only a union takes a separate padding slot");
662 return s.complete(members, packed, memberKinds);
663 }
664 return mlir::cast<UnionType>(*this).complete(members, packed, padding,
665 memberKinds);
666}
667uint64_t RecordType::getElementOffset(const mlir::DataLayout &dataLayout,
668 unsigned idx) const {
669 if (mlir::isa<UnionType>(*this))
670 return 0;
671 return mlir::cast<StructType>(*this).getElementOffset(dataLayout, idx);
672}
674 if (auto s = mlir::dyn_cast<StructType>(*this)) {
675 if (auto so = mlir::dyn_cast<StructType>(other))
676 return s.isLayoutIdentical(so);
677 return false;
678 }
679 if (auto u = mlir::dyn_cast<UnionType>(*this)) {
680 if (auto uo = mlir::dyn_cast<UnionType>(other))
681 return u.isLayoutIdentical(uo);
682 return false;
683 }
684 return false;
685}
687 if (auto s = mlir::dyn_cast<StructType>(*this))
688 return s.isABIConvertedRecord();
689 return mlir::cast<UnionType>(*this).isABIConvertedRecord();
690}
691mlir::StringAttr RecordType::getABIConvertedName() const {
692 if (auto s = mlir::dyn_cast<StructType>(*this))
693 return s.getABIConvertedName();
694 return mlir::cast<UnionType>(*this).getABIConvertedName();
695}
697 if (auto s = mlir::dyn_cast<StructType>(*this))
698 return s.removeABIConversionNamePrefix();
699 return mlir::cast<UnionType>(*this).removeABIConversionNamePrefix();
700}
701
703 // An incomplete record has no members yet, which must not read as vacuously
704 // holding no data.
705 if (isIncomplete())
706 return false;
708 return false;
709 // An access unit of nothing but unnamed bit-fields is marked `empty`, since
710 // no field of the source reads it, but it is still storage that holds data
711 // for the ABI. This has to answer the way CIRGen's isEmptyFieldForABI does,
712 // which is where that rule lives.
713 return llvm::none_of(getMembers(), [](mlir::Type memberTy) {
714 auto bfTy = mlir::dyn_cast<cir::BitFieldType>(memberTy);
715 return bfTy && bfTy.ownsBytes();
716 });
717}
718
719//===----------------------------------------------------------------------===//
720// Data Layout information for types
721//===----------------------------------------------------------------------===//
722
723// The cir.ptr data-layout entry holds a #cir.ptr_spec attribute (see
724// cir::setMLIRDataLayout).
725namespace {
726constexpr static uint64_t kBitsInByte = 8;
727
728// Defaults used when the module carries no cir.ptr data-layout entry.
729constexpr static uint64_t kDefaultPointerSizeBits = 64;
730constexpr static uint64_t kDefaultPointerAlignment = 8;
731
732/// Returns the default-address-space #cir.ptr_spec entry, or a synthesized
733/// 64-bit default when there is none. Per-AS entries are not modeled yet.
734cir::PtrSpecAttr getPointerSpec(mlir::DataLayoutEntryListRef params,
735 cir::PointerType type) {
736 // FIXME: improve this in face of address spaces
738 for (mlir::DataLayoutEntryInterface entry : params) {
739 if (!entry.isTypeEntry())
740 continue;
741 auto key =
742 mlir::cast<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey()));
743 if (key.getAddrSpace())
744 continue;
745 if (auto spec = mlir::dyn_cast<cir::PtrSpecAttr>(entry.getValue()))
746 return spec;
747 }
748 return cir::PtrSpecAttr::get(type.getContext(), kDefaultPointerSizeBits,
749 kDefaultPointerAlignment * kBitsInByte,
750 kDefaultPointerAlignment * kBitsInByte,
751 kDefaultPointerSizeBits);
752}
753} // namespace
754
755llvm::TypeSize
756PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
757 ::mlir::DataLayoutEntryListRef params) const {
758 return llvm::TypeSize::getFixed(getPointerSpec(params, *this).getSize());
759}
760
762PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
763 ::mlir::DataLayoutEntryListRef params) const {
764 return getPointerSpec(params, *this).getAbi() / kBitsInByte;
765}
766
767uint64_t PointerType::getPreferredAlignment(
768 const ::mlir::DataLayout &dataLayout,
769 ::mlir::DataLayoutEntryListRef params) const {
770 return getPointerSpec(params, *this).getPreferred() / kBitsInByte;
771}
772
773std::optional<uint64_t>
774PointerType::getIndexBitwidth(const ::mlir::DataLayout &dataLayout,
775 ::mlir::DataLayoutEntryListRef params) const {
776 cir::PtrSpecAttr spec = getPointerSpec(params, *this);
777 if (spec.getIndex() == cir::PtrSpecAttr::kOptionalSpecValue)
778 return spec.getSize();
779 return spec.getIndex();
780}
781
782llvm::LogicalResult
783PointerType::verifyEntries(mlir::DataLayoutEntryListRef entries,
784 mlir::Location loc) const {
785 for (mlir::DataLayoutEntryInterface entry : entries) {
786 if (!entry.isTypeEntry())
787 continue;
788 auto key = mlir::cast<PointerType>(mlir::cast<mlir::Type>(entry.getKey()));
789 if (!mlir::isa<cir::PtrSpecAttr>(entry.getValue()))
790 return mlir::emitError(loc) << "expected layout attribute for " << key
791 << " to be a #cir.ptr_spec attribute";
792 if (!mlir::isa<cir::VoidType>(key.getPointee()))
793 return mlir::emitError(loc) << "expected !cir.ptr data layout entry for "
794 << key << " to use !cir.void as pointee";
795 // Per-address-space pointer layouts are not supported yet.
796 if (key.getAddrSpace())
797 return mlir::emitError(loc)
798 << "!cir.ptr data layout entries are currently limited to the "
799 "default address space";
800 }
801 return mlir::success();
802}
803
804bool PointerType::areCompatible(
805 mlir::DataLayoutEntryListRef oldLayout,
806 mlir::DataLayoutEntryListRef newLayout, mlir::DataLayoutSpecInterface,
807 const mlir::DataLayoutIdentifiedEntryMap &) const {
808 // A nested spec may only override with the same size and a compatible ABI
809 // alignment. TODO(cir): match by address space once per-AS specs exist.
810 cir::PtrSpecAttr oldSpec = getPointerSpec(oldLayout, *this);
811 uint64_t size = oldSpec.getSize();
812 uint64_t abi = oldSpec.getAbi();
813 for (mlir::DataLayoutEntryInterface newEntry : newLayout) {
814 if (!newEntry.isTypeEntry())
815 continue;
816 auto newSpec = mlir::cast<cir::PtrSpecAttr>(newEntry.getValue());
817 if (size != newSpec.getSize() || abi < newSpec.getAbi() ||
818 abi % newSpec.getAbi() != 0)
819 return false;
820 }
821 return true;
822}
823
824llvm::TypeSize
825StructType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
826 mlir::DataLayoutEntryListRef params) const {
827 auto recordSize = static_cast<uint64_t>(computeStructSize(dataLayout));
828 return llvm::TypeSize::getFixed(recordSize * 8);
829}
830
832StructType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
833 ::mlir::DataLayoutEntryListRef params) const {
834 // Packed structures always have an ABI alignment of 1.
835 if (getPacked())
836 return 1;
837 return computeStructAlignment(dataLayout);
838}
839
840// Sums the storage member (if present) with the padding field (if present).
841// A union whose member list came out empty has no storage type, so its whole
842// size lives in the padding, which lowerUnion sizes from the ASTRecordLayout.
843llvm::TypeSize
844UnionType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
845 mlir::DataLayoutEntryListRef params) const {
846 llvm::TypeSize size = llvm::TypeSize::getFixed(0);
847 if (mlir::Type storage = getUnionStorageType(dataLayout))
848 size += dataLayout.getTypeSizeInBits(storage);
849 if (mlir::Type pad = getPadding())
850 size += dataLayout.getTypeSizeInBits(pad);
851 return size;
852}
853
855UnionType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
856 ::mlir::DataLayoutEntryListRef params) const {
857 if (getPacked())
858 return 1;
859 mlir::Type storage = getUnionStorageType(dataLayout);
860 if (!storage)
861 return 1;
862 return dataLayout.getTypeABIAlignment(storage);
863}
864
865unsigned
866StructType::computeStructSize(const mlir::DataLayout &dataLayout) const {
867 assert(isComplete() && "Cannot get layout of incomplete records");
868
869 // This is a similar algorithm to LLVM's StructLayout. A member that owns no
870 // bytes needs no special case: it reports size 0 and alignment 1, so the
871 // running size passes over it unchanged.
872 unsigned recordSize = 0;
873 uint64_t recordAlignment = 1;
874
875 for (mlir::Type ty : getMembers()) {
876 // This assumes that we're calculating size based on the ABI alignment, not
877 // the preferred alignment for each type.
878 const uint64_t tyAlign =
879 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
880
881 // Add padding to the struct size to align it to the abi alignment of the
882 // element type before adding the size of the element.
883 recordSize = llvm::alignTo(recordSize, tyAlign);
884 recordSize += dataLayout.getTypeSize(ty);
885
886 // The alignment requirement of a struct is equal to the strictest
887 // alignment requirement of its elements.
888 recordAlignment = std::max(tyAlign, recordAlignment);
889 }
890
891 // At the end, add padding to the struct to satisfy its own alignment
892 // requirement. Otherwise structs inside of arrays would be misaligned.
893 recordSize = llvm::alignTo(recordSize, recordAlignment);
894 return recordSize;
895}
896
897unsigned
898StructType::computeStructDataSize(const mlir::DataLayout &dataLayout) const {
899 assert(isComplete() && "Cannot get layout of incomplete records");
900
901 // Tail padding is the trailing run of pad members, which is what a derived
902 // class may reuse. A member that owns no bytes holds no storage, so it does
903 // not end that run. A member of any other kind stays inside the data size.
904 llvm::ArrayRef<mlir::Type> members = getMembers();
905 llvm::ArrayRef<RecordMemberKind> kinds = getMemberKinds();
906 assert(kinds.size() == members.size() &&
907 "the two drop_back calls below must stay in step");
908 while (!kinds.empty() && (kinds.back() == RecordMemberKind::Pad ||
909 !memberOwnsBytes(members.back()))) {
910 kinds = kinds.drop_back();
911 members = members.drop_back();
912 }
913
914 unsigned recordSize = 0;
915 for (mlir::Type ty : members) {
916 const uint64_t tyAlign =
917 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
918 recordSize = llvm::alignTo(recordSize, tyAlign);
919 recordSize += dataLayout.getTypeSize(ty);
920 }
921 return recordSize;
922}
923
924// We also compute the alignment as part of computeStructSize, but this is more
925// efficient. Ideally, we'd like to compute both at once and cache the result,
926// but that's not implemented yet.
927// TODO(CIR): Implement a way to cache the result.
929StructType::computeStructAlignment(const mlir::DataLayout &dataLayout) const {
930 assert(isComplete() && "Cannot get layout of incomplete records");
931
932 uint64_t recordAlignment = 1;
933 for (mlir::Type ty : getMembers())
934 recordAlignment =
935 std::max(dataLayout.getTypeABIAlignment(ty), recordAlignment);
936 return recordAlignment;
937}
938
939unsigned StructType::getLLVMFieldIndex(unsigned idx) const {
940 llvm::ArrayRef<mlir::Type> members = getMembers();
941 assert(idx < members.size() && "access not valid");
942 assert(memberOwnsBytes(members[idx]) &&
943 "a member that owns no bytes has no LLVM field");
944
945 unsigned llvmIdx = 0;
946 for (unsigned i = 0; i != idx; ++i)
947 if (memberOwnsBytes(members[i]))
948 ++llvmIdx;
949 return llvmIdx;
950}
951
952uint64_t StructType::getElementOffset(const ::mlir::DataLayout &dataLayout,
953 unsigned idx) const {
954 assert(idx < getMembers().size() && "access not valid");
955 if (idx == 0)
956 return 0;
957
958 assert(isComplete() && "Cannot get layout of incomplete records");
959 llvm::ArrayRef<mlir::Type> members = getMembers();
960
961 // A zero-width bit-field reports alignment 1 and size 0, so the running
962 // offset passes over it unchanged and lands on where the storage ahead of it
963 // ends, which is the offset it was declared at.
964 unsigned offset = 0;
965 for (unsigned i = 0; i != idx; ++i) {
966 const llvm::Align tyAlign = llvm::Align(
967 getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[i]));
968 offset = llvm::alignTo(offset, tyAlign);
969 offset += dataLayout.getTypeSize(members[i]);
970 }
971
972 const llvm::Align tyAlign = llvm::Align(
973 getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[idx]));
974 return llvm::alignTo(offset, tyAlign);
975}
976
977//===----------------------------------------------------------------------===//
978// IntType Definitions
979//===----------------------------------------------------------------------===//
980
981Type IntType::parse(mlir::AsmParser &parser) {
982 mlir::MLIRContext *context = parser.getBuilder().getContext();
983 llvm::SMLoc loc = parser.getCurrentLocation();
984 bool isSigned;
985 unsigned width;
986
987 if (parser.parseLess())
988 return {};
989
990 // Fetch integer sign.
991 llvm::StringRef sign;
992 if (parser.parseKeyword(&sign))
993 return {};
994 if (sign == "s")
995 isSigned = true;
996 else if (sign == "u")
997 isSigned = false;
998 else {
999 parser.emitError(loc, "expected 's' or 'u'");
1000 return {};
1001 }
1002
1003 if (parser.parseComma())
1004 return {};
1005
1006 // Fetch integer size.
1007 if (parser.parseInteger(width))
1008 return {};
1009 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
1010 parser.emitError(loc, "expected integer width to be from ")
1011 << IntType::minBitwidth() << " up to " << IntType::maxBitwidth();
1012 return {};
1013 }
1014
1015 bool isBitInt = false;
1016 if (succeeded(parser.parseOptionalComma())) {
1017 llvm::StringRef kw;
1018 if (parser.parseKeyword(&kw) || kw != "bitint") {
1019 parser.emitError(loc, "expected 'bitint'");
1020 return {};
1021 }
1022 isBitInt = true;
1023 }
1024
1025 if (parser.parseGreater())
1026 return {};
1027
1028 return IntType::get(context, width, isSigned, isBitInt);
1029}
1030
1031void IntType::print(mlir::AsmPrinter &printer) const {
1032 char sign = isSigned() ? 's' : 'u';
1033 printer << '<' << sign << ", " << getWidth();
1034 if (isBitInt())
1035 printer << ", bitint";
1036 printer << '>';
1037}
1038
1039llvm::TypeSize
1040IntType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1041 mlir::DataLayoutEntryListRef params) const {
1042 return llvm::TypeSize::getFixed(getStorageTypeWidth(dataLayout));
1043}
1044
1045unsigned
1046IntType::getStorageTypeWidth(const mlir::DataLayout &dataLayout) const {
1047 if (!isBitInt())
1048 return getWidth();
1049 uint64_t alignBits = getABIAlignment(dataLayout, {}) * 8;
1050 return static_cast<unsigned>(llvm::alignTo(getWidth(), alignBits));
1051}
1052
1054IntType::getStorageTypeAlignment(const mlir::DataLayout &dataLayout) const {
1055 if (!isBitInt())
1056 return getABIAlignment(dataLayout, {});
1057 auto storageTy =
1058 mlir::IntegerType::get(getContext(), getStorageTypeWidth(dataLayout));
1059 return dataLayout.getTypeABIAlignment(storageTy);
1060}
1061
1062uint64_t IntType::getABIAlignment(const mlir::DataLayout &dataLayout,
1063 mlir::DataLayoutEntryListRef params) const {
1064 unsigned width = getWidth();
1065 if (isBitInt()) {
1066 // _BitInt alignment: min(PowerOf2Ceil(width), 64 bits) in bytes.
1067 // Matches Clang's TargetInfo::getBitIntAlign with default max = 64.
1068 uint64_t alignBits =
1069 std::min(llvm::PowerOf2Ceil(width), static_cast<uint64_t>(64));
1070 return std::max(alignBits / 8, static_cast<uint64_t>(1));
1071 }
1072 // Round up to a power-of-two byte alignment. DataLayout consumers such as
1073 // llvm::Align require power-of-two alignments, and width / 8 is not a power
1074 // of two for non-fundamental widths (e.g. i24 -> 3). This leaves the
1075 // fundamental widths unchanged (i8 -> 1, i16 -> 2, i32 -> 4, i64 -> 8) and
1076 // keeps __int128 at 16.
1077 uint64_t alignBits = llvm::PowerOf2Ceil(width);
1078 return std::max(alignBits / 8, static_cast<uint64_t>(1));
1079}
1080
1081mlir::LogicalResult
1082IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1083 unsigned width, bool isSigned, bool isBitInt) {
1084 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth())
1085 return emitError() << "IntType only supports widths from "
1086 << IntType::minBitwidth() << " up to "
1087 << IntType::maxBitwidth();
1088 return mlir::success();
1089}
1090
1092 return width == 8 || width == 16 || width == 32 || width == 64;
1093}
1094
1095//===----------------------------------------------------------------------===//
1096// Floating-point type definitions
1097//===----------------------------------------------------------------------===//
1098
1099const llvm::fltSemantics &SingleType::getFloatSemantics() const {
1100 return llvm::APFloat::IEEEsingle();
1101}
1102
1103llvm::TypeSize
1104SingleType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1105 mlir::DataLayoutEntryListRef params) const {
1106 return llvm::TypeSize::getFixed(getWidth());
1107}
1108
1110SingleType::getABIAlignment(const mlir::DataLayout &dataLayout,
1111 mlir::DataLayoutEntryListRef params) const {
1112 return (uint64_t)(getWidth() / 8);
1113}
1114
1115const llvm::fltSemantics &DoubleType::getFloatSemantics() const {
1116 return llvm::APFloat::IEEEdouble();
1117}
1118
1119llvm::TypeSize
1120DoubleType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1121 mlir::DataLayoutEntryListRef params) const {
1122 return llvm::TypeSize::getFixed(getWidth());
1123}
1124
1126DoubleType::getABIAlignment(const mlir::DataLayout &dataLayout,
1127 mlir::DataLayoutEntryListRef params) const {
1128 return (uint64_t)(getWidth() / 8);
1129}
1130
1131const llvm::fltSemantics &FP16Type::getFloatSemantics() const {
1132 return llvm::APFloat::IEEEhalf();
1133}
1134
1135llvm::TypeSize
1136FP16Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1137 mlir::DataLayoutEntryListRef params) const {
1138 return llvm::TypeSize::getFixed(getWidth());
1139}
1140
1141uint64_t FP16Type::getABIAlignment(const mlir::DataLayout &dataLayout,
1142 mlir::DataLayoutEntryListRef params) const {
1143 return (uint64_t)(getWidth() / 8);
1144}
1145
1146const llvm::fltSemantics &BF16Type::getFloatSemantics() const {
1147 return llvm::APFloat::BFloat();
1148}
1149
1150llvm::TypeSize
1151BF16Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1152 mlir::DataLayoutEntryListRef params) const {
1153 return llvm::TypeSize::getFixed(getWidth());
1154}
1155
1156uint64_t BF16Type::getABIAlignment(const mlir::DataLayout &dataLayout,
1157 mlir::DataLayoutEntryListRef params) const {
1158 return (uint64_t)(getWidth() / 8);
1159}
1160
1161const llvm::fltSemantics &FP80Type::getFloatSemantics() const {
1162 return llvm::APFloat::x87DoubleExtended();
1163}
1164
1165llvm::TypeSize
1166FP80Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1167 mlir::DataLayoutEntryListRef params) const {
1168 // Though only 80 bits are used for the value, the type is 128 bits in size.
1169 return llvm::TypeSize::getFixed(128);
1170}
1171
1172uint64_t FP80Type::getABIAlignment(const mlir::DataLayout &dataLayout,
1173 mlir::DataLayoutEntryListRef params) const {
1174 return 16;
1175}
1176
1177const llvm::fltSemantics &FP128Type::getFloatSemantics() const {
1178 return llvm::APFloat::IEEEquad();
1179}
1180
1181llvm::TypeSize
1182FP128Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1183 mlir::DataLayoutEntryListRef params) const {
1184 return llvm::TypeSize::getFixed(getWidth());
1185}
1186
1187uint64_t FP128Type::getABIAlignment(const mlir::DataLayout &dataLayout,
1188 mlir::DataLayoutEntryListRef params) const {
1189 return 16;
1190}
1191
1192const llvm::fltSemantics &LongDoubleType::getFloatSemantics() const {
1193 return mlir::cast<cir::FPTypeInterface>(getUnderlying()).getFloatSemantics();
1194}
1195
1196llvm::TypeSize
1197LongDoubleType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1198 mlir::DataLayoutEntryListRef params) const {
1199 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
1200 .getTypeSizeInBits(dataLayout, params);
1201}
1202
1204LongDoubleType::getABIAlignment(const mlir::DataLayout &dataLayout,
1205 mlir::DataLayoutEntryListRef params) const {
1206 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
1207 .getABIAlignment(dataLayout, params);
1208}
1209
1210//===----------------------------------------------------------------------===//
1211// ComplexType Definitions
1212//===----------------------------------------------------------------------===//
1213
1214llvm::TypeSize
1215cir::ComplexType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1216 mlir::DataLayoutEntryListRef params) const {
1217 // C17 6.2.5p13:
1218 // Each complex type has the same representation and alignment requirements
1219 // as an array type containing exactly two elements of the corresponding
1220 // real type.
1221
1222 return dataLayout.getTypeSizeInBits(getElementType()) * 2;
1223}
1224
1226cir::ComplexType::getABIAlignment(const mlir::DataLayout &dataLayout,
1227 mlir::DataLayoutEntryListRef params) const {
1228 // C17 6.2.5p13:
1229 // Each complex type has the same representation and alignment requirements
1230 // as an array type containing exactly two elements of the corresponding
1231 // real type.
1232
1233 return dataLayout.getTypeABIAlignment(getElementType());
1234}
1235
1236FuncType FuncType::clone(TypeRange inputs, TypeRange results) const {
1237 assert(results.size() == 1 && "expected exactly one result type");
1238 return get(llvm::to_vector(inputs), results[0], isVarArg());
1239}
1240
1241// Custom parser that parses function parameters of form `(<type>*, ...)`.
1242static mlir::ParseResult
1244 bool &isVarArg) {
1245 isVarArg = false;
1246 return p.parseCommaSeparatedList(
1247 AsmParser::Delimiter::Paren, [&]() -> mlir::ParseResult {
1248 if (isVarArg)
1249 return p.emitError(p.getCurrentLocation(),
1250 "variadic `...` must be the last parameter");
1251 if (succeeded(p.parseOptionalEllipsis())) {
1252 isVarArg = true;
1253 return success();
1254 }
1255 mlir::Type type;
1256 if (failed(p.parseType(type)))
1257 return failure();
1258 params.push_back(type);
1259 return success();
1260 });
1261}
1262
1263static void printFuncTypeParams(mlir::AsmPrinter &p,
1264 mlir::ArrayRef<mlir::Type> params,
1265 bool isVarArg) {
1266 p << '(';
1267 llvm::interleaveComma(params, p,
1268 [&p](mlir::Type type) { p.printType(type); });
1269 if (isVarArg) {
1270 if (!params.empty())
1271 p << ", ";
1272 p << "...";
1273 }
1274 p << ')';
1275}
1276
1277/// Get the C-style return type of the function, which is !cir.void if the
1278/// function returns nothing and the actual return type otherwise.
1279mlir::Type FuncType::getReturnType() const {
1280 if (hasVoidReturn())
1281 return cir::VoidType::get(getContext());
1282 return getOptionalReturnType();
1283}
1284
1285/// Get the MLIR-style return type of the function, which is an empty
1286/// ArrayRef if the function returns nothing and a single-element ArrayRef
1287/// with the actual return type otherwise.
1288llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes() const {
1289 if (hasVoidReturn())
1290 return {};
1291 // Can't use getOptionalReturnType() here because llvm::ArrayRef hold a
1292 // pointer to its elements and doesn't do lifetime extension. That would
1293 // result in returning a pointer to a temporary that has gone out of scope.
1294 return getImpl()->optionalReturnType;
1295}
1296
1297// Does the fuction type return nothing?
1298bool FuncType::hasVoidReturn() const { return !getOptionalReturnType(); }
1299
1300mlir::LogicalResult
1301FuncType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1302 llvm::ArrayRef<mlir::Type> argTypes, mlir::Type returnType,
1303 bool isVarArg) {
1304 if (mlir::isa_and_nonnull<cir::VoidType>(returnType))
1305 return emitError()
1306 << "!cir.func cannot have an explicit 'void' return type";
1307
1308 // The calling convention lowering pass expects all types in a function
1309 // signature to be CIR types.
1310 for (mlir::Type type : argTypes) {
1311 if (!isPureCIRType(type))
1312 return emitError()
1313 << "expected all types in the function signature to be CIR types";
1314 }
1315 if (!isPureCIRType(returnType))
1316 return emitError()
1317 << "expected all types in the function signature to be CIR types";
1318
1319 return mlir::success();
1320}
1321
1322//===----------------------------------------------------------------------===//
1323// MethodType Definitions
1324//===----------------------------------------------------------------------===//
1325
1326static mlir::Type getMethodLayoutType(mlir::MLIRContext *ctx) {
1327 // With Itanium ABI, member function pointers have the same layout as the
1328 // following struct: struct { fnptr_t, ptrdiff_t }, where fnptr_t is a
1329 // function pointer type.
1330 // TODO: consider member function pointer layout in other ABIs
1331 auto voidPtrTy = cir::PointerType::get(cir::VoidType::get(ctx));
1332 mlir::Type fields[2]{voidPtrTy, voidPtrTy};
1333 return cir::StructType::get(ctx, fields, /*packed=*/false,
1334 /*is_class=*/false,
1336}
1337
1338llvm::TypeSize
1339MethodType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1340 mlir::DataLayoutEntryListRef params) const {
1341 return dataLayout.getTypeSizeInBits(getMethodLayoutType(getContext()));
1342}
1343
1345MethodType::getABIAlignment(const mlir::DataLayout &dataLayout,
1346 mlir::DataLayoutEntryListRef params) const {
1347 return cast<cir::StructType>(getMethodLayoutType(getContext()))
1348 .getABIAlignment(dataLayout, params);
1349}
1350
1351//===----------------------------------------------------------------------===//
1352// BoolType
1353//===----------------------------------------------------------------------===//
1354
1355llvm::TypeSize
1356BoolType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
1357 ::mlir::DataLayoutEntryListRef params) const {
1358 return llvm::TypeSize::getFixed(8);
1359}
1360
1362BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1363 ::mlir::DataLayoutEntryListRef params) const {
1364 return 1;
1365}
1366
1367//===----------------------------------------------------------------------===//
1368// DataMemberType Definitions
1369//===----------------------------------------------------------------------===//
1370
1371static mlir::Type getDataMemberLayoutType(const mlir::DataLayout &dataLayout,
1372 mlir::MLIRContext *ctx) {
1373 // Itanium ABI: a data member pointer is a ptrdiff_t, an integer of the
1374 // pointer index width.
1375 // TODO: consider data member pointer layout in other ABIs
1376 auto voidPtrTy = cir::PointerType::get(cir::VoidType::get(ctx));
1377 uint64_t width = dataLayout.getTypeIndexBitwidth(voidPtrTy).value_or(
1378 dataLayout.getTypeSizeInBits(voidPtrTy).getFixedValue());
1379 return cir::IntType::get(ctx, width, /*is_signed=*/true);
1380}
1381
1382llvm::TypeSize
1383DataMemberType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
1384 ::mlir::DataLayoutEntryListRef params) const {
1385 assert(!MissingFeatures::cxxABI());
1386 return dataLayout.getTypeSizeInBits(
1387 getDataMemberLayoutType(dataLayout, getContext()));
1388}
1389
1391DataMemberType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1392 ::mlir::DataLayoutEntryListRef params) const {
1393 assert(!MissingFeatures::cxxABI());
1394 return dataLayout.getTypeABIAlignment(
1395 getDataMemberLayoutType(dataLayout, getContext()));
1396}
1397
1398//===----------------------------------------------------------------------===//
1399// VPtrType Definitions
1400//===----------------------------------------------------------------------===//
1401
1402llvm::TypeSize
1403VPtrType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1404 mlir::DataLayoutEntryListRef params) const {
1405 // A vtable pointer is an ordinary data pointer; size it as a cir.ptr.
1406 return dataLayout.getTypeSizeInBits(
1407 cir::PointerType::get(cir::VoidType::get(getContext())));
1408}
1409
1410uint64_t VPtrType::getABIAlignment(const mlir::DataLayout &dataLayout,
1411 mlir::DataLayoutEntryListRef params) const {
1412 return dataLayout.getTypeABIAlignment(
1413 cir::PointerType::get(cir::VoidType::get(getContext())));
1414}
1415
1416//===----------------------------------------------------------------------===//
1417// ArrayType Definitions
1418//===----------------------------------------------------------------------===//
1419
1420llvm::TypeSize
1421ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
1422 ::mlir::DataLayoutEntryListRef params) const {
1423 return getSize() * dataLayout.getTypeSizeInBits(getElementType());
1424}
1425
1427ArrayType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1428 ::mlir::DataLayoutEntryListRef params) const {
1429 return dataLayout.getTypeABIAlignment(getElementType());
1430}
1431
1432//===----------------------------------------------------------------------===//
1433// BitFieldType Definitions
1434//===----------------------------------------------------------------------===//
1435
1436mlir::LogicalResult
1437BitFieldType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1438 mlir::Type storageType,
1439 llvm::ArrayRef<cir::BitFieldDeclAttr> fields) {
1440 if (fields.empty())
1441 return emitError() << "bit-field member must hold at least one bit-field";
1442
1443 if (!storageType) {
1444 // Absent storage is the zero-width bit-field, which belongs to no access
1445 // unit and so keeps company with nothing.
1446 if (fields.size() != 1 || fields.front().getWidth() != 0)
1447 return emitError() << "a bit-field member without storage must hold a "
1448 "single zero-width bit-field";
1449 return mlir::success();
1450 }
1451
1452 if (mlir::isa<cir::BitFieldType>(storageType))
1453 return emitError() << "bit-field access unit storage cannot itself be a "
1454 "bit-field type";
1455
1456 if (!cir::isSized(storageType))
1457 return emitError() << "bit-field access unit storage must be sized, got "
1458 << storageType;
1459
1460 // A zero-width bit-field ends the run before it rather than joining a unit,
1461 // so it never appears alongside the fields that occupy one.
1462 if (llvm::any_of(fields, [](cir::BitFieldDeclAttr decl) {
1463 return decl.getWidth() == 0;
1464 }))
1465 return emitError() << "a zero-width bit-field cannot occupy an access unit";
1466
1467 return mlir::success();
1468}
1469
1470llvm::TypeSize
1471BitFieldType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
1472 mlir::DataLayoutEntryListRef params) const {
1473 // A unit is stored as its storage type. A zero-width bit-field has none,
1474 // and holds no bits of its own.
1475 if (mlir::Type storage = getStorageType())
1476 return dataLayout.getTypeSizeInBits(storage);
1477 return llvm::TypeSize::getFixed(0);
1478}
1479
1481BitFieldType::getABIAlignment(const mlir::DataLayout &dataLayout,
1482 mlir::DataLayoutEntryListRef params) const {
1483 // A member that occupies no bytes imposes no alignment, which is what lets
1484 // the record layout walk a zero-width bit-field without skipping it.
1485 if (mlir::Type storage = getStorageType())
1486 return dataLayout.getTypeABIAlignment(storage);
1487 return 1;
1488}
1489
1490//===----------------------------------------------------------------------===//
1491// VectorType Definitions
1492//===----------------------------------------------------------------------===//
1493
1494llvm::TypeSize cir::VectorType::getTypeSizeInBits(
1495 const ::mlir::DataLayout &dataLayout,
1496 ::mlir::DataLayoutEntryListRef params) const {
1497 return llvm::TypeSize::getFixed(
1498 getSize() * dataLayout.getTypeSizeInBits(getElementType()));
1499}
1500
1502cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
1503 ::mlir::DataLayoutEntryListRef params) const {
1504 // This hook answers in bytes, not bits.
1505 return llvm::PowerOf2Ceil(
1506 llvm::divideCeil(dataLayout.getTypeSizeInBits(*this), 8u));
1507}
1508
1509mlir::LogicalResult cir::VectorType::verify(
1510 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1511 mlir::Type elementType, uint64_t size, bool scalable) {
1512 if (size == 0)
1513 return emitError() << "the number of vector elements must be non-zero";
1514 return success();
1515}
1516
1517mlir::Type cir::VectorType::parse(::mlir::AsmParser &odsParser) {
1518
1519 llvm::SMLoc odsLoc = odsParser.getCurrentLocation();
1520 mlir::Builder odsBuilder(odsParser.getContext());
1521 mlir::FailureOr<::mlir::Type> elementType;
1522 mlir::FailureOr<uint64_t> size;
1523 bool isScalabe = false;
1524
1525 // Parse literal '<'
1526 if (odsParser.parseLess())
1527 return {};
1528
1529 // Parse literal '[', if present, and set the scalability flag accordingly
1530 if (odsParser.parseOptionalLSquare().succeeded())
1531 isScalabe = true;
1532
1533 // Parse variable 'size'
1534 size = mlir::FieldParser<uint64_t>::parse(odsParser);
1535 if (mlir::failed(size)) {
1536 odsParser.emitError(odsParser.getCurrentLocation(),
1537 "failed to parse CIR_VectorType parameter 'size' which "
1538 "is to be a `uint64_t`");
1539 return {};
1540 }
1541
1542 // Parse literal ']', which is expected when dealing with scalable
1543 // dim sizes
1544 if (isScalabe && odsParser.parseRSquare().failed()) {
1545 odsParser.emitError(odsParser.getCurrentLocation(),
1546 "missing closing `]` for scalable dim size");
1547 return {};
1548 }
1549
1550 // Parse literal 'x'
1551 if (odsParser.parseKeyword("x"))
1552 return {};
1553
1554 // Parse variable 'elementType'
1555 elementType = mlir::FieldParser<::mlir::Type>::parse(odsParser);
1556 if (mlir::failed(elementType)) {
1557 odsParser.emitError(odsParser.getCurrentLocation(),
1558 "failed to parse CIR_VectorType parameter "
1559 "'elementType' which is to be a `mlir::Type`");
1560 return {};
1561 }
1562
1563 // Parse literal '>'
1564 if (odsParser.parseGreater())
1565 return {};
1566 return odsParser.getChecked<VectorType>(odsLoc, odsParser.getContext(),
1567 mlir::Type((*elementType)),
1568 uint64_t((*size)), isScalabe);
1569}
1570
1571void cir::VectorType::print(mlir::AsmPrinter &odsPrinter) const {
1572 mlir::Builder odsBuilder(getContext());
1573 odsPrinter << "<";
1574 if (this->getIsScalable())
1575 odsPrinter << "[";
1576
1577 odsPrinter.printStrippedAttrOrType(getSize());
1578 if (this->getIsScalable())
1579 odsPrinter << "]";
1580 odsPrinter << ' ' << "x";
1581 odsPrinter << ' ';
1582 odsPrinter.printStrippedAttrOrType(getElementType());
1583 odsPrinter << ">";
1584}
1585
1586//===----------------------------------------------------------------------===//
1587// AddressSpace definitions
1588//===----------------------------------------------------------------------===//
1589
1591 mlir::ptr::MemorySpaceAttrInterface memorySpace) {
1592 return mlir::isa<cir::LangAddressSpaceAttr, cir::TargetAddressSpaceAttr>(
1593 memorySpace);
1594}
1595
1596cir::LangAddressSpace cir::toCIRLangAddressSpace(clang::LangAS langAS) {
1597 using clang::LangAS;
1598 switch (langAS) {
1599 case LangAS::Default:
1600 return LangAddressSpace::Default;
1601 case LangAS::opencl_global:
1602 return LangAddressSpace::OffloadGlobal;
1603 case LangAS::opencl_local:
1604 case LangAS::cuda_shared:
1605 // Local means local among the work-group (OpenCL) or block (CUDA).
1606 // All threads inside the kernel can access local memory.
1607 return LangAddressSpace::OffloadLocal;
1608 case LangAS::cuda_device:
1609 return LangAddressSpace::OffloadGlobal;
1610 case LangAS::opencl_constant:
1611 case LangAS::cuda_constant:
1612 return LangAddressSpace::OffloadConstant;
1613 case LangAS::opencl_private:
1614 return LangAddressSpace::OffloadPrivate;
1615 case LangAS::opencl_generic:
1616 return LangAddressSpace::OffloadGeneric;
1617 case LangAS::opencl_global_device:
1618 return LangAddressSpace::OffloadGlobalDevice;
1619 case LangAS::opencl_global_host:
1620 return LangAddressSpace::OffloadGlobalHost;
1621 case LangAS::sycl_global:
1622 case LangAS::sycl_global_device:
1623 case LangAS::sycl_global_host:
1624 case LangAS::sycl_local:
1625 case LangAS::sycl_private:
1626 case LangAS::ptr32_sptr:
1627 case LangAS::ptr32_uptr:
1628 case LangAS::ptr64:
1629 case LangAS::hlsl_groupshared:
1630 case LangAS::wasm_funcref:
1631 llvm_unreachable("NYI");
1632 default:
1633 llvm_unreachable("unknown/unsupported clang language address space");
1634 }
1635}
1636
1637mlir::ParseResult parseMemorySpace(mlir::AsmParser &p,
1638 mlir::ptr::MemorySpaceAttrInterface &attr) {
1639
1640 llvm::SMLoc loc = p.getCurrentLocation();
1641
1642 // Try to parse target address space first.
1643 attr = nullptr;
1644 if (p.parseOptionalKeyword("target_address_space").succeeded()) {
1645 unsigned val;
1646 if (p.parseLParen())
1647 return p.emitError(loc, "expected '(' after 'target_address_space'");
1648
1649 if (p.parseInteger(val))
1650 return p.emitError(loc, "expected target address space value");
1651
1652 if (p.parseRParen())
1653 return p.emitError(loc, "expected ')'");
1654
1655 attr = cir::TargetAddressSpaceAttr::get(p.getContext(), val);
1656 return mlir::success();
1657 }
1658
1659 // Try to parse language specific address space.
1660 if (p.parseOptionalKeyword("lang_address_space").succeeded()) {
1661 if (p.parseLParen())
1662 return p.emitError(loc, "expected '(' after 'lang_address_space'");
1663
1664 mlir::FailureOr<cir::LangAddressSpace> result =
1665 mlir::FieldParser<cir::LangAddressSpace>::parse(p);
1666 if (mlir::failed(result))
1667 return mlir::failure();
1668
1669 if (p.parseRParen())
1670 return p.emitError(loc, "expected ')'");
1671
1672 attr = cir::LangAddressSpaceAttr::get(p.getContext(), result.value());
1673 return mlir::success();
1674 }
1675
1676 llvm::StringRef keyword;
1677 if (p.parseOptionalKeyword(&keyword).succeeded())
1678 return p.emitError(loc, "unknown address space specifier '")
1679 << keyword << "'; expected 'target_address_space' or "
1680 << "'lang_address_space'";
1681
1682 return mlir::success();
1683}
1684
1685void printMemorySpace(mlir::AsmPrinter &p,
1686 mlir::ptr::MemorySpaceAttrInterface attr) {
1687 if (!attr)
1688 return;
1689
1690 if (auto language = dyn_cast<cir::LangAddressSpaceAttr>(attr)) {
1691 p << "lang_address_space("
1692 << cir::stringifyLangAddressSpace(language.getValue()) << ')';
1693 return;
1694 }
1695
1696 if (auto target = dyn_cast<cir::TargetAddressSpaceAttr>(attr)) {
1697 p << "target_address_space(" << target.getValue() << ')';
1698 return;
1699 }
1700
1701 llvm_unreachable("unexpected address-space attribute kind");
1702}
1703
1704mlir::OptionalParseResult
1705parseGlobalMemorySpace(mlir::AsmParser &p,
1706 mlir::ptr::MemorySpaceAttrInterface &attr) {
1707
1708 mlir::SMLoc loc = p.getCurrentLocation();
1709 if (parseMemorySpace(p, attr).failed())
1710 return p.emitError(loc, "failed to parse Address Space Value for GlobalOp");
1711 return mlir::success();
1712}
1713
1714void printGlobalMemorySpace(mlir::AsmPrinter &printer, cir::GlobalOp,
1715 mlir::ptr::MemorySpaceAttrInterface attr) {
1716 printMemorySpace(printer, attr);
1717}
1718
1719mlir::ptr::MemorySpaceAttrInterface cir::normalizeDefaultAddressSpace(
1720 mlir::ptr::MemorySpaceAttrInterface addrSpace) {
1721 if (auto langAS =
1722 mlir::dyn_cast_if_present<cir::LangAddressSpaceAttr>(addrSpace))
1723 if (langAS.getValue() == cir::LangAddressSpace::Default)
1724 return {};
1725 return addrSpace;
1726}
1727
1728mlir::ptr::MemorySpaceAttrInterface
1729cir::toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS) {
1730 using clang::LangAS;
1731
1732 if (langAS == LangAS::Default)
1733 return cir::LangAddressSpaceAttr::get(&ctx, cir::LangAddressSpace::Default);
1734
1735 if (clang::isTargetAddressSpace(langAS)) {
1736 unsigned targetAS = clang::toTargetAddressSpace(langAS);
1737 return cir::TargetAddressSpaceAttr::get(&ctx, targetAS);
1738 }
1739
1740 return cir::LangAddressSpaceAttr::get(&ctx, toCIRLangAddressSpace(langAS));
1741}
1742
1743bool cir::isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS,
1744 clang::LangAS as) {
1745 cirAS = normalizeDefaultAddressSpace(cirAS);
1746 if (!cirAS)
1747 return as == clang::LangAS::Default;
1748 mlir::ptr::MemorySpaceAttrInterface expected = normalizeDefaultAddressSpace(
1749 toCIRAddressSpaceAttr(*cirAS.getContext(), as));
1750 return expected == cirAS;
1751}
1752
1753//===----------------------------------------------------------------------===//
1754// PointerType Definitions
1755//===----------------------------------------------------------------------===//
1756
1757mlir::LogicalResult cir::PointerType::verify(
1758 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1759 mlir::Type pointee, mlir::ptr::MemorySpaceAttrInterface addrSpace) {
1760 if (addrSpace) {
1761 if (!isSupportedCIRMemorySpaceAttr(addrSpace)) {
1762 return emitError() << "unsupported address space attribute; expected "
1763 "'target_address_space' or 'lang_address_space'";
1764 }
1765 }
1766
1767 return success();
1768}
1769
1770//===----------------------------------------------------------------------===//
1771// CIR Dialect
1772//===----------------------------------------------------------------------===//
1773
1774void CIRDialect::registerTypes() {
1775 // Register tablegen'd types.
1776 addTypes<
1777#define GET_TYPEDEF_LIST
1778#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
1779 >();
1780
1781 // Register raw C++ types.
1782 // TODO(CIR) addTypes<RecordType>();
1783}
Provides definitions for the various language-specific address spaces.
mlir::OptionalParseResult parseGlobalMemorySpace(mlir::AsmParser &p, mlir::ptr::MemorySpaceAttrInterface &attr)
void printGlobalMemorySpace(mlir::AsmPrinter &printer, cir::GlobalOp op, mlir::ptr::MemorySpaceAttrInterface attr)
mlir::ParseResult parseMemorySpace(mlir::AsmParser &p, mlir::ptr::MemorySpaceAttrInterface &attr)
static const llvm::StringRef memberKindMarks[]
The keywords that spell a member kind.
Definition CIRTypes.cpp:181
static void printRecordBody(mlir::AsmPrinter &printer, RecordTy self, mlir::StringAttr name, bool hasClassPrefix, bool isPacked, bool isIncomplete, llvm::ArrayRef< mlir::Type > members, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > memberKinds)
Print a complete CIR record body: '<' ['class '] [name] ['packed '] body '>' where body is "incomplet...
Definition CIRTypes.cpp:224
static mlir::LogicalResult verifyRecordMemberKinds(function_ref< mlir::InFlightDiagnostic()> emitError, size_t numMembers, llvm::ArrayRef< RecordMemberKind > memberKinds)
An incomplete record has no members, so a kind for one is caught by the same check.
Definition CIRTypes.cpp:170
static mlir::ParseResult parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector< mlir::Type > &params, bool &isVarArg)
void printMemorySpace(mlir::AsmPrinter &printer, mlir::ptr::MemorySpaceAttrInterface attr)
static bool isPureCIRType(mlir::Type ty)
Definition CIRTypes.cpp:64
static mlir::Type getMethodLayoutType(mlir::MLIRContext *ctx)
static void printFuncTypeParams(mlir::AsmPrinter &p, mlir::ArrayRef< mlir::Type > params, bool isVarArg)
static mlir::ParseResult parseRecordBody(mlir::AsmParser &parser, bool &incomplete, llvm::SmallVector< mlir::Type > &members, llvm::SmallVectorImpl< RecordMemberKind > &memberKinds)
Parse "incomplete" or "{mark type, mark type, ...}", writing results into incomplete,...
Definition CIRTypes.cpp:200
static std::optional< RecordMemberKind > parseMemberKind(mlir::AsmParser &parser)
Definition CIRTypes.cpp:185
static mlir::Type getDataMemberLayoutType(const mlir::DataLayout &dataLayout, mlir::MLIRContext *ctx)
static LiveVariablesImpl & getImpl(void *x)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
bool isLayoutIdentical(const RecordType &other)
Definition CIRTypes.cpp:673
bool isABIConvertedRecord() const
Definition CIRTypes.cpp:686
bool isIncomplete() const
Definition CIRTypes.cpp:619
bool isEmptyForABI() const
Whether no member holds data.
Definition CIRTypes.cpp:702
std::string getPrefixedName() const
Definition CIRTypes.cpp:654
llvm::ArrayRef< mlir::Type > getMembers() const
Definition CIRTypes.cpp:609
bool isClass() const
Definition CIRTypes.cpp:639
void removeABIConversionNamePrefix()
Definition CIRTypes.cpp:696
bool getPacked() const
Definition CIRTypes.cpp:624
static llvm::SmallVector< RecordMemberKind > getAllDataKinds(llvm::ArrayRef< mlir::Type > members)
One Data kind per member.
Definition CIRTypes.cpp:162
RecordType(StructType t)
Definition CIRTypes.h:157
mlir::StringAttr getName() const
Definition CIRTypes.cpp:614
void complete(llvm::ArrayRef< mlir::Type > members, bool packed, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > memberKinds)
padding is union-only.
Definition CIRTypes.cpp:657
mlir::StringAttr getABIConvertedName() const
Definition CIRTypes.cpp:691
std::string getKindAsStr() const
Definition CIRTypes.cpp:649
bool isStruct() const
Definition CIRTypes.cpp:644
bool getPadded() const
Definition CIRTypes.cpp:629
llvm::ArrayRef< RecordMemberKind > getMemberKinds() const
Definition CIRTypes.cpp:634
uint64_t getElementOffset(const mlir::DataLayout &dataLayout, unsigned idx) const
Definition CIRTypes.cpp:667
bool isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS, clang::LangAS as)
cir::LangAddressSpace toCIRLangAddressSpace(clang::LangAS langAS)
mlir::Type memberStorageType(mlir::Type memberTy)
The storage a member is stored as: the access unit for a bit-field member, and the member type itself...
Definition CIRTypes.h:134
bool memberOwnsBytes(mlir::Type memberTy)
Whether a record member occupies bytes of its record.
Definition CIRTypes.h:125
bool isValidFundamentalIntWidth(unsigned width)
cir::FPTypeInterface getFloatingPointType(const llvm::fltSemantics &sem, mlir::MLIRContext *ctx)
Returns the CIR floating-point type for the given semantics, or a null type if CIR has no type for it...
Definition CIRTypes.cpp:42
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
bool anyMemberHoldsDataForABI(llvm::ArrayRef< RecordMemberKind > kinds)
Whether any member holds data for argument passing on its mark alone.
Definition CIRTypes.h:52
mlir::ptr::MemorySpaceAttrInterface normalizeDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace)
Normalize LangAddressSpace::Default to null (empty attribute).
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
Definition CIRTypes.cpp:35
bool isSupportedCIRMemorySpaceAttr(mlir::ptr::MemorySpaceAttrInterface memorySpace)
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
StringRef getName(const HeaderType T)
Definition HeaderFile.h:38
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
bool isTargetAddressSpace(LangAS AS)
unsigned toTargetAddressSpace(LangAS AS)
LangAS
Defines the address space values used by the address space qualifier of QualType.
unsigned long uint64_t
float __ovld __cnfn sign(float)
Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x = +0.0, or -1.0 if x < 0.
#define true
Definition stdbool.h:25
static bool unsizedTypes()
static bool dataLayoutPtrHandlingBasedOnLangAS()
static bool astRecordDeclAttr()