15#include "mlir/IR/BuiltinAttributes.h"
16#include "mlir/IR/DialectImplementation.h"
17#include "mlir/IR/MLIRContext.h"
23#include "llvm/ADT/APInt.h"
24#include "llvm/ADT/APSInt.h"
25#include "llvm/ADT/TypeSwitch.h"
31 if (
auto sizedTy = mlir::dyn_cast<cir::SizedTypeInterface>(ty))
32 return sizedTy.isSized();
41static mlir::ParseResult
45 mlir::ArrayRef<mlir::Type> params,
51static mlir::ParseResult
56 mlir::ArrayRef<mlir::Type> params,
64 cir::TargetAddressSpaceAttr &attr);
67 cir::TargetAddressSpaceAttr attr);
75#include "clang/CIR/Dialect/IR/CIRTypeConstraints.cpp.inc"
79#define GET_TYPEDEF_CLASSES
80#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
89Type CIRDialect::parseType(DialectAsmParser &parser)
const {
90 llvm::SMLoc typeLoc = parser.getCurrentLocation();
91 llvm::StringRef mnemonic;
95 OptionalParseResult parseResult =
96 generatedTypeParser(parser, &mnemonic, genType);
97 if (parseResult.has_value())
101 return StringSwitch<function_ref<Type()>>(mnemonic)
102 .Case(
"record", [&] {
return RecordType::parse(parser); })
104 parser.emitError(typeLoc) <<
"unknown CIR type: " << mnemonic;
109void CIRDialect::printType(Type type, DialectAsmPrinter &os)
const {
111 if (generatedTypePrinter(type, os).succeeded())
115 llvm::report_fatal_error(
"printer is missing a handler for this type");
122Type RecordType::parse(mlir::AsmParser &parser) {
123 FailureOr<AsmParser::CyclicParseReset> cyclicParseGuard;
124 const llvm::SMLoc loc = parser.getCurrentLocation();
125 const mlir::Location eLoc = parser.getEncodedSourceLoc(loc);
129 mlir::MLIRContext *context = parser.getContext();
131 if (parser.parseLess())
136 if (parser.parseOptionalKeyword(
"struct").succeeded())
137 kind = RecordKind::Struct;
138 else if (parser.parseOptionalKeyword(
"union").succeeded())
139 kind = RecordKind::Union;
140 else if (parser.parseOptionalKeyword(
"class").succeeded())
141 kind = RecordKind::Class;
143 parser.emitError(loc,
"unknown record type");
147 mlir::StringAttr
name;
148 parser.parseOptionalAttribute(name);
151 if (name && parser.parseOptionalGreater().succeeded()) {
152 RecordType
type = getChecked(eLoc, context, name, kind);
153 if (succeeded(parser.tryStartCyclicParse(type))) {
154 parser.emitError(loc,
"invalid self-reference within record");
162 RecordType
type = getChecked(eLoc, context, name, kind);
163 cyclicParseGuard = parser.tryStartCyclicParse(type);
164 if (failed(cyclicParseGuard)) {
165 parser.emitError(loc,
"record already defined");
170 if (parser.parseOptionalKeyword(
"packed").succeeded())
173 if (parser.parseOptionalKeyword(
"padded").succeeded())
177 bool incomplete =
true;
178 llvm::SmallVector<mlir::Type> members;
179 if (parser.parseOptionalKeyword(
"incomplete").failed()) {
181 const auto delimiter = AsmParser::Delimiter::Braces;
182 const auto parseElementFn = [&parser, &members]() {
183 return parser.parseType(members.emplace_back());
185 if (parser.parseCommaSeparatedList(delimiter, parseElementFn).failed())
189 if (parser.parseGreater())
193 ArrayRef<mlir::Type> membersRef(members);
194 mlir::Type
type = {};
195 if (name && incomplete) {
196 type = getChecked(eLoc, context, name, kind);
197 }
else if (!name && !incomplete) {
198 type = getChecked(eLoc, context, membersRef, packed, padded, kind);
199 }
else if (!incomplete) {
200 type = getChecked(eLoc, context, membersRef, name, packed, padded, kind);
203 if (mlir::cast<RecordType>(type).isIncomplete())
204 mlir::cast<RecordType>(type).complete(membersRef, packed, padded);
207 parser.emitError(loc,
"anonymous records must be complete");
214void RecordType::print(mlir::AsmPrinter &printer)
const {
215 FailureOr<AsmPrinter::CyclicPrintReset> cyclicPrintGuard;
219 case RecordKind::Struct:
220 printer <<
"struct ";
222 case RecordKind::Union:
225 case RecordKind::Class:
234 cyclicPrintGuard = printer.tryStartCyclicPrint(*
this);
235 if (failed(cyclicPrintGuard)) {
244 printer <<
"packed ";
247 printer <<
"padded ";
249 if (isIncomplete()) {
250 printer <<
"incomplete";
253 llvm::interleaveComma(getMembers(), printer);
261RecordType::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
262 llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name,
263 bool incomplete,
bool packed,
bool padded,
264 RecordType::RecordKind kind) {
265 if (name &&
name.getValue().empty())
266 return emitError() <<
"identified records cannot have an empty name";
267 return mlir::success();
270::llvm::ArrayRef<mlir::Type> RecordType::getMembers()
const {
274bool RecordType::isIncomplete()
const {
return getImpl()->incomplete; }
276mlir::StringAttr RecordType::getName()
const {
return getImpl()->name; }
278bool RecordType::getIncomplete()
const {
return getImpl()->incomplete; }
280bool RecordType::getPacked()
const {
return getImpl()->packed; }
282bool RecordType::getPadded()
const {
return getImpl()->padded; }
284cir::RecordType::RecordKind RecordType::getKind()
const {
288void RecordType::complete(ArrayRef<Type> members,
bool packed,
bool padded) {
290 if (mutate(members, packed, padded).failed())
291 llvm_unreachable(
"failed to complete record");
297Type RecordType::getLargestMember(const ::mlir::DataLayout &dataLayout)
const {
298 assert(isUnion() &&
"Only call getLargestMember on unions");
299 llvm::ArrayRef<Type> members = getMembers();
302 return *std::max_element(
303 members.begin(), getPadded() ? members.end() - 1 : members.end(),
304 [&](Type lhs, Type rhs) {
305 return dataLayout.getTypeABIAlignment(lhs) <
306 dataLayout.getTypeABIAlignment(rhs) ||
307 (dataLayout.getTypeABIAlignment(lhs) ==
308 dataLayout.getTypeABIAlignment(rhs) &&
309 dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
313bool RecordType::isLayoutIdentical(
const RecordType &other) {
314 if (
getImpl() == other.getImpl())
317 if (getPacked() != other.getPacked())
320 return getMembers() == other.getMembers();
328PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
329 ::mlir::DataLayoutEntryListRef params)
const {
332 return llvm::TypeSize::getFixed(64);
336PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
337 ::mlir::DataLayoutEntryListRef params)
const {
344RecordType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
345 mlir::DataLayoutEntryListRef params)
const {
347 return dataLayout.getTypeSize(getLargestMember(dataLayout));
349 auto recordSize =
static_cast<uint64_t>(computeStructSize(dataLayout));
350 return llvm::TypeSize::getFixed(recordSize * 8);
354RecordType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
355 ::mlir::DataLayoutEntryListRef params)
const {
357 return dataLayout.getTypeABIAlignment(getLargestMember(dataLayout));
362 return computeStructAlignment(dataLayout);
366RecordType::computeStructSize(
const mlir::DataLayout &dataLayout)
const {
367 assert(isComplete() &&
"Cannot get layout of incomplete records");
370 unsigned recordSize = 0;
373 for (mlir::Type ty : getMembers()) {
377 (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
381 recordSize = llvm::alignTo(recordSize, tyAlign);
382 recordSize += dataLayout.getTypeSize(ty);
386 recordAlignment = std::max(tyAlign, recordAlignment);
391 recordSize = llvm::alignTo(recordSize, recordAlignment);
400RecordType::computeStructAlignment(
const mlir::DataLayout &dataLayout)
const {
401 assert(isComplete() &&
"Cannot get layout of incomplete records");
405 for (mlir::Type ty : getMembers())
407 std::max(dataLayout.getTypeABIAlignment(ty), recordAlignment);
409 return recordAlignment;
412uint64_t RecordType::getElementOffset(const ::mlir::DataLayout &dataLayout,
413 unsigned idx)
const {
414 assert(idx < getMembers().size() &&
"access not valid");
417 if (isUnion() || idx == 0)
420 assert(isComplete() &&
"Cannot get layout of incomplete records");
421 assert(idx < getNumElements());
422 llvm::ArrayRef<mlir::Type> members = getMembers();
427 llvm::make_range(members.begin(), std::next(members.begin(), idx))) {
429 const llvm::Align tyAlign =
430 llvm::Align(getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
433 offset = llvm::alignTo(offset, tyAlign);
436 offset += dataLayout.getTypeSize(ty);
441 const llvm::Align tyAlign = llvm::Align(
442 getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[idx]));
443 offset = llvm::alignTo(offset, tyAlign);
452Type IntType::parse(mlir::AsmParser &parser) {
453 mlir::MLIRContext *context = parser.getBuilder().getContext();
454 llvm::SMLoc loc = parser.getCurrentLocation();
458 if (parser.parseLess())
462 llvm::StringRef
sign;
463 if (parser.parseKeyword(&
sign))
467 else if (
sign ==
"u")
470 parser.emitError(loc,
"expected 's' or 'u'");
474 if (parser.parseComma())
478 if (parser.parseInteger(width))
480 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
481 parser.emitError(loc,
"expected integer width to be from ")
482 << IntType::minBitwidth() <<
" up to " << IntType::maxBitwidth();
486 if (parser.parseGreater())
489 return IntType::get(context, width, isSigned);
492void IntType::print(mlir::AsmPrinter &printer)
const {
493 char sign = isSigned() ?
's' :
'u';
494 printer <<
'<' <<
sign <<
", " << getWidth() <<
'>';
498IntType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
499 mlir::DataLayoutEntryListRef params)
const {
500 return llvm::TypeSize::getFixed(getWidth());
503uint64_t IntType::getABIAlignment(
const mlir::DataLayout &dataLayout,
504 mlir::DataLayoutEntryListRef params)
const {
505 return (uint64_t)(getWidth() / 8);
509IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
510 unsigned width,
bool isSigned) {
511 if (width < IntType::minBitwidth() || width > IntType::maxBitwidth())
512 return emitError() <<
"IntType only supports widths from "
513 << IntType::minBitwidth() <<
" up to "
514 << IntType::maxBitwidth();
515 return mlir::success();
519 return width == 8 || width == 16 || width == 32 || width == 64;
526const llvm::fltSemantics &SingleType::getFloatSemantics()
const {
527 return llvm::APFloat::IEEEsingle();
531SingleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
532 mlir::DataLayoutEntryListRef params)
const {
533 return llvm::TypeSize::getFixed(getWidth());
537SingleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
538 mlir::DataLayoutEntryListRef params)
const {
539 return (uint64_t)(getWidth() / 8);
542const llvm::fltSemantics &DoubleType::getFloatSemantics()
const {
543 return llvm::APFloat::IEEEdouble();
547DoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
548 mlir::DataLayoutEntryListRef params)
const {
549 return llvm::TypeSize::getFixed(getWidth());
553DoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
554 mlir::DataLayoutEntryListRef params)
const {
555 return (uint64_t)(getWidth() / 8);
558const llvm::fltSemantics &FP16Type::getFloatSemantics()
const {
559 return llvm::APFloat::IEEEhalf();
563FP16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
564 mlir::DataLayoutEntryListRef params)
const {
565 return llvm::TypeSize::getFixed(getWidth());
568uint64_t FP16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
569 mlir::DataLayoutEntryListRef params)
const {
570 return (uint64_t)(getWidth() / 8);
573const llvm::fltSemantics &BF16Type::getFloatSemantics()
const {
574 return llvm::APFloat::BFloat();
578BF16Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
579 mlir::DataLayoutEntryListRef params)
const {
580 return llvm::TypeSize::getFixed(getWidth());
583uint64_t BF16Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
584 mlir::DataLayoutEntryListRef params)
const {
585 return (uint64_t)(getWidth() / 8);
588const llvm::fltSemantics &FP80Type::getFloatSemantics()
const {
589 return llvm::APFloat::x87DoubleExtended();
593FP80Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
594 mlir::DataLayoutEntryListRef params)
const {
596 return llvm::TypeSize::getFixed(128);
599uint64_t FP80Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
600 mlir::DataLayoutEntryListRef params)
const {
604const llvm::fltSemantics &FP128Type::getFloatSemantics()
const {
605 return llvm::APFloat::IEEEquad();
609FP128Type::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
610 mlir::DataLayoutEntryListRef params)
const {
611 return llvm::TypeSize::getFixed(getWidth());
614uint64_t FP128Type::getABIAlignment(
const mlir::DataLayout &dataLayout,
615 mlir::DataLayoutEntryListRef params)
const {
619const llvm::fltSemantics &LongDoubleType::getFloatSemantics()
const {
620 return mlir::cast<cir::FPTypeInterface>(getUnderlying()).getFloatSemantics();
624LongDoubleType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
625 mlir::DataLayoutEntryListRef params)
const {
626 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
627 .getTypeSizeInBits(dataLayout, params);
631LongDoubleType::getABIAlignment(
const mlir::DataLayout &dataLayout,
632 mlir::DataLayoutEntryListRef params)
const {
633 return mlir::cast<mlir::DataLayoutTypeInterface>(getUnderlying())
634 .getABIAlignment(dataLayout, params);
642cir::ComplexType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
643 mlir::DataLayoutEntryListRef params)
const {
649 return dataLayout.getTypeSizeInBits(getElementType()) * 2;
653cir::ComplexType::getABIAlignment(
const mlir::DataLayout &dataLayout,
654 mlir::DataLayoutEntryListRef params)
const {
660 return dataLayout.getTypeABIAlignment(getElementType());
663FuncType FuncType::clone(TypeRange inputs, TypeRange results)
const {
664 assert(results.size() == 1 &&
"expected exactly one result type");
665 return get(llvm::to_vector(inputs), results[0], isVarArg());
669static mlir::ParseResult
673 return p.parseCommaSeparatedList(
674 AsmParser::Delimiter::Paren, [&]() -> mlir::ParseResult {
676 return p.emitError(p.getCurrentLocation(),
677 "variadic `...` must be the last parameter");
678 if (succeeded(p.parseOptionalEllipsis())) {
683 if (failed(p.parseType(type)))
685 params.push_back(type);
691 mlir::ArrayRef<mlir::Type> params,
694 llvm::interleaveComma(params, p,
695 [&p](mlir::Type type) { p.printType(type); });
706mlir::Type FuncType::getReturnType()
const {
708 return cir::VoidType::get(getContext());
709 return getOptionalReturnType();
715llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes()
const {
721 return getImpl()->optionalReturnType;
725bool FuncType::hasVoidReturn()
const {
return !getOptionalReturnType(); }
728FuncType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
729 llvm::ArrayRef<mlir::Type> argTypes, mlir::Type returnType,
731 if (mlir::isa_and_nonnull<cir::VoidType>(returnType))
733 <<
"!cir.func cannot have an explicit 'void' return type";
734 return mlir::success();
742BoolType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
743 ::mlir::DataLayoutEntryListRef params)
const {
744 return llvm::TypeSize::getFixed(8);
748BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
749 ::mlir::DataLayoutEntryListRef params)
const {
758VPtrType::getTypeSizeInBits(
const mlir::DataLayout &dataLayout,
759 mlir::DataLayoutEntryListRef params)
const {
761 return llvm::TypeSize::getFixed(64);
764uint64_t VPtrType::getABIAlignment(
const mlir::DataLayout &dataLayout,
765 mlir::DataLayoutEntryListRef params)
const {
775ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
776 ::mlir::DataLayoutEntryListRef params)
const {
777 return getSize() * dataLayout.getTypeSizeInBits(getElementType());
781ArrayType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
782 ::mlir::DataLayoutEntryListRef params)
const {
783 return dataLayout.getTypeABIAlignment(getElementType());
790llvm::TypeSize cir::VectorType::getTypeSizeInBits(
791 const ::mlir::DataLayout &dataLayout,
792 ::mlir::DataLayoutEntryListRef params)
const {
793 return llvm::TypeSize::getFixed(
794 getSize() * dataLayout.getTypeSizeInBits(getElementType()));
798cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
799 ::mlir::DataLayoutEntryListRef params)
const {
800 return llvm::NextPowerOf2(dataLayout.getTypeSizeInBits(*
this));
803mlir::LogicalResult cir::VectorType::verify(
804 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
805 mlir::Type elementType, uint64_t size) {
807 return emitError() <<
"the number of vector elements must be non-zero";
815cir::TargetAddressSpaceAttr
817 return cir::TargetAddressSpaceAttr::get(
819 IntegerAttr::get(&context,
830 if (!isTargetAddressSpace(as))
833 return cirAS.getValue().getUInt() == toTargetAddressSpace(as);
837 cir::TargetAddressSpaceAttr &attr) {
838 if (failed(p.parseKeyword(
"target_address_space")))
839 return mlir::failure();
841 if (failed(p.parseLParen()))
842 return mlir::failure();
845 if (failed(p.parseInteger(targetValue)))
846 return p.emitError(p.getCurrentLocation(),
847 "expected integer address space value");
849 if (failed(p.parseRParen()))
850 return p.emitError(p.getCurrentLocation(),
851 "expected ')' after address space value");
853 mlir::MLIRContext *context = p.getBuilder().getContext();
854 attr = cir::TargetAddressSpaceAttr::get(
855 context, p.getBuilder().getUI32IntegerAttr(targetValue));
856 return mlir::success();
862 cir::TargetAddressSpaceAttr attr) {
863 p <<
"target_address_space(" << attr.getValue().getUInt() <<
")";
870void CIRDialect::registerTypes() {
873#define GET_TYPEDEF_LIST
874#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
Provides definitions for the various language-specific address spaces.
mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p, cir::TargetAddressSpaceAttr &attr)
void printTargetAddressSpace(mlir::AsmPrinter &p, cir::TargetAddressSpaceAttr attr)
mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p, cir::TargetAddressSpaceAttr &attr)
static mlir::ParseResult parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector< mlir::Type > ¶ms, bool &isVarArg)
static void printFuncTypeParams(mlir::AsmPrinter &p, mlir::ArrayRef< mlir::Type > params, bool isVarArg)
void printTargetAddressSpace(mlir::AsmPrinter &p, cir::TargetAddressSpaceAttr attr)
static Decl::Kind getKind(const Decl *D)
static LiveVariablesImpl & getImpl(void *x)
bool isValidFundamentalIntWidth(unsigned width)
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
bool isMatchingAddressSpace(cir::TargetAddressSpaceAttr cirAS, clang::LangAS as)
cir::TargetAddressSpaceAttr toCIRTargetAddressSpace(mlir::MLIRContext &context, clang::LangAS langAS)
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)
unsigned toTargetAddressSpace(LangAS AS)
LangAS
Defines the address space values used by the address space qualifier of QualType.
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 dataLayoutPtrHandlingBasedOnLangAS()
static bool astRecordDeclAttr()