diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h | 7 | ||||
-rw-r--r-- | clang/include/clang/CIR/Dialect/IR/CIROps.td | 10 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenAtomic.cpp | 20 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenCall.cpp | 26 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenCall.h | 2 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 14 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 20 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 13 | ||||
-rw-r--r-- | clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 19 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/complex.cpp | 62 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/paren-init-list.cpp | 30 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/struct.cpp | 64 |
13 files changed, 245 insertions, 57 deletions
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 93d81e3..569491a 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -178,9 +178,10 @@ public: } mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) { - auto operandTy = mlir::cast<cir::ComplexType>(operand.getType()); - return cir::ComplexImagOp::create(*this, loc, operandTy.getElementType(), - operand); + auto resultType = operand.getType(); + if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType)) + resultType = complexResultType.getElementType(); + return cir::ComplexImagOp::create(*this, loc, resultType, operand); } cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr, diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 7f2e55d..c81f64d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3308,18 +3308,20 @@ def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> { def CIR_ComplexImagOp : CIR_Op<"complex.imag", [Pure]> { let summary = "Extract the imaginary part of a complex value"; let description = [{ - `cir.complex.imag` operation takes an operand of `!cir.complex` type and - yields the imaginary part of it. + `cir.complex.imag` operation takes an operand of `!cir.complex`, `!cir.int` + or `!cir.float`. If the operand is `!cir.complex`, the imag part of it will + be returned, otherwise a zero value will be returned. Example: ```mlir - %1 = cir.complex.imag %0 : !cir.complex<!cir.float> -> !cir.float + %imag = cir.complex.imag %complex : !cir.complex<!cir.float> -> !cir.float + %imag = cir.complex.imag %scalar : !cir.float -> !cir.float ``` }]; let results = (outs CIR_AnyIntOrFloatType:$result); - let arguments = (ins CIR_ComplexType:$operand); + let arguments = (ins CIR_AnyComplexOrIntOrFloatType:$operand); let assemblyFormat = [{ $operand `:` qualified(type($operand)) `->` qualified(type($result)) diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index e943b02..0f4d6d2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -718,10 +718,26 @@ void CIRGenFunction::emitAtomicInit(Expr *init, LValue dest) { return; } - case cir::TEK_Aggregate: - cgm.errorNYI(init->getSourceRange(), "emitAtomicInit: aggregate type"); + case cir::TEK_Aggregate: { + // Fix up the destination if the initializer isn't an expression + // of atomic type. + bool zeroed = false; + if (!init->getType()->isAtomicType()) { + zeroed = atomics.emitMemSetZeroIfNecessary(); + dest = atomics.projectValue(); + } + + // Evaluate the expression directly into the destination. + assert(!cir::MissingFeatures::aggValueSlotGC()); + AggValueSlot slot = AggValueSlot::forLValue( + dest, AggValueSlot::IsNotDestructed, AggValueSlot::IsNotAliased, + AggValueSlot::DoesNotOverlap, + zeroed ? AggValueSlot::IsZeroed : AggValueSlot::IsNotZeroed); + + emitAggExpr(init, slot); return; } + } llvm_unreachable("bad evaluation kind"); } diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 2970b36..61072f0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -522,7 +522,8 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo, assert(!cir::MissingFeatures::opCallPaddingArgs()); mlir::Type argType = convertType(canQualArgType); - if (!mlir::isa<cir::RecordType>(argType)) { + if (!mlir::isa<cir::RecordType>(argType) && + !mlir::isa<cir::ComplexType>(argType)) { mlir::Value v; if (arg.isAggregate()) cgm.errorNYI(loc, "emitCall: aggregate call argument"); @@ -540,15 +541,16 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo, cirCallArgs[argNo] = v; } else { Address src = Address::invalid(); - if (!arg.isAggregate()) - cgm.errorNYI(loc, "emitCall: non-aggregate call argument"); - else + if (!arg.isAggregate()) { + src = createMemTemp(arg.ty, loc, "coerce"); + arg.copyInto(*this, src, loc); + } else { src = arg.hasLValue() ? arg.getKnownLValue().getAddress() : arg.getKnownRValue().getAggregateAddress(); + } // Fast-isel and the optimizer generally like scalar values better than // FCAs, so we flatten them if this is safe to do for this argument. - auto argRecordTy = cast<cir::RecordType>(argType); mlir::Type srcTy = src.getElementType(); // FIXME(cir): get proper location for each argument. mlir::Location argLoc = loc; @@ -564,7 +566,7 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo, // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy); // if (SrcSize < DstSize) { assert(!cir::MissingFeatures::dataLayoutTypeAllocSize()); - if (srcTy != argRecordTy) { + if (srcTy != argType) { cgm.errorNYI(loc, "emitCall: source type does not match argument type"); } else { // FIXME(cir): this currently only runs when the types are exactly the @@ -676,6 +678,18 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo, llvm_unreachable("Invalid evaluation kind"); } +void CallArg::copyInto(CIRGenFunction &cgf, Address addr, + mlir::Location loc) const { + LValue dst = cgf.makeAddrLValue(addr, ty); + if (!hasLV && rv.isScalar()) + cgf.cgm.errorNYI(loc, "copyInto scalar value"); + else if (!hasLV && rv.isComplex()) + cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true); + else + cgf.cgm.errorNYI(loc, "copyInto hasLV"); + isUsed = true; +} + void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType) { assert(argType->isReferenceType() == e->isGLValue() && diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h b/clang/lib/CIR/CodeGen/CIRGenCall.h index 52d541f..55b3d97 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.h +++ b/clang/lib/CIR/CodeGen/CIRGenCall.h @@ -224,6 +224,8 @@ public: } bool isAggregate() const { return hasLV || rv.isAggregate(); } + + void copyInto(CIRGenFunction &cgf, Address addr, mlir::Location loc) const; }; class CallArgList : public llvm::SmallVector<CallArg, 8> { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 1e987f3..e51c3fc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -144,10 +144,7 @@ public: void VisitUnaryCoawait(UnaryOperator *e) { cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitUnaryCoawait"); } - void VisitUnaryExtension(UnaryOperator *e) { - cgf.cgm.errorNYI(e->getSourceRange(), - "AggExprEmitter: VisitUnaryExtension"); - } + void VisitUnaryExtension(UnaryOperator *e) { Visit(e->getSubExpr()); } void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) { cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitSubstNonTypeTemplateParmExpr"); @@ -184,7 +181,8 @@ public: cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitBinAssign"); } void VisitBinComma(const BinaryOperator *e) { - cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitBinComma"); + cgf.emitIgnoredExpr(e->getLHS()); + Visit(e->getRHS()); } void VisitBinCmp(const BinaryOperator *e) { cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitBinCmp"); @@ -212,9 +210,11 @@ public: } void VisitChooseExpr(const ChooseExpr *e) { Visit(e->getChosenSubExpr()); } void VisitCXXParenListInitExpr(CXXParenListInitExpr *e) { - cgf.cgm.errorNYI(e->getSourceRange(), - "AggExprEmitter: VisitCXXParenListInitExpr"); + visitCXXParenListOrInitListExpr(e, e->getInitExprs(), + e->getInitializedFieldInUnion(), + e->getArrayFiller()); } + void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *e, llvm::Value *outerBegin = nullptr) { cgf.cgm.errorNYI(e->getSourceRange(), diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 500007f..768d75d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -2159,16 +2159,16 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e, // __imag on a scalar returns zero. Emit the subexpr to ensure side // effects are evaluated, but not the actual value. - if (op->isGLValue()) - cgf.emitLValue(op); - else if (!promotionTy.isNull()) - cgf.emitPromotedScalarExpr(op, promotionTy); - else - cgf.emitScalarExpr(op); - - mlir::Type valueTy = - cgf.convertType(promotionTy.isNull() ? e->getType() : promotionTy); - return builder.getNullValue(valueTy, loc); + mlir::Value operand; + if (op->isGLValue()) { + operand = cgf.emitLValue(op).getPointer(); + operand = cir::LoadOp::create(builder, loc, operand); + } else if (!promotionTy.isNull()) { + operand = cgf.emitPromotedScalarExpr(op, promotionTy); + } else { + operand = cgf.emitScalarExpr(op); + } + return builder.createComplexImag(loc, operand); } /// Return the size or alignment of the type of argument of the sizeof diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index fba094f..cdd4e3c 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2402,9 +2402,8 @@ OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) { LogicalResult cir::ComplexRealOp::verify() { mlir::Type operandTy = getOperand().getType(); - if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) { + if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) operandTy = complexOperandTy.getElementType(); - } if (getType() != operandTy) { emitOpError() << ": result type does not match operand type"; @@ -2431,14 +2430,22 @@ OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) { //===----------------------------------------------------------------------===// LogicalResult cir::ComplexImagOp::verify() { - if (getType() != getOperand().getType().getElementType()) { + mlir::Type operandTy = getOperand().getType(); + if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) + operandTy = complexOperandTy.getElementType(); + + if (getType() != operandTy) { emitOpError() << ": result type does not match operand type"; return failure(); } + return success(); } OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) { + if (!mlir::isa<cir::ComplexType>(getOperand().getType())) + return nullptr; + if (auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>()) return complexCreateOp.getOperand(1); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index bfb1262..1ff8cc5 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3061,8 +3061,19 @@ mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite( cir::ComplexImagOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType()); - rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>( - op, resultLLVMTy, adaptor.getOperand(), llvm::ArrayRef<std::int64_t>{1}); + mlir::Value operand = adaptor.getOperand(); + mlir::Location loc = op.getLoc(); + + if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) { + operand = mlir::LLVM::ExtractValueOp::create( + rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1}); + } else { + mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy); + operand = + mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr); + } + + rewriter.replaceOp(op, operand); return mlir::success(); } diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 9a61888..8ba23aa 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -1189,14 +1189,13 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, // parameter list of a synthesized CTAD guide. See also the FIXME in // test/SemaCXX/cxx20-ctad-type-alias.cpp:test25. Sema::CheckTemplateArgumentInfo CTAI; + for (auto TA : Output.arguments()) + if (SemaRef.CheckTemplateArgument( + TP, TA, F, F->getLocation(), F->getLocation(), + /*ArgumentPackIndex=*/-1, CTAI, + Sema::CheckTemplateArgumentKind::CTAK_Specified)) + return nullptr; if (Input.getArgument().getKind() == TemplateArgument::Pack) { - for (auto TA : Output.arguments()) { - if (SemaRef.CheckTemplateArgument( - TP, TA, F, F->getLocation(), F->getLocation(), - /*ArgumentPackIndex=*/-1, CTAI, - Sema::CheckTemplateArgumentKind::CTAK_Specified)) - return nullptr; - } // We will substitute the non-deduced template arguments with these // transformed (unpacked at this point) arguments, where that substitution // requires a pack for the corresponding parameter packs. @@ -1204,12 +1203,6 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, TemplateArgument::CreatePackCopy(Context, CTAI.SugaredConverted); } else { assert(Output.arguments().size() == 1); - TemplateArgumentLoc Transformed = Output.arguments()[0]; - if (SemaRef.CheckTemplateArgument( - TP, Transformed, F, F->getLocation(), F->getLocation(), - /*ArgumentPackIndex=*/-1, CTAI, - Sema::CheckTemplateArgumentKind::CTAK_Specified)) - return nullptr; TemplateArgsForBuildingFPrime[Index] = CTAI.SugaredConverted[0]; } } diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index ae69b24..3524b8b 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -1160,8 +1160,9 @@ void imag_on_scalar_glvalue() { // CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"] // CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init] -// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float -// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> +// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float +// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.float -> !cir.float +// CIR: cir.store{{.*}} %[[A_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> // LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4 // LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4 @@ -1205,9 +1206,10 @@ void imag_on_scalar_with_type_promotion() { // CIR: %[[A_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["a"] // CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init] -// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float -// CIR: %[[CONST_ZERO_F16:.*]] = cir.cast floating %[[CONST_ZERO]] : !cir.float -> !cir.f16 -// CIR: cir.store{{.*}} %[[CONST_ZERO_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16> +// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.f16>, !cir.f16 +// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.f16 -> !cir.f16 +// CIR: %[[A_IMAG_F16:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.f16 +// CIR: cir.store{{.*}} %[[A_IMAG_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16> // LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 2 // LLVM: %[[B_ADDR:.*]] = alloca half, i64 1, align 2 @@ -1225,8 +1227,8 @@ void imag_on_const_scalar() { // CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"] // CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init] // CIR: %[[CONST_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float -// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float -// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> +// CIR: %[[CONST_IMAG:.*]] = cir.complex.imag %[[CONST_ONE]] : !cir.float -> !cir.float +// CIR: cir.store{{.*}} %[[CONST_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float> // LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4 // LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4 @@ -1311,3 +1313,49 @@ void real_on_scalar_from_imag_with_type_promotion() { // OGCG: %[[A_IMAG_F32:.*]] = fpext half %[[A_IMAG]] to float // OGCG: %[[A_IMAG_F16:.*]] = fptrunc float %[[A_IMAG_F32]] to half // OGCG: store half %[[A_IMAG_F16]], ptr %[[B_ADDR]], align 2 + +void complex_type_parameter(float _Complex a) {} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init] +// CIR: cir.store %{{.*}}, %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering, +// Test will be updated when that is implemented + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: store { float, float } %{{.*}}, ptr %[[A_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: store <2 x float> %a.coerce, ptr %[[A_ADDR]], align 4 + +void complex_type_argument() { + float _Complex a; + complex_type_parameter(a); +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"] +// CIR: %[[ARG_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["coerce"] +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR: cir.store{{.*}} %[[TMP_A]], %[[ARG_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> +// CIR: %[[TMP_ARG:.*]] = cir.load{{.*}} %[[ARG_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR: cir.call @_Z22complex_type_parameterCf(%[[TMP_ARG]]) : (!cir.complex<!cir.float>) -> () + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[ARG_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM: store { float, float } %[[TMP_A]], ptr %[[ARG_ADDR]], align 4 +// LLVM: %[[TMP_ARG:.*]] = load { float, float }, ptr %[[ARG_ADDR]], align 4 +// LLVM: call void @_Z22complex_type_parameterCf({ float, float } %[[TMP_ARG]]) + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[ARG_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[ARG_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 0 +// OGCG: %[[ARG_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL]], ptr %[[ARG_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[ARG_IMAG_PTR]], align 4 +// OGCG: %[[TMP_ARG:.*]] = load <2 x float>, ptr %[[ARG_ADDR]], align 4 +// OGCG: call void @_Z22complex_type_parameterCf(<2 x float> noundef %[[TMP_ARG]]) diff --git a/clang/test/CIR/CodeGen/paren-init-list.cpp b/clang/test/CIR/CodeGen/paren-init-list.cpp new file mode 100644 index 0000000..0efa363 --- /dev/null +++ b/clang/test/CIR/CodeGen/paren-init-list.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + +struct CompleteS { + int a; + char b; +}; + +void cxx_paren_list_init_expr() { CompleteS a(1, 'a'); } + +// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init] +// CIR: %[[ELEM_0_PTR:.*]] = cir.get_member %[[A_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i> +// CIR: %[[ELEM_0_VAL:.*]] = cir.const #cir.int<1> : !s32i +// CIR: cir.store{{.*}} %[[ELEM_0_VAL]], %[[ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i> +// CIR: %[[ELEM_1_PTR:.*]] = cir.get_member %[[A_ADDR]][1] {name = "b"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s8i> +// CIR: %[[ELEM_1_VAL:.*]] = cir.const #cir.int<97> : !s8i +// CIR: cir.store{{.*}} %[[ELEM_1_VAL]], %[[ELEM_1_PTR]] : !s8i, !cir.ptr<!s8i> + +// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4 +// LLVM: %[[ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0 +// LLVM: store i32 1, ptr %[[ELEM_0_PTR]], align 4 +// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1 +// LLVM: store i8 97, ptr %[[ELEM_1_PTR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4 +// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[A_ADDR]], ptr align 4 @__const._Z24cxx_paren_list_init_exprv.a, i64 8, i1 false) diff --git a/clang/test/CIR/CodeGen/struct.cpp b/clang/test/CIR/CodeGen/struct.cpp index 96db82a..c68f742 100644 --- a/clang/test/CIR/CodeGen/struct.cpp +++ b/clang/test/CIR/CodeGen/struct.cpp @@ -183,3 +183,67 @@ void generic_selection() { // OGCG: %[[C_ADDR:.*]] = alloca i32, align 4 // OGCG: %[[D_ADDR:.*]] = alloca %struct.CompleteS, align 4 // OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[D_ADDR]], ptr align 4 %[[A_ADDR]], i64 8, i1 false) + +void atomic_init() { + _Atomic CompleteS a; + __c11_atomic_init(&a, {}); +} + +// CIR: cir.func{{.*}} @_Z11atomic_initv() +// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a"] +// CIR: %[[ELEM_0_PTR:.*]] = cir.get_member %[[A_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i> +// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i +// CIR: cir.store{{.*}} %[[CONST_0]], %[[ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i> +// CIR: %[[ELEM_1_PTR:.*]] = cir.get_member %[[A_ADDR]][1] {name = "b"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s8i> +// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s8i +// CIR: cir.store{{.*}} %[[CONST_0]], %[[ELEM_1_PTR]] : !s8i, !cir.ptr<!s8i> + +// LLVM: define{{.*}} void @_Z11atomic_initv() +// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 8 +// LLVM: %[[ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0 +// LLVM: store i32 0, ptr %[[ELEM_0_PTR]], align 8 +// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1 +// LLVM: store i8 0, ptr %[[ELEM_1_PTR]], align 4 + +// OGCG: define{{.*}} void @_Z11atomic_initv() +// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 8 +// OGCG: %[[ELEM_0_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: store i32 0, ptr %[[ELEM_0_PTR]], align 8 +// OGCG: %[[ELEM_1_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store i8 0, ptr %[[ELEM_1_PTR]], align 4 + +void unary_extension() { + CompleteS a = __extension__ CompleteS(); +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init] +// CIR: %[[ZERO_INIT:.*]] = cir.const #cir.zero : !rec_CompleteS +// CIR: cir.store{{.*}} %[[ZERO_INIT]], %[[A_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS> + +// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4 +// LLVM: store %struct.CompleteS zeroinitializer, ptr %[[A_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4 +// OGCG: call void @llvm.memset.p0.i64(ptr align 4 %[[A_ADDR]], i8 0, i64 8, i1 false) + +void bin_comma() { + CompleteS a = (CompleteS(), CompleteS()); +} + +// CIR: cir.func{{.*}} @_Z9bin_commav() +// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init] +// CIR: %[[TMP_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["agg.tmp0"] +// CIR: %[[ZERO:.*]] = cir.const #cir.zero : !rec_CompleteS +// CIR: cir.store{{.*}} %[[ZERO]], %[[TMP_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS> +// CIR: %[[ZERO:.*]] = cir.const #cir.zero : !rec_CompleteS +// CIR: cir.store{{.*}} %[[ZERO]], %[[A_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS> + +// LLVM: define{{.*}} void @_Z9bin_commav() +// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4 +// LLVM: %[[TMP_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4 +// LLVM: store %struct.CompleteS zeroinitializer, ptr %[[TMP_ADDR]], align 4 +// LLVM: store %struct.CompleteS zeroinitializer, ptr %[[A_ADDR]], align 4 + +// OGCG: define{{.*}} void @_Z9bin_commav() +// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4 +// OGCG: call void @llvm.memset.p0.i64(ptr align 4 %[[A_ADDR]], i8 0, i64 8, i1 false) |