[clang] 36dd199 - [CIR] Upstream global initialization for ComplexType (#141369)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 5 13:06:47 PDT 2025
Author: Amr Hesham
Date: 2025-06-05T22:06:43+02:00
New Revision: 36dd1993a8d06c4ddd5732f926bcffacbb513649
URL: https://github.com/llvm/llvm-project/commit/36dd1993a8d06c4ddd5732f926bcffacbb513649
DIFF: https://github.com/llvm/llvm-project/commit/36dd1993a8d06c4ddd5732f926bcffacbb513649.diff
LOG: [CIR] Upstream global initialization for ComplexType (#141369)
This change adds support for zero and global init for ComplexType
#141365
Added:
clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
clang/test/CIR/CodeGen/complex.cpp
clang/test/CIR/IR/complex.cir
clang/test/CIR/IR/invalid-complex.cir
Modified:
clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
clang/include/clang/CIR/Dialect/IR/CIRTypes.td
clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
clang/lib/CIR/CodeGen/CIRGenTypes.cpp
clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
clang/lib/CIR/Dialect/IR/CIRDialect.cpp
clang/lib/CIR/Dialect/IR/CIRTypes.cpp
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 5cd0caa823ca1..7a5f192618a5d 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -90,6 +90,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return cir::IntAttr::get(ty, 0);
if (cir::isAnyFloatingPointType(ty))
return cir::FPAttr::getZero(ty);
+ if (auto complexType = mlir::dyn_cast<cir::ComplexType>(ty))
+ return cir::ZeroAttr::get(complexType);
if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
return cir::ZeroAttr::get(arrTy);
if (auto vecTy = mlir::dyn_cast<cir::VectorType>(ty))
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
new file mode 100644
index 0000000000000..382117938b2fe
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrConstraints.td
@@ -0,0 +1,42 @@
+
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CIR dialect attributes constraints.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CIR_DIALECT_IR_CIRATTRCONSTRAINTS_TD
+#define CLANG_CIR_DIALECT_IR_CIRATTRCONSTRAINTS_TD
+
+include "mlir/IR/CommonAttrConstraints.td"
+
+class CIR_IsAttrPred<code attr> : CPred<"::mlir::isa<" # attr # ">($_self)">;
+
+class CIR_AttrConstraint<code attr, string summary = "">
+ : Attr<CIR_IsAttrPred<attr>, summary>;
+
+//===----------------------------------------------------------------------===//
+// IntAttr constraints
+//===----------------------------------------------------------------------===//
+
+def CIR_AnyIntAttr : CIR_AttrConstraint<"::cir::IntAttr", "integer attribute">;
+
+//===----------------------------------------------------------------------===//
+// FPAttr constraints
+//===----------------------------------------------------------------------===//
+
+def CIR_AnyFPAttr : CIR_AttrConstraint<"::cir::FPAttr",
+ "floating-point attribute">;
+
+def CIR_AnyIntOrFloatAttr : AnyAttrOf<[CIR_AnyIntAttr, CIR_AnyFPAttr],
+ "integer or floating point type"> {
+ string cppType = "::mlir::TypedAttr";
+}
+
+#endif // CLANG_CIR_DIALECT_IR_CIRATTRCONSTRAINTS_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index ecbced05a5fdd..d22d265e82425 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -17,6 +17,7 @@ include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/EnumAttr.td"
include "clang/CIR/Dialect/IR/CIRDialect.td"
+include "clang/CIR/Dialect/IR/CIRAttrConstraints.td"
//===----------------------------------------------------------------------===//
// CIR Attrs
@@ -276,6 +277,50 @@ def ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> {
}];
}
+//===----------------------------------------------------------------------===//
+// ConstComplexAttr
+//===----------------------------------------------------------------------===//
+
+def ConstComplexAttr : CIR_Attr<"ConstComplex", "const_complex",
+ [TypedAttrInterface]> {
+ let summary = "An attribute that contains a constant complex value";
+ let description = [{
+ The `#cir.const_complex` attribute contains a constant value of complex
+ number type. The `real` parameter gives the real part of the complex number
+ and the `imag` parameter gives the imaginary part of the complex number.
+
+ The `real` and `imag` parameters must both reference the same type and must
+ be either IntAttr or FPAttr.
+
+ ```mlir
+ %ci = #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i>
+ : !cir.complex<!s32i>
+ %cf = #cir.const_complex<#cir.fp<1.000000e+00> : !cir.float,
+ #cir.fp<2.000000e+00> : !cir.float> : !cir.complex<!cir.float>
+ ```
+ }];
+
+ let parameters = (ins
+ AttributeSelfTypeParameter<"", "cir::ComplexType">:$type,
+ CIR_AnyIntOrFloatAttr:$real,
+ CIR_AnyIntOrFloatAttr:$imag
+ );
+
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "cir::ComplexType":$type,
+ "mlir::TypedAttr":$real,
+ "mlir::TypedAttr":$imag), [{
+ return $_get(type.getContext(), type, real, imag);
+ }]>,
+ ];
+
+ let genVerifyDecl = 1;
+
+ let assemblyFormat = [{
+ `<` qualified($real) `,` qualified($imag) `>`
+ }];
+}
+
//===----------------------------------------------------------------------===//
// VisibilityAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index b29b703c47139..fb96976075130 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -161,6 +161,56 @@ def CIR_LongDouble : CIR_FloatType<"LongDouble", "long_double"> {
}];
}
+//===----------------------------------------------------------------------===//
+// ComplexType
+//===----------------------------------------------------------------------===//
+
+def CIR_ComplexType : CIR_Type<"Complex", "complex",
+ [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
+
+ let summary = "CIR complex type";
+ let description = [{
+ CIR type that represents a C complex number. `cir.complex` models the C type
+ `T _Complex`.
+
+ `cir.complex` type is not directly mapped to `std::complex`.
+
+ The type models complex values, per C99 6.2.5p11. It supports the C99
+ complex float types as well as the GCC integer complex extensions.
+
+ The parameter `elementType` gives the type of the real and imaginary part of
+ the complex number. `elementType` must be either a CIR integer type or a CIR
+ floating-point type.
+
+ ```mlir
+ !cir.complex<!s32i>
+ !cir.complex<!cir.float>
+ ```
+ }];
+
+ let parameters = (ins CIR_AnyIntOrFloatType:$elementType);
+
+ let builders = [
+ TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
+ return $_get(elementType.getContext(), elementType);
+ }]>,
+ ];
+
+ let assemblyFormat = [{
+ `<` $elementType `>`
+ }];
+
+ let extraClassDeclaration = [{
+ bool isFloatingPointComplex() const {
+ return isAnyFloatingPointType(getElementType());
+ }
+
+ bool isIntegerComplex() const {
+ return mlir::isa<cir::IntType>(getElementType());
+ }
+ }];
+}
+
//===----------------------------------------------------------------------===//
// PointerType
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 9085ee2dfe506..c41ab54be09ca 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -577,12 +577,33 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
case APValue::Union:
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate struct or union");
return {};
- case APValue::FixedPoint:
case APValue::ComplexInt:
- case APValue::ComplexFloat:
+ case APValue::ComplexFloat: {
+ mlir::Type desiredType = cgm.convertType(destType);
+ cir::ComplexType complexType =
+ mlir::dyn_cast<cir::ComplexType>(desiredType);
+
+ mlir::Type complexElemTy = complexType.getElementType();
+ if (isa<cir::IntType>(complexElemTy)) {
+ llvm::APSInt real = value.getComplexIntReal();
+ llvm::APSInt imag = value.getComplexIntImag();
+ return builder.getAttr<cir::ConstComplexAttr>(
+ complexType, builder.getAttr<cir::IntAttr>(complexElemTy, real),
+ builder.getAttr<cir::IntAttr>(complexElemTy, imag));
+ }
+
+ assert(isa<cir::CIRFPTypeInterface>(complexElemTy) &&
+ "expected floating-point type");
+ llvm::APFloat real = value.getComplexFloatReal();
+ llvm::APFloat imag = value.getComplexFloatImag();
+ return builder.getAttr<cir::ConstComplexAttr>(
+ complexType, builder.getAttr<cir::FPAttr>(complexElemTy, real),
+ builder.getAttr<cir::FPAttr>(complexElemTy, imag));
+ }
+ case APValue::FixedPoint:
case APValue::AddrLabelDiff:
- cgm.errorNYI("ConstExprEmitter::tryEmitPrivate fixed point, complex int, "
- "complex float, addr label
diff ");
+ cgm.errorNYI(
+ "ConstExprEmitter::tryEmitPrivate fixed point, addr label
diff ");
return {};
}
llvm_unreachable("Unknown APValue kind");
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index f748649c8ac70..5f51d348e75ce 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -388,6 +388,13 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
break;
}
+ case Type::Complex: {
+ const auto *ct = cast<clang::ComplexType>(ty);
+ mlir::Type elementTy = convertType(ct->getElementType());
+ resultType = cir::ComplexType::get(elementTy);
+ break;
+ }
+
case Type::LValueReference:
case Type::RValueReference: {
const ReferenceType *refTy = cast<ReferenceType>(ty);
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 52f0b33afaba4..b52e9c3e49199 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -183,6 +183,26 @@ LogicalResult FPAttr::verify(function_ref<InFlightDiagnostic()> emitError,
return success();
}
+//===----------------------------------------------------------------------===//
+// ConstComplexAttr definitions
+//===----------------------------------------------------------------------===//
+
+LogicalResult
+ConstComplexAttr::verify(function_ref<InFlightDiagnostic()> emitError,
+ cir::ComplexType type, mlir::TypedAttr real,
+ mlir::TypedAttr imag) {
+ mlir::Type elemType = type.getElementType();
+ if (real.getType() != elemType)
+ return emitError()
+ << "type of the real part does not match the complex type";
+
+ if (imag.getType() != elemType)
+ return emitError()
+ << "type of the imaginary part does not match the complex type";
+
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// CIR ConstArrayAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index fa7fb592a3cd6..5f2efa3fd84af 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -231,9 +231,11 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
}
if (isa<cir::ZeroAttr>(attrType)) {
- if (isa<cir::RecordType, cir::ArrayType, cir::VectorType>(opType))
+ if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>(
+ opType))
return success();
- return op->emitOpError("zero expects struct or array type");
+ return op->emitOpError(
+ "zero expects struct, array, vector, or complex type");
}
if (mlir::isa<cir::BoolAttr>(attrType)) {
@@ -253,7 +255,8 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
return success();
}
- if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr>(attrType))
+ if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
+ cir::ConstComplexAttr>(attrType))
return success();
assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 3543c139bbf79..09926a93eb6f3 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -558,9 +558,31 @@ LongDoubleType::getABIAlignment(const mlir::DataLayout &dataLayout,
}
//===----------------------------------------------------------------------===//
-// FuncType Definitions
+// ComplexType Definitions
//===----------------------------------------------------------------------===//
+llvm::TypeSize
+cir::ComplexType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
+ mlir::DataLayoutEntryListRef params) const {
+ // C17 6.2.5p13:
+ // Each complex type has the same representation and alignment requirements
+ // as an array type containing exactly two elements of the corresponding
+ // real type.
+
+ return dataLayout.getTypeSizeInBits(getElementType()) * 2;
+}
+
+uint64_t
+cir::ComplexType::getABIAlignment(const mlir::DataLayout &dataLayout,
+ mlir::DataLayoutEntryListRef params) const {
+ // C17 6.2.5p13:
+ // Each complex type has the same representation and alignment requirements
+ // as an array type containing exactly two elements of the corresponding
+ // real type.
+
+ return dataLayout.getTypeABIAlignment(getElementType());
+}
+
FuncType FuncType::clone(TypeRange inputs, TypeRange results) const {
assert(results.size() == 1 && "expected exactly one result type");
return get(llvm::to_vector(inputs), results[0], isVarArg());
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index bbfd5df925eca..8059836db6b71 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -188,14 +188,15 @@ class CIRAttrToValue {
mlir::Value visit(mlir::Attribute attr) {
return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
- .Case<cir::IntAttr, cir::FPAttr, cir::ConstArrayAttr,
- cir::ConstVectorAttr, cir::ConstPtrAttr, cir::ZeroAttr>(
- [&](auto attrT) { return visitCirAttr(attrT); })
+ .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
+ cir::ConstArrayAttr, cir::ConstVectorAttr, cir::ConstPtrAttr,
+ cir::ZeroAttr>([&](auto attrT) { return visitCirAttr(attrT); })
.Default([&](auto attrT) { return mlir::Value(); });
}
mlir::Value visitCirAttr(cir::IntAttr intAttr);
mlir::Value visitCirAttr(cir::FPAttr fltAttr);
+ mlir::Value visitCirAttr(cir::ConstComplexAttr complexAttr);
mlir::Value visitCirAttr(cir::ConstPtrAttr ptrAttr);
mlir::Value visitCirAttr(cir::ConstArrayAttr attr);
mlir::Value visitCirAttr(cir::ConstVectorAttr attr);
@@ -226,6 +227,42 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
loc, converter->convertType(intAttr.getType()), intAttr.getValue());
}
+/// FPAttr visitor.
+mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
+ mlir::Location loc = parentOp->getLoc();
+ return rewriter.create<mlir::LLVM::ConstantOp>(
+ loc, converter->convertType(fltAttr.getType()), fltAttr.getValue());
+}
+
+/// ConstComplexAttr visitor.
+mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
+ auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
+ mlir::Type complexElemTy = complexType.getElementType();
+ mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
+
+ mlir::Attribute components[2];
+ if (const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
+ components[0] = rewriter.getIntegerAttr(
+ complexElemLLVMTy,
+ mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
+ components[1] = rewriter.getIntegerAttr(
+ complexElemLLVMTy,
+ mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
+ } else {
+ components[0] = rewriter.getFloatAttr(
+ complexElemLLVMTy,
+ mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
+ components[1] = rewriter.getFloatAttr(
+ complexElemLLVMTy,
+ mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
+ }
+
+ mlir::Location loc = parentOp->getLoc();
+ return rewriter.create<mlir::LLVM::ConstantOp>(
+ loc, converter->convertType(complexAttr.getType()),
+ rewriter.getArrayAttr(components));
+}
+
/// ConstPtrAttr visitor.
mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
mlir::Location loc = parentOp->getLoc();
@@ -241,13 +278,6 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
loc, converter->convertType(ptrAttr.getType()), ptrVal);
}
-/// FPAttr visitor.
-mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
- mlir::Location loc = parentOp->getLoc();
- return rewriter.create<mlir::LLVM::ConstantOp>(
- loc, converter->convertType(fltAttr.getType()), fltAttr.getValue());
-}
-
// ConstArrayAttr visitor
mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
mlir::Type llvmTy = converter->convertType(attr.getType());
@@ -341,9 +371,11 @@ class GlobalInitAttrRewriter {
mlir::Attribute visitCirAttr(cir::IntAttr attr) {
return rewriter.getIntegerAttr(llvmType, attr.getValue());
}
+
mlir::Attribute visitCirAttr(cir::FPAttr attr) {
return rewriter.getFloatAttr(llvmType, attr.getValue());
}
+
mlir::Attribute visitCirAttr(cir::BoolAttr attr) {
return rewriter.getBoolAttr(attr.getValue());
}
@@ -986,7 +1018,7 @@ CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
mlir::ConversionPatternRewriter &rewriter) const {
// TODO: Generalize this handling when more types are needed here.
assert((isa<cir::ConstArrayAttr, cir::ConstVectorAttr, cir::ConstPtrAttr,
- cir::ZeroAttr>(init)));
+ cir::ConstComplexAttr, cir::ZeroAttr>(init)));
// TODO(cir): once LLVM's dialect has proper equivalent attributes this
// should be updated. For now, we use a custom op to initialize globals
@@ -1039,7 +1071,8 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
return mlir::failure();
}
} else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
- cir::ConstPtrAttr, cir::ZeroAttr>(init.value())) {
+ cir::ConstPtrAttr, cir::ConstComplexAttr,
+ cir::ZeroAttr>(init.value())) {
// TODO(cir): once LLVM's dialect has proper equivalent attributes this
// should be updated. For now, we use a custom op to initialize globals
// to the appropriate value.
@@ -1571,6 +1604,14 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
return mlir::BFloat16Type::get(type.getContext());
});
+ converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
+ // A complex type is lowered to an LLVM struct that contains the real and
+ // imaginary part as data fields.
+ mlir::Type elementTy = converter.convertType(type.getElementType());
+ mlir::Type structFields[2] = {elementTy, elementTy};
+ return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
+ structFields);
+ });
converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
auto result = converter.convertType(type.getReturnType());
llvm::SmallVector<mlir::Type> arguments;
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
new file mode 100644
index 0000000000000..6fa7bca3749cf
--- /dev/null
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+int _Complex ci;
+
+float _Complex cf;
+
+int _Complex ci2 = { 1, 2 };
+
+float _Complex cf2 = { 1.0f, 2.0f };
+
+// CIR: cir.global external @ci = #cir.zero : !cir.complex<!s32i>
+// CIR: cir.global external @cf = #cir.zero : !cir.complex<!cir.float>
+// CIR: cir.global external @ci2 = #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i> : !cir.complex<!s32i>
+// CIR: cir.global external @cf2 = #cir.const_complex<#cir.fp<1.000000e+00> : !cir.float, #cir.fp<2.000000e+00> : !cir.float> : !cir.complex<!cir.float>
+
+// LLVM: {{.*}} = global { i32, i32 } zeroinitializer, align 4
+// LLVM: {{.*}} = global { float, float } zeroinitializer, align 4
+// LLVM: {{.*}} = global { i32, i32 } { i32 1, i32 2 }, align 4
+// LLVM: {{.*}} = global { float, float } { float 1.000000e+00, float 2.000000e+00 }, align 4
+
+// OGCG: {{.*}} = global { i32, i32 } zeroinitializer, align 4
+// OGCG: {{.*}} = global { float, float } zeroinitializer, align 4
+// OGCG: {{.*}} = global { i32, i32 } { i32 1, i32 2 }, align 4
+// OGCG: {{.*}} = global { float, float } { float 1.000000e+00, float 2.000000e+00 }, align 4
diff --git a/clang/test/CIR/IR/complex.cir b/clang/test/CIR/IR/complex.cir
new file mode 100644
index 0000000000000..a73a8654ca274
--- /dev/null
+++ b/clang/test/CIR/IR/complex.cir
@@ -0,0 +1,16 @@
+// RUN: cir-opt %s | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+
+module {
+
+cir.global external @ci = #cir.zero : !cir.complex<!s32i>
+// CHECK: cir.global external {{.*}} = #cir.zero : !cir.complex<!s32i>
+
+cir.global external @cf = #cir.zero : !cir.complex<!cir.float>
+// CHECK: cir.global external {{.*}} = #cir.zero : !cir.complex<!cir.float>
+
+cir.global external @ci2 = #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i> : !cir.complex<!s32i>
+// CHECK: cir.global external {{.*}} = #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i> : !cir.complex<!s32i>
+
+}
diff --git a/clang/test/CIR/IR/invalid-complex.cir b/clang/test/CIR/IR/invalid-complex.cir
new file mode 100644
index 0000000000000..8c6d890579321
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-complex.cir
@@ -0,0 +1,23 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!s32i = !cir.int<s, 32>
+!s64i = !cir.int<s, 64>
+
+module {
+
+// expected-error @below {{type of the real part does not match the complex type}}
+cir.global external @ci2 = #cir.const_complex<#cir.int<1> : !s64i, #cir.int<2> : !s32i> : !cir.complex<!s32i>
+
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!s64i = !cir.int<s, 64>
+
+module {
+
+// expected-error @below {{type of the imaginary part does not match the complex type}}
+cir.global external @ci2 = #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s64i> : !cir.complex<!s32i>
+
+}
More information about the cfe-commits
mailing list