clang 22.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/IR/DialectImplementation.h"
19#include "llvm/ADT/TypeSwitch.h"
20
21//===----------------------------------------------------------------------===//
22// CIR Helpers
23//===----------------------------------------------------------------------===//
24bool cir::isSized(mlir::Type ty) {
25 if (auto sizedTy = mlir::dyn_cast<cir::SizedTypeInterface>(ty))
26 return sizedTy.isSized();
28 return false;
29}
30
31//===----------------------------------------------------------------------===//
32// CIR Custom Parser/Printer Signatures
33//===----------------------------------------------------------------------===//
34
35static mlir::ParseResult
36parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &params,
37 bool &isVarArg);
38static void printFuncTypeParams(mlir::AsmPrinter &p,
39 mlir::ArrayRef<mlir::Type> params,
40 bool isVarArg);
41
42//===----------------------------------------------------------------------===//
43// Get autogenerated stuff
44//===----------------------------------------------------------------------===//
45
46namespace cir {
47
48#include "clang/CIR/Dialect/IR/CIRTypeConstraints.cpp.inc"
49
50} // namespace cir
51
52#define GET_TYPEDEF_CLASSES
53#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
54
55using namespace mlir;
56using namespace cir;
57
58//===----------------------------------------------------------------------===//
59// General CIR parsing / printing
60//===----------------------------------------------------------------------===//
61
62Type CIRDialect::parseType(DialectAsmParser &parser) const {
63 llvm::SMLoc typeLoc = parser.getCurrentLocation();
64 llvm::StringRef mnemonic;
65 Type genType;
66
67 // Try to parse as a tablegen'd type.
68 OptionalParseResult parseResult =
69 generatedTypeParser(parser, &mnemonic, genType);
70 if (parseResult.has_value())
71 return genType;
72
73 // Type is not tablegen'd: try to parse as a raw C++ type.
74 return StringSwitch<function_ref<Type()>>(mnemonic)
75 .Case("record", [&] { return RecordType::parse(parser); })
76 .Default([&] {
77 parser.emitError(typeLoc) << "unknown CIR type: " << mnemonic;
78 return Type();
79 })();
80}
81
82void CIRDialect::printType(Type type, DialectAsmPrinter &os) const {
83 // Try to print as a tablegen'd type.
84 if (generatedTypePrinter(type, os).succeeded())
85 return;
86
87 // TODO(CIR) Attempt to print as a raw C++ type.
88 llvm::report_fatal_error("printer is missing a handler for this type");
89}
90
91//===----------------------------------------------------------------------===//
92// RecordType Definitions
93//===----------------------------------------------------------------------===//
94
95Type RecordType::parse(mlir::AsmParser &parser) {
96 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
97 const llvm::SMLoc loc = parser.getCurrentLocation();
98 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
99 bool packed = false;
100 bool padded = false;
101 RecordKind kind;
102 mlir::MLIRContext *context = parser.getContext();
103
104 if (parser.parseLess())
105 return {};
106
107 // TODO(cir): in the future we should probably separate types for different
108 // source language declarations such as cir.record and cir.union
109 if (parser.parseOptionalKeyword("struct").succeeded())
110 kind = RecordKind::Struct;
111 else if (parser.parseOptionalKeyword("union").succeeded())
112 kind = RecordKind::Union;
113 else if (parser.parseOptionalKeyword("class").succeeded())
114 kind = RecordKind::Class;
115 else {
116 parser.emitError(loc, "unknown record type");
117 return {};
118 }
119
120 mlir::StringAttr name;
121 parser.parseOptionalAttribute(name);
122
123 // Is a self reference: ensure referenced type was parsed.
124 if (name && parser.parseOptionalGreater().succeeded()) {
125 RecordType type = getChecked(eLoc, context, name, kind);
126 if (succeeded(parser.tryStartCyclicParse(type))) {
127 parser.emitError(loc, "invalid self-reference within record");
128 return {};
129 }
130 return type;
131 }
132
133 // Is a named record definition: ensure name has not been parsed yet.
134 if (name) {
135 RecordType type = getChecked(eLoc, context, name, kind);
136 cyclicParseGuard = parser.tryStartCyclicParse(type);
137 if (failed(cyclicParseGuard)) {
138 parser.emitError(loc, "record already defined");
139 return {};
140 }
141 }
142
143 if (parser.parseOptionalKeyword("packed").succeeded())
144 packed = true;
145
146 if (parser.parseOptionalKeyword("padded").succeeded())
147 padded = true;
148
149 // Parse record members or lack thereof.
150 bool incomplete = true;
151 llvm::SmallVector<mlir::Type> members;
152 if (parser.parseOptionalKeyword("incomplete").failed()) {
153 incomplete = false;
154 const auto delimiter = AsmParser::Delimiter::Braces;
155 const auto parseElementFn = [&parser, &members]() {
156 return parser.parseType(members.emplace_back());
157 };
158 if (parser.parseCommaSeparatedList(delimiter, parseElementFn).failed())
159 return {};
160 }
161
162 if (parser.parseGreater())
163 return {};
164
165 // Try to create the proper record type.
166 ArrayRef<mlir::Type> membersRef(members); // Needed for template deduction.
167 mlir::Type type = {};
168 if (name && incomplete) { // Identified & incomplete
169 type = getChecked(eLoc, context, name, kind);
170 } else if (!name && !incomplete) { // Anonymous & complete
171 type = getChecked(eLoc, context, membersRef, packed, padded, kind);
172 } else if (!incomplete) { // Identified & complete
173 type = getChecked(eLoc, context, membersRef, name, packed, padded, kind);
174 // If the record has a self-reference, its type already exists in a
175 // incomplete state. In this case, we must complete it.
176 if (mlir::cast<RecordType>(type).isIncomplete())
177 mlir::cast<RecordType>(type).complete(membersRef, packed, padded);
179 } else { // anonymous & incomplete
180 parser.emitError(loc, "anonymous records must be complete");
181 return {};
182 }
183
184 return type;
185}
186
187void RecordType::print(mlir::AsmPrinter &printer) const {
188 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrintGuard;
189 printer << '<';
190
191 switch (getKind()) {
192 case RecordKind::Struct:
193 printer << "struct ";
194 break;
195 case RecordKind::Union:
196 printer << "union ";
197 break;
198 case RecordKind::Class:
199 printer << "class ";
200 break;
201 }
202
203 if (getName())
204 printer << getName();
205
206 // Current type has already been printed: print as self reference.
207 cyclicPrintGuard = printer.tryStartCyclicPrint(*this);
208 if (failed(cyclicPrintGuard)) {
209 printer << '>';
210 return;
211 }
212
213 // Type not yet printed: continue printing the entire record.
214 printer << ' ';
215
216 if (getPacked())
217 printer << "packed ";
218
219 if (getPadded())
220 printer << "padded ";
221
222 if (isIncomplete()) {
223 printer << "incomplete";
224 } else {
225 printer << "{";
226 llvm::interleaveComma(getMembers(), printer);
227 printer << "}";
228 }
229
230 printer << '>';
231}
232
233mlir::LogicalResult
234RecordType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
235 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
236 bool incomplete, bool packed, bool padded,
237 RecordType::RecordKind kind) {
238 if (name && name.getValue().empty())
239 return emitError() << "identified records cannot have an empty name";
240 return mlir::success();
241}
242
243::llvm::ArrayRef<mlir::Type> RecordType::getMembers() const {
244 return getImpl()->members;
245}
246
247bool RecordType::isIncomplete() const { return getImpl()->incomplete; }
248
249mlir::StringAttr RecordType::getName() const { return getImpl()->name; }
250
251bool RecordType::getIncomplete() const { return getImpl()->incomplete; }
252
253bool RecordType::getPacked() const { return getImpl()->packed; }
254
255bool RecordType::getPadded() const { return getImpl()->padded; }
256
257cir::RecordType::RecordKind RecordType::getKind() const {
258 return getImpl()->kind;
259}
260
261void RecordType::complete(ArrayRef<Type> members, bool packed, bool padded) {
263 if (mutate(members, packed, padded).failed())
264 llvm_unreachable("failed to complete record");
265}
266
267/// Return the largest member of in the type.
268///
269/// Recurses into union members never returning a union as the largest member.
270Type RecordType::getLargestMember(const ::mlir::DataLayout &dataLayout) const {
271 assert(isUnion() && "Only call getLargestMember on unions");
272 llvm::ArrayRef<Type> members = getMembers();
273 // If the union is padded, we need to ignore the last member,
274 // which is the padding.
275 return *std::max_element(
276 members.begin(), getPadded() ? members.end() - 1 : members.end(),
277 [&](Type lhs, Type rhs) {
278 return dataLayout.getTypeABIAlignment(lhs) <
279 dataLayout.getTypeABIAlignment(rhs) ||
280 (dataLayout.getTypeABIAlignment(lhs) ==
281 dataLayout.getTypeABIAlignment(rhs) &&
282 dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
283 });
284}
285
286bool RecordType::isLayoutIdentical(const RecordType &other) {
287 if (getImpl() == other.getImpl())
288 return true;
289
290 if (getPacked() != other.getPacked())
291 return false;
292
293 return getMembers() == other.getMembers();
294}
295
296//===----------------------------------------------------------------------===//
297// Data Layout information for types
298//===----------------------------------------------------------------------===//
299
300llvm::TypeSize
301RecordType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
302 mlir::DataLayoutEntryListRef params) const {
303 if (isUnion())
304 return dataLayout.getTypeSize(getLargestMember(dataLayout));
305
306 unsigned recordSize = computeStructSize(dataLayout);
307 return llvm::TypeSize::getFixed(recordSize * 8);
308}
309
311RecordType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
312 ::mlir::DataLayoutEntryListRef params) const {
313 if (isUnion())
314 return dataLayout.getTypeABIAlignment(getLargestMember(dataLayout));
315
316 // Packed structures always have an ABI alignment of 1.
317 if (getPacked())
318 return 1;
319 return computeStructAlignment(dataLayout);
320}
321
322unsigned
323RecordType::computeStructSize(const mlir::DataLayout &dataLayout) const {
324 assert(isComplete() && "Cannot get layout of incomplete records");
325
326 // This is a similar algorithm to LLVM's StructLayout.
327 unsigned recordSize = 0;
328 uint64_t recordAlignment = 1;
329
330 for (mlir::Type ty : getMembers()) {
331 // This assumes that we're calculating size based on the ABI alignment, not
332 // the preferred alignment for each type.
333 const uint64_t tyAlign =
334 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
335
336 // Add padding to the struct size to align it to the abi alignment of the
337 // element type before than adding the size of the element.
338 recordSize = llvm::alignTo(recordSize, tyAlign);
339 recordSize += dataLayout.getTypeSize(ty);
340
341 // The alignment requirement of a struct is equal to the strictest alignment
342 // requirement of its elements.
343 recordAlignment = std::max(tyAlign, recordAlignment);
344 }
345
346 // At the end, add padding to the struct to satisfy its own alignment
347 // requirement. Otherwise structs inside of arrays would be misaligned.
348 recordSize = llvm::alignTo(recordSize, recordAlignment);
349 return recordSize;
350}
351
352// We also compute the alignment as part of computeStructSize, but this is more
353// efficient. Ideally, we'd like to compute both at once and cache the result,
354// but that's implemented yet.
355// TODO(CIR): Implement a way to cache the result.
357RecordType::computeStructAlignment(const mlir::DataLayout &dataLayout) const {
358 assert(isComplete() && "Cannot get layout of incomplete records");
359
360 // This is a similar algorithm to LLVM's StructLayout.
361 uint64_t recordAlignment = 1;
362 for (mlir::Type ty : getMembers())
363 recordAlignment =
364 std::max(dataLayout.getTypeABIAlignment(ty), recordAlignment);
365
366 return recordAlignment;
367}
368
369uint64_t RecordType::getElementOffset(const ::mlir::DataLayout &dataLayout,
370 unsigned idx) const {
371 assert(idx < getMembers().size() && "access not valid");
372
373 // All union elements are at offset zero.
374 if (isUnion() || idx == 0)
375 return 0;
376
377 assert(isComplete() && "Cannot get layout of incomplete records");
378 assert(idx < getNumElements());
379 llvm::ArrayRef<mlir::Type> members = getMembers();
380
381 unsigned offset = 0;
382
383 for (mlir::Type ty :
384 llvm::make_range(members.begin(), std::next(members.begin(), idx))) {
385 // This matches LLVM since it uses the ABI instead of preferred alignment.
386 const llvm::Align tyAlign =
387 llvm::Align(getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
388
389 // Add padding if necessary to align the data element properly.
390 offset = llvm::alignTo(offset, tyAlign);
391
392 // Consume space for this data item
393 offset += dataLayout.getTypeSize(ty);
394 }
395
396 // Account for padding, if necessary, for the alignment of the field whose
397 // offset we are calculating.
398 const llvm::Align tyAlign = llvm::Align(
399 getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[idx]));
400 offset = llvm::alignTo(offset, tyAlign);
401
402 return offset;
403}
404
405//===----------------------------------------------------------------------===//
406// IntType Definitions
407//===----------------------------------------------------------------------===//
408
409Type IntType::parse(mlir::AsmParser &parser) {
410 mlir::MLIRContext *context = parser.getBuilder().getContext();
411 llvm::SMLoc loc = parser.getCurrentLocation();
412 bool isSigned;
413 unsigned width;
414
415 if (parser.parseLess())
416 return {};
417
418 // Fetch integer sign.
419 llvm::StringRef sign;
420 if (parser.parseKeyword(&sign))
421 return {};
422 if (sign == "s")
423 isSigned = true;
424 else if (sign == "u")
425 isSigned = false;
426 else {
427 parser.emitError(loc, "expected 's' or 'u'");
428 return {};
429 }
430
431 if (parser.parseComma())
432 return {};
433
434 // Fetch integer size.
435 if (parser.parseInteger(width))
436 return {};
437 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
438 parser.emitError(loc, "expected integer width to be from ")
439 << IntType::minBitwidth() << " up to " << IntType::maxBitwidth();
440 return {};
441 }
442
443 if (parser.parseGreater())
444 return {};
445
446 return IntType::get(context, width, isSigned);
447}
448
449void IntType::print(mlir::AsmPrinter &printer) const {
450 char sign = isSigned() ? 's' : 'u';
451 printer << '<' << sign << ", " << getWidth() << '>';
452}
453
454llvm::TypeSize
455IntType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
456 mlir::DataLayoutEntryListRef params) const {
457 return llvm::TypeSize::getFixed(getWidth());
458}
459
460uint64_t IntType::getABIAlignment(const mlir::DataLayout &dataLayout,
461 mlir::DataLayoutEntryListRef params) const {
462 return (uint64_t)(getWidth() / 8);
463}
464
465mlir::LogicalResult
466IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
467 unsigned width, bool isSigned) {
468 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth())
469 return emitError() << "IntType only supports widths from "
470 << IntType::minBitwidth() << " up to "
471 << IntType::maxBitwidth();
472 return mlir::success();
473}
474
476 return width == 8 || width == 16 || width == 32 || width == 64;
477}
478
479//===----------------------------------------------------------------------===//
480// Floating-point type definitions
481//===----------------------------------------------------------------------===//
482
483const llvm::fltSemantics &SingleType::getFloatSemantics() const {
484 return llvm::APFloat::IEEEsingle();
485}
486
487llvm::TypeSize
488SingleType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
489 mlir::DataLayoutEntryListRef params) const {
490 return llvm::TypeSize::getFixed(getWidth());
491}
492
494SingleType::getABIAlignment(const mlir::DataLayout &dataLayout,
495 mlir::DataLayoutEntryListRef params) const {
496 return (uint64_t)(getWidth() / 8);
497}
498
499const llvm::fltSemantics &DoubleType::getFloatSemantics() const {
500 return llvm::APFloat::IEEEdouble();
501}
502
503llvm::TypeSize
504DoubleType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
505 mlir::DataLayoutEntryListRef params) const {
506 return llvm::TypeSize::getFixed(getWidth());
507}
508
510DoubleType::getABIAlignment(const mlir::DataLayout &dataLayout,
511 mlir::DataLayoutEntryListRef params) const {
512 return (uint64_t)(getWidth() / 8);
513}
514
515const llvm::fltSemantics &FP16Type::getFloatSemantics() const {
516 return llvm::APFloat::IEEEhalf();
517}
518
519llvm::TypeSize
520FP16Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
521 mlir::DataLayoutEntryListRef params) const {
522 return llvm::TypeSize::getFixed(getWidth());
523}
524
525uint64_t FP16Type::getABIAlignment(const mlir::DataLayout &dataLayout,
526 mlir::DataLayoutEntryListRef params) const {
527 return (uint64_t)(getWidth() / 8);
528}
529
530const llvm::fltSemantics &BF16Type::getFloatSemantics() const {
531 return llvm::APFloat::BFloat();
532}
533
534llvm::TypeSize
535BF16Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
536 mlir::DataLayoutEntryListRef params) const {
537 return llvm::TypeSize::getFixed(getWidth());
538}
539
540uint64_t BF16Type::getABIAlignment(const mlir::DataLayout &dataLayout,
541 mlir::DataLayoutEntryListRef params) const {
542 return (uint64_t)(getWidth() / 8);
543}
544
545const llvm::fltSemantics &FP80Type::getFloatSemantics() const {
546 return llvm::APFloat::x87DoubleExtended();
547}
548
549llvm::TypeSize
550FP80Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
551 mlir::DataLayoutEntryListRef params) const {
552 // Though only 80 bits are used for the value, the type is 128 bits in size.
553 return llvm::TypeSize::getFixed(128);
554}
555
556uint64_t FP80Type::getABIAlignment(const mlir::DataLayout &dataLayout,
557 mlir::DataLayoutEntryListRef params) const {
558 return 16;
559}
560
561const llvm::fltSemantics &FP128Type::getFloatSemantics() const {
562 return llvm::APFloat::IEEEquad();
563}
564
565llvm::TypeSize
566FP128Type::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
567 mlir::DataLayoutEntryListRef params) const {
568 return llvm::TypeSize::getFixed(getWidth());
569}
570
571uint64_t FP128Type::getABIAlignment(const mlir::DataLayout &dataLayout,
572 mlir::DataLayoutEntryListRef params) const {
573 return 16;
574}
575
576const llvm::fltSemantics &LongDoubleType::getFloatSemantics() const {
577 return mlir::cast<cir::FPTypeInterface>(getUnderlying()).getFloatSemantics();
578}
579
580llvm::TypeSize
581LongDoubleType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
582 mlir::DataLayoutEntryListRef params) const {
583 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
584 .getTypeSizeInBits(dataLayout, params);
585}
586
588LongDoubleType::getABIAlignment(const mlir::DataLayout &dataLayout,
589 mlir::DataLayoutEntryListRef params) const {
590 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
591 .getABIAlignment(dataLayout, params);
592}
593
594//===----------------------------------------------------------------------===//
595// ComplexType Definitions
596//===----------------------------------------------------------------------===//
597
598llvm::TypeSize
599cir::ComplexType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
600 mlir::DataLayoutEntryListRef params) const {
601 // C17 6.2.5p13:
602 // Each complex type has the same representation and alignment requirements
603 // as an array type containing exactly two elements of the corresponding
604 // real type.
605
606 return dataLayout.getTypeSizeInBits(getElementType()) * 2;
607}
608
610cir::ComplexType::getABIAlignment(const mlir::DataLayout &dataLayout,
611 mlir::DataLayoutEntryListRef params) const {
612 // C17 6.2.5p13:
613 // Each complex type has the same representation and alignment requirements
614 // as an array type containing exactly two elements of the corresponding
615 // real type.
616
617 return dataLayout.getTypeABIAlignment(getElementType());
618}
619
620FuncType FuncType::clone(TypeRange inputs, TypeRange results) const {
621 assert(results.size() == 1 && "expected exactly one result type");
622 return get(llvm::to_vector(inputs), results[0], isVarArg());
623}
624
625// Custom parser that parses function parameters of form `(<type>*, ...)`.
626static mlir::ParseResult
628 bool &isVarArg) {
629 isVarArg = false;
630 return p.parseCommaSeparatedList(
631 AsmParser::Delimiter::Paren, [&]() -> mlir::ParseResult {
632 if (isVarArg)
633 return p.emitError(p.getCurrentLocation(),
634 "variadic `...` must be the last parameter");
635 if (succeeded(p.parseOptionalEllipsis())) {
636 isVarArg = true;
637 return success();
638 }
639 mlir::Type type;
640 if (failed(p.parseType(type)))
641 return failure();
642 params.push_back(type);
643 return success();
644 });
645}
646
647static void printFuncTypeParams(mlir::AsmPrinter &p,
648 mlir::ArrayRef<mlir::Type> params,
649 bool isVarArg) {
650 p << '(';
651 llvm::interleaveComma(params, p,
652 [&p](mlir::Type type) { p.printType(type); });
653 if (isVarArg) {
654 if (!params.empty())
655 p << ", ";
656 p << "...";
657 }
658 p << ')';
659}
660
661/// Get the C-style return type of the function, which is !cir.void if the
662/// function returns nothing and the actual return type otherwise.
663mlir::Type FuncType::getReturnType() const {
664 if (hasVoidReturn())
665 return cir::VoidType::get(getContext());
666 return getOptionalReturnType();
667}
668
669/// Get the MLIR-style return type of the function, which is an empty
670/// ArrayRef if the function returns nothing and a single-element ArrayRef
671/// with the actual return type otherwise.
672llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes() const {
673 if (hasVoidReturn())
674 return {};
675 // Can't use getOptionalReturnType() here because llvm::ArrayRef hold a
676 // pointer to its elements and doesn't do lifetime extension. That would
677 // result in returning a pointer to a temporary that has gone out of scope.
678 return getImpl()->optionalReturnType;
679}
680
681// Does the fuction type return nothing?
682bool FuncType::hasVoidReturn() const { return !getOptionalReturnType(); }
683
684mlir::LogicalResult
685FuncType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
686 llvm::ArrayRef<mlir::Type> argTypes, mlir::Type returnType,
687 bool isVarArg) {
688 if (mlir::isa_and_nonnull<cir::VoidType>(returnType))
689 return emitError()
690 << "!cir.func cannot have an explicit 'void' return type";
691 return mlir::success();
692}
693
694//===----------------------------------------------------------------------===//
695// BoolType
696//===----------------------------------------------------------------------===//
697
698llvm::TypeSize
699BoolType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
700 ::mlir::DataLayoutEntryListRef params) const {
701 return llvm::TypeSize::getFixed(8);
702}
703
705BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
706 ::mlir::DataLayoutEntryListRef params) const {
707 return 1;
708}
709
710//===----------------------------------------------------------------------===//
711// VPtrType Definitions
712//===----------------------------------------------------------------------===//
713
714llvm::TypeSize
715VPtrType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
716 mlir::DataLayoutEntryListRef params) const {
717 // FIXME: consider size differences under different ABIs
718 return llvm::TypeSize::getFixed(64);
719}
720
721uint64_t VPtrType::getABIAlignment(const mlir::DataLayout &dataLayout,
722 mlir::DataLayoutEntryListRef params) const {
723 // FIXME: consider alignment differences under different ABIs
724 return 8;
725}
726
727//===----------------------------------------------------------------------===//
728// ArrayType Definitions
729//===----------------------------------------------------------------------===//
730
731llvm::TypeSize
732ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
733 ::mlir::DataLayoutEntryListRef params) const {
734 return getSize() * dataLayout.getTypeSizeInBits(getElementType());
735}
736
738ArrayType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
739 ::mlir::DataLayoutEntryListRef params) const {
740 return dataLayout.getTypeABIAlignment(getElementType());
741}
742
743//===----------------------------------------------------------------------===//
744// VectorType Definitions
745//===----------------------------------------------------------------------===//
746
747llvm::TypeSize cir::VectorType::getTypeSizeInBits(
748 const ::mlir::DataLayout &dataLayout,
749 ::mlir::DataLayoutEntryListRef params) const {
750 return llvm::TypeSize::getFixed(
751 getSize() * dataLayout.getTypeSizeInBits(getElementType()));
752}
753
755cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
756 ::mlir::DataLayoutEntryListRef params) const {
757 return llvm::NextPowerOf2(dataLayout.getTypeSizeInBits(*this));
758}
759
760mlir::LogicalResult cir::VectorType::verify(
761 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
762 mlir::Type elementType, uint64_t size) {
763 if (size == 0)
764 return emitError() << "the number of vector elements must be non-zero";
765 return success();
766}
767
768//===----------------------------------------------------------------------===//
769// PointerType Definitions
770//===----------------------------------------------------------------------===//
771
772llvm::TypeSize
773PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
774 ::mlir::DataLayoutEntryListRef params) const {
775 // FIXME: improve this in face of address spaces
776 return llvm::TypeSize::getFixed(64);
777}
778
780PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
781 ::mlir::DataLayoutEntryListRef params) const {
782 // FIXME: improve this in face of address spaces
783 return 8;
784}
785
786mlir::LogicalResult
787PointerType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
788 mlir::Type pointee) {
789 // TODO(CIR): Verification of the address space goes here.
790 return mlir::success();
791}
792
793//===----------------------------------------------------------------------===//
794// CIR Dialect
795//===----------------------------------------------------------------------===//
796
797void CIRDialect::registerTypes() {
798 // Register tablegen'd types.
799 addTypes<
800#define GET_TYPEDEF_LIST
801#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
802 >();
803
804 // Register raw C++ types.
805 // TODO(CIR) addTypes<RecordType>();
806}
static mlir::ParseResult parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector< mlir::Type > &params, bool &isVarArg)
Definition CIRTypes.cpp:627
static void printFuncTypeParams(mlir::AsmPrinter &p, mlir::ArrayRef< mlir::Type > params, bool isVarArg)
Definition CIRTypes.cpp:647
static Decl::Kind getKind(const Decl *D)
static LiveVariablesImpl & getImpl(void *x)
bool isValidFundamentalIntWidth(unsigned width)
Definition CIRTypes.cpp:475
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
Definition CIRTypes.cpp:24
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
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...
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.
static bool unsizedTypes()
static bool astRecordDeclAttr()