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

source code of clang/lib/CIR/Dialect/IR/CIRTypes.cpp