19#include "llvm/IR/Constants.h"
20#include "llvm/IR/Instructions.h"
21#include "llvm/IR/MDBuilder.h"
22#include "llvm/IR/Metadata.h"
24using namespace CodeGen;
42 return cast<ComplexType>(cast<AtomicType>(
type)->getValueType());
47class ComplexExprEmitter
48 :
public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
53 bool FPHasBeenPromoted;
56 ComplexExprEmitter(
CodeGenFunction &cgf,
bool ir =
false,
bool ii =
false)
57 : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii),
58 FPHasBeenPromoted(
false) {}
64 bool TestAndClearIgnoreReal() {
69 bool TestAndClearIgnoreImag() {
106 llvm_unreachable(
"Stmt can't have complex result type!");
112 Result->getAggregateElement(1U));
113 return Visit(
E->getSubExpr());
117 return Visit(
GE->getResultExpr());
131 return Visit(
E->getSubExpr());
136 assert(Constant &&
"not a constant");
141 llvm::Constant *pair = Constant.
getValue();
143 pair->getAggregateElement(1U));
149 return emitConstant(Constant,
E);
150 return EmitLoadOfLValue(
E);
153 return EmitLoadOfLValue(
E);
163 return emitConstant(Constant, ME);
165 return EmitLoadOfLValue(ME);
184 if (
E->changesVolatileQualification())
185 return EmitLoadOfLValue(
E);
186 return EmitCast(
E->getCastKind(),
E->getSubExpr(),
E->
getType());
189 if (
const auto *ECE = dyn_cast<ExplicitCastExpr>(
E))
191 if (
E->changesVolatileQualification())
192 return EmitLoadOfLValue(
E);
193 return EmitCast(
E->getCastKind(),
E->getSubExpr(),
E->
getType());
200 bool isInc,
bool isPre) {
205 return VisitPrePostIncDec(
E,
false,
false);
208 return VisitPrePostIncDec(
E,
true,
false);
211 return VisitPrePostIncDec(
E,
false,
true);
214 return VisitPrePostIncDec(
E,
true,
true);
227 return Visit(
E->getSubExpr());
242 Scope.ForceCleanup({&Vals.first, &Vals.second});
248 llvm::Constant *
Null = llvm::Constant::getNullValue(CGF.
ConvertType(Elem));
254 llvm::Constant *
Null =
255 llvm::Constant::getNullValue(CGF.
ConvertType(Elem));
276 (
const BinOpInfo &));
282 ComplexPairTy EmitAlgebraicDiv(llvm::Value *A, llvm::Value *B, llvm::Value *
C,
284 ComplexPairTy EmitRangeReductionDiv(llvm::Value *A, llvm::Value *B,
285 llvm::Value *
C, llvm::Value *
D);
288 const BinOpInfo &Op);
294 const llvm::fltSemantics &ElementTypeSemantics =
296 const llvm::fltSemantics &HigherElementTypeSemantics =
305 if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <=
306 llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
311 FPHasBeenPromoted =
true;
321 bool IsComplexDivisor) {
323 QualType ElementType = CT->getElementType();
325 bool IsComplexRangePromoted = CGF.
getLangOpts().getComplexRange() ==
326 LangOptions::ComplexRangeKind::CX_Promoted;
327 bool HasNoComplexRangeOverride = !Features.hasComplexRangeOverride();
328 bool HasMatchingComplexRange = Features.hasComplexRangeOverride() &&
329 Features.getComplexRangeOverride() ==
332 if (IsComplexDivisor && IsFloatingType && IsComplexRangePromoted &&
333 (HasNoComplexRangeOverride || HasMatchingComplexRange))
334 return HigherPrecisionTypeForComplexArithmetic(ElementType);
343#define HANDLEBINOP(OP) \
344 ComplexPairTy VisitBin##OP(const BinaryOperator *E) { \
345 QualType promotionTy = \
346 getPromotionType(E->getStoredFPFeaturesOrDefault(), E->getType(), \
347 (E->getOpcode() == BinaryOperatorKind::BO_Div && \
348 E->getRHS()->getType()->isAnyComplexType())); \
349 ComplexPairTy result = EmitBin##OP(EmitBinOps(E, promotionTy)); \
350 if (!promotionTy.isNull()) \
351 result = CGF.EmitUnPromotedValue(result, E->getType()); \
362 return Visit(
E->getSemanticForm());
368 return EmitCompoundAssign(
E, &ComplexExprEmitter::EmitBinAdd);
372 return EmitCompoundAssign(
E, &ComplexExprEmitter::EmitBinSub);
376 return EmitCompoundAssign(
E, &ComplexExprEmitter::EmitBinMul);
380 return EmitCompoundAssign(
E, &ComplexExprEmitter::EmitBinDiv);
401 return EmitLoadOfLValue(
E);
411 return Visit(
E->getSelectedExpr());
434 assert(lvalue.
isSimple() &&
"non-simple complex l-value?");
441 llvm::Value *Real =
nullptr, *Imag =
nullptr;
443 if (!IgnoreReal || isVolatile) {
445 Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr.
getName() +
".real");
448 if (!IgnoreImag || isVolatile) {
450 Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr.
getName() +
".imag");
486 llvm::Value *
U = llvm::PoisonValue::get(EltTy);
493 return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag);
498 if (
E->getCallReturnType(CGF.
getContext())->isReferenceType())
499 return EmitLoadOfLValue(
E);
507 assert(RetAlloca.
isValid() &&
"Expected complex return value");
531ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val,
540 return ComplexPairTy(Val, llvm::Constant::getNullValue(Val->getType()));
546 case CK_Dependent: llvm_unreachable(
"dependent cast kind in IR gen!");
550 case CK_AtomicToNonAtomic:
551 case CK_NonAtomicToAtomic:
553 case CK_LValueToRValue:
554 case CK_UserDefinedConversion:
557 case CK_LValueBitCast: {
563 case CK_LValueToRValueBitCast: {
569 return EmitLoadOfLValue(DestLV, Op->
getExprLoc());
573 case CK_BaseToDerived:
574 case CK_DerivedToBase:
575 case CK_UncheckedDerivedToBase:
578 case CK_ArrayToPointerDecay:
579 case CK_FunctionToPointerDecay:
580 case CK_NullToPointer:
581 case CK_NullToMemberPointer:
582 case CK_BaseToDerivedMemberPointer:
583 case CK_DerivedToBaseMemberPointer:
584 case CK_MemberPointerToBoolean:
585 case CK_ReinterpretMemberPointer:
586 case CK_ConstructorConversion:
587 case CK_IntegralToPointer:
588 case CK_PointerToIntegral:
589 case CK_PointerToBoolean:
592 case CK_IntegralCast:
593 case CK_BooleanToSignedIntegral:
594 case CK_IntegralToBoolean:
595 case CK_IntegralToFloating:
596 case CK_FloatingToIntegral:
597 case CK_FloatingToBoolean:
598 case CK_FloatingCast:
599 case CK_CPointerToObjCPointerCast:
600 case CK_BlockPointerToObjCPointerCast:
601 case CK_AnyPointerToBlockPointerCast:
602 case CK_ObjCObjectLValueCast:
603 case CK_FloatingComplexToReal:
604 case CK_FloatingComplexToBoolean:
605 case CK_IntegralComplexToReal:
606 case CK_IntegralComplexToBoolean:
607 case CK_ARCProduceObject:
608 case CK_ARCConsumeObject:
609 case CK_ARCReclaimReturnedObject:
610 case CK_ARCExtendBlockObject:
611 case CK_CopyAndAutoreleaseBlockObject:
612 case CK_BuiltinFnToFnPtr:
613 case CK_ZeroToOCLOpaqueType:
614 case CK_AddressSpaceConversion:
615 case CK_IntToOCLSampler:
616 case CK_FloatingToFixedPoint:
617 case CK_FixedPointToFloating:
618 case CK_FixedPointCast:
619 case CK_FixedPointToBoolean:
620 case CK_FixedPointToIntegral:
621 case CK_IntegralToFixedPoint:
623 case CK_HLSLVectorTruncation:
624 case CK_HLSLArrayRValue:
625 case CK_HLSLElementwiseCast:
626 case CK_HLSLAggregateSplatCast:
627 llvm_unreachable(
"invalid cast kind for complex value");
629 case CK_FloatingRealToComplex:
630 case CK_IntegralRealToComplex: {
636 case CK_FloatingComplexCast:
637 case CK_FloatingComplexToIntegralComplex:
638 case CK_IntegralComplexCast:
639 case CK_IntegralComplexToFloatingComplex: {
641 return EmitComplexToComplexCast(Visit(Op), Op->
getType(), DestTy,
646 llvm_unreachable(
"unknown cast resulting in complex value");
653 ? getPromotionType(
E->getStoredFPFeaturesOrDefault(),
658 if (!promotionTy.
isNull())
665 TestAndClearIgnoreReal();
666 TestAndClearIgnoreImag();
667 if (!PromotionType.
isNull())
669 return Visit(
E->getSubExpr());
676 ? getPromotionType(
E->getStoredFPFeaturesOrDefault(),
681 if (!promotionTy.
isNull())
687 TestAndClearIgnoreReal();
688 TestAndClearIgnoreImag();
690 if (!PromotionType.
isNull())
693 Op = Visit(
E->getSubExpr());
695 llvm::Value *ResR, *ResI;
696 if (Op.first->getType()->isFloatingPointTy()) {
697 ResR = Builder.CreateFNeg(Op.first,
"neg.r");
698 ResI = Builder.CreateFNeg(Op.second,
"neg.i");
700 ResR = Builder.CreateNeg(Op.first,
"neg.r");
701 ResI = Builder.CreateNeg(Op.second,
"neg.i");
707 TestAndClearIgnoreReal();
708 TestAndClearIgnoreImag();
712 if (Op.second->getType()->isFloatingPointTy())
713 ResI = Builder.CreateFNeg(Op.second,
"conj.i");
715 ResI = Builder.CreateNeg(Op.second,
"conj.i");
720ComplexPairTy ComplexExprEmitter::EmitBinAdd(
const BinOpInfo &Op) {
721 llvm::Value *ResR, *ResI;
723 if (Op.LHS.first->getType()->isFloatingPointTy()) {
725 ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first,
"add.r");
726 if (Op.LHS.second && Op.RHS.second)
727 ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second,
"add.i");
729 ResI = Op.LHS.second ? Op.LHS.second : Op.RHS.second;
730 assert(ResI &&
"Only one operand may be real!");
732 ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first,
"add.r");
733 assert(Op.LHS.second && Op.RHS.second &&
734 "Both operands of integer complex operators must be complex!");
735 ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second,
"add.i");
740ComplexPairTy ComplexExprEmitter::EmitBinSub(
const BinOpInfo &Op) {
741 llvm::Value *ResR, *ResI;
742 if (Op.LHS.first->getType()->isFloatingPointTy()) {
744 ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first,
"sub.r");
745 if (Op.LHS.second && Op.RHS.second)
746 ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second,
"sub.i");
748 ResI = Op.LHS.second ? Op.LHS.second
749 : Builder.CreateFNeg(Op.RHS.second,
"sub.i");
750 assert(ResI &&
"Only one operand may be real!");
752 ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first,
"sub.r");
753 assert(Op.LHS.second && Op.RHS.second &&
754 "Both operands of integer complex operators must be complex!");
755 ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second,
"sub.i");
761ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
762 const BinOpInfo &Op) {
786 Args, cast<FunctionType>(FQTy.
getTypePtr()),
false);
790 FTy, LibCallName, llvm::AttributeList(),
true);
793 llvm::CallBase *
Call;
802 switch (Ty->getTypeID()) {
804 llvm_unreachable(
"Unsupported floating point type!");
805 case llvm::Type::HalfTyID:
807 case llvm::Type::FloatTyID:
809 case llvm::Type::DoubleTyID:
811 case llvm::Type::PPC_FP128TyID:
813 case llvm::Type::X86_FP80TyID:
815 case llvm::Type::FP128TyID:
822ComplexPairTy ComplexExprEmitter::EmitBinMul(
const BinOpInfo &Op) {
827 if (Op.LHS.first->getType()->isFloatingPointTy()) {
835 if (Op.LHS.second && Op.RHS.second) {
846 Value *AC = Builder.CreateFMul(Op.LHS.first, Op.RHS.first,
"mul_ac");
847 Value *BD = Builder.CreateFMul(Op.LHS.second, Op.RHS.second,
"mul_bd");
848 Value *AD = Builder.CreateFMul(Op.LHS.first, Op.RHS.second,
"mul_ad");
849 Value *BC = Builder.CreateFMul(Op.LHS.second, Op.RHS.first,
"mul_bc");
853 ResR = Builder.CreateFSub(AC, BD,
"mul_r");
854 ResI = Builder.CreateFAdd(AD, BC,
"mul_i");
863 Value *IsRNaN = Builder.CreateFCmpUNO(ResR, ResR,
"isnan_cmp");
866 llvm::Instruction *Branch = Builder.CreateCondBr(IsRNaN, INaNBB, ContBB);
867 llvm::BasicBlock *OrigBB = Branch->getParent();
870 llvm::MDNode *BrWeight = MDHelper.createUnlikelyBranchWeights();
871 Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight);
875 Value *IsINaN = Builder.CreateFCmpUNO(ResI, ResI,
"isnan_cmp");
877 Branch = Builder.CreateCondBr(IsINaN, LibCallBB, ContBB);
878 Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight);
882 Value *LibCallR, *LibCallI;
883 std::tie(LibCallR, LibCallI) = EmitComplexBinOpLibCall(
885 Builder.CreateBr(ContBB);
890 llvm::PHINode *RealPHI = Builder.CreatePHI(ResR->
getType(), 3,
"real_mul_phi");
891 RealPHI->addIncoming(ResR, OrigBB);
892 RealPHI->addIncoming(ResR, INaNBB);
893 RealPHI->addIncoming(LibCallR, LibCallBB);
894 llvm::PHINode *ImagPHI = Builder.CreatePHI(ResI->
getType(), 3,
"imag_mul_phi");
895 ImagPHI->addIncoming(ResI, OrigBB);
896 ImagPHI->addIncoming(ResI, INaNBB);
897 ImagPHI->addIncoming(LibCallI, LibCallBB);
900 assert((Op.LHS.second || Op.RHS.second) &&
901 "At least one operand must be complex!");
906 ResR = Builder.CreateFMul(Op.LHS.first, Op.RHS.first,
"mul.rl");
909 ? Builder.CreateFMul(Op.LHS.second, Op.RHS.first,
"mul.il")
910 : Builder.CreateFMul(Op.LHS.first, Op.RHS.second,
"mul.ir");
912 assert(Op.LHS.second && Op.RHS.second &&
913 "Both operands of integer complex operators must be complex!");
914 Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first,
"mul.rl");
915 Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,
"mul.rr");
916 ResR = Builder.CreateSub(ResRl, ResRr,
"mul.r");
918 Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first,
"mul.il");
919 Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second,
"mul.ir");
920 ResI = Builder.CreateAdd(ResIl, ResIr,
"mul.i");
925ComplexPairTy ComplexExprEmitter::EmitAlgebraicDiv(llvm::Value *LHSr,
930 llvm::Value *DSTr, *DSTi;
932 llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr);
933 llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi);
934 llvm::Value *ACpBD = Builder.CreateFAdd(AC, BD);
936 llvm::Value *CC = Builder.CreateFMul(RHSr, RHSr);
937 llvm::Value *DD = Builder.CreateFMul(RHSi, RHSi);
938 llvm::Value *CCpDD = Builder.CreateFAdd(CC, DD);
940 llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr);
941 llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi);
942 llvm::Value *BCmAD = Builder.CreateFSub(BC, AD);
944 DSTr = Builder.CreateFDiv(ACpBD, CCpDD);
945 DSTi = Builder.CreateFDiv(BCmAD, CCpDD);
951 llvm::Function *
Func =
959ComplexPairTy ComplexExprEmitter::EmitRangeReductionDiv(llvm::Value *LHSr,
970 llvm::Value *IsR = Builder.CreateFCmpUGT(FAbsRHSr, FAbsRHSi,
"abs_cmp");
972 llvm::BasicBlock *TrueBB =
974 llvm::BasicBlock *FalseBB =
977 Builder.CreateCondBr(IsR, TrueBB, FalseBB);
985 llvm::Value *DdC = Builder.CreateFDiv(RHSi, RHSr);
987 llvm::Value *RD = Builder.CreateFMul(DdC, RHSi);
988 llvm::Value *CpRD = Builder.CreateFAdd(RHSr, RD);
990 llvm::Value *T3 = Builder.CreateFMul(LHSi, DdC);
991 llvm::Value *T4 = Builder.CreateFAdd(LHSr, T3);
992 llvm::Value *DSTTr = Builder.CreateFDiv(T4, CpRD);
994 llvm::Value *T5 = Builder.CreateFMul(LHSr, DdC);
995 llvm::Value *T6 = Builder.CreateFSub(LHSi, T5);
996 llvm::Value *DSTTi = Builder.CreateFDiv(T6, CpRD);
997 Builder.CreateBr(ContBB);
1005 llvm::Value *CdD = Builder.CreateFDiv(RHSr, RHSi);
1007 llvm::Value *RC = Builder.CreateFMul(CdD, RHSr);
1008 llvm::Value *DpRC = Builder.CreateFAdd(RHSi, RC);
1010 llvm::Value *T7 = Builder.CreateFMul(LHSr, CdD);
1011 llvm::Value *T8 = Builder.CreateFAdd(T7, LHSi);
1012 llvm::Value *DSTFr = Builder.CreateFDiv(T8, DpRC);
1014 llvm::Value *T9 = Builder.CreateFMul(LHSi, CdD);
1015 llvm::Value *T10 = Builder.CreateFSub(T9, LHSr);
1016 llvm::Value *DSTFi = Builder.CreateFDiv(T10, DpRC);
1017 Builder.CreateBr(ContBB);
1021 llvm::PHINode *VALr = Builder.CreatePHI(DSTTr->getType(), 2);
1022 VALr->addIncoming(DSTTr, TrueBB);
1023 VALr->addIncoming(DSTFr, FalseBB);
1024 llvm::PHINode *VALi = Builder.CreatePHI(DSTTi->getType(), 2);
1025 VALi->addIncoming(DSTTi, TrueBB);
1026 VALi->addIncoming(DSTFi, FalseBB);
1032ComplexPairTy ComplexExprEmitter::EmitBinDiv(
const BinOpInfo &Op) {
1033 llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second;
1034 llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second;
1035 llvm::Value *DSTr, *DSTi;
1036 if (LHSr->getType()->isFloatingPointTy()) {
1039 assert(LHSi &&
"Can have at most one non-complex operand!");
1041 DSTr = Builder.CreateFDiv(LHSr, RHSr);
1042 DSTi = Builder.CreateFDiv(LHSi, RHSr);
1045 llvm::Value *OrigLHSi = LHSi;
1047 LHSi = llvm::Constant::getNullValue(RHSi->getType());
1050 !FPHasBeenPromoted))
1051 return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi);
1054 return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi);
1063 BinOpInfo LibCallOp = Op;
1066 LibCallOp.LHS.second = llvm::Constant::getNullValue(LHSr->getType());
1068 switch (LHSr->getType()->getTypeID()) {
1070 llvm_unreachable(
"Unsupported floating point type!");
1071 case llvm::Type::HalfTyID:
1072 return EmitComplexBinOpLibCall(
"__divhc3", LibCallOp);
1073 case llvm::Type::FloatTyID:
1074 return EmitComplexBinOpLibCall(
"__divsc3", LibCallOp);
1075 case llvm::Type::DoubleTyID:
1076 return EmitComplexBinOpLibCall(
"__divdc3", LibCallOp);
1077 case llvm::Type::PPC_FP128TyID:
1078 return EmitComplexBinOpLibCall(
"__divtc3", LibCallOp);
1079 case llvm::Type::X86_FP80TyID:
1080 return EmitComplexBinOpLibCall(
"__divxc3", LibCallOp);
1081 case llvm::Type::FP128TyID:
1082 return EmitComplexBinOpLibCall(
"__divtc3", LibCallOp);
1085 return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi);
1088 assert(Op.LHS.second && Op.RHS.second &&
1089 "Both operands of integer complex operators must be complex!");
1091 llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr);
1092 llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi);
1093 llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2);
1095 llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr);
1096 llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi);
1097 llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5);
1099 llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr);
1100 llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi);
1101 llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8);
1104 DSTr = Builder.CreateUDiv(Tmp3, Tmp6);
1105 DSTi = Builder.CreateUDiv(Tmp9, Tmp6);
1107 DSTr = Builder.CreateSDiv(Tmp3, Tmp6);
1108 DSTi = Builder.CreateSDiv(Tmp9, Tmp6);
1117 llvm::Type *ComplexElementTy =
1121 Builder.CreateFPTrunc(result.first, ComplexElementTy,
"unpromotion");
1124 Builder.CreateFPTrunc(result.second, ComplexElementTy,
"unpromotion");
1130 llvm::Type *ComplexElementTy =
1133 result.first =
Builder.CreateFPExt(result.first, ComplexElementTy,
"ext");
1135 result.second =
Builder.CreateFPExt(result.second, ComplexElementTy,
"ext");
1143 if (
auto BO = dyn_cast<BinaryOperator>(
E)) {
1144 switch (BO->getOpcode()) {
1145#define HANDLE_BINOP(OP) \
1147 return EmitBin##OP(EmitBinOps(BO, PromotionType));
1156 }
else if (
auto UO = dyn_cast<UnaryOperator>(
E)) {
1157 switch (UO->getOpcode()) {
1159 return VisitMinus(UO, PromotionType);
1161 return VisitPlus(UO, PromotionType);
1166 auto result = Visit(
const_cast<Expr *
>(
E));
1167 if (!PromotionType.
isNull())
1175 return ComplexExprEmitter(*this).EmitPromoted(
E, DstTy);
1179ComplexExprEmitter::EmitPromotedComplexOperand(
const Expr *
E,
1182 if (!OverallPromotionType.
isNull())
1185 return Visit(
const_cast<Expr *
>(
E));
1187 if (!OverallPromotionType.
isNull()) {
1198ComplexExprEmitter::BinOpInfo
1201 TestAndClearIgnoreReal();
1202 TestAndClearIgnoreImag();
1205 Ops.LHS = EmitPromotedComplexOperand(
E->getLHS(), PromotionType);
1206 Ops.RHS = EmitPromotedComplexOperand(
E->getRHS(), PromotionType);
1207 if (!PromotionType.
isNull())
1208 Ops.Ty = PromotionType;
1216LValue ComplexExprEmitter::
1220 TestAndClearIgnoreReal();
1221 TestAndClearIgnoreImag();
1224 LHSTy = AT->getValueType();
1230 const bool IsComplexDivisor =
E->getOpcode() == BO_DivAssign &&
1238 getPromotionType(
E->getStoredFPFeaturesOrDefault(),
1239 E->getComputationResultType(), IsComplexDivisor);
1240 if (PromotionTypeCR.
isNull())
1241 PromotionTypeCR =
E->getComputationResultType();
1242 OpInfo.Ty = PromotionTypeCR;
1246 getPromotionType(
E->getStoredFPFeaturesOrDefault(),
1247 E->getRHS()->
getType(), IsComplexDivisor);
1251 if (!PromotionTypeRHS.
isNull())
1261 if (!PromotionTypeRHS.
isNull()) {
1267 OpInfo.RHS = Visit(
E->getRHS());
1276 getPromotionType(
E->getStoredFPFeaturesOrDefault(),
1277 E->getComputationLHSType(), IsComplexDivisor);
1280 if (!PromotionTypeLHS.
isNull())
1282 EmitComplexToComplexCast(LHSVal, LHSTy, PromotionTypeLHS,
Loc);
1284 OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty,
Loc);
1291 if (!PromotionTypeLHS.
isNull()) {
1292 PromotedComplexElementTy =
1293 cast<ComplexType>(PromotionTypeLHS)->getElementType();
1297 PromotedComplexElementTy,
Loc);
1305 OpInfo.LHS = EmitScalarToComplexCast(LHSVal, LHSTy, OpInfo.Ty,
Loc);
1315 EmitComplexToComplexCast(
Result, OpInfo.Ty, LHSTy,
Loc);
1316 EmitStoreOfComplex(ResVal, LHS,
false);
1319 llvm::Value *ResVal =
1333 LValue LV = EmitCompoundAssignLValue(
E,
Func, Val);
1350 "Invalid assignment");
1351 TestAndClearIgnoreReal();
1352 TestAndClearIgnoreImag();
1355 Val = Visit(
E->getRHS());
1361 EmitStoreOfComplex(Val, LHS,
false);
1369 LValue LV = EmitBinAssignLValue(
E, Val);
1384 return Visit(
E->getRHS());
1389 TestAndClearIgnoreReal();
1390 TestAndClearIgnoreImag();
1411 LHSBlock = Builder.GetInsertBlock();
1420 RHSBlock = Builder.GetInsertBlock();
1427 llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), 2,
"cond.r");
1428 RealPN->addIncoming(LHS.first, LHSBlock);
1429 RealPN->addIncoming(RHS.first, RHSBlock);
1432 llvm::PHINode *ImagPN = Builder.CreatePHI(LHS.first->getType(), 2,
"cond.i");
1433 ImagPN->addIncoming(LHS.second, LHSBlock);
1434 ImagPN->addIncoming(RHS.second, RHSBlock);
1440 return Visit(
E->getChosenSubExpr());
1444 bool Ignore = TestAndClearIgnoreReal();
1446 assert (Ignore ==
false &&
"init list ignored");
1447 Ignore = TestAndClearIgnoreImag();
1449 assert (Ignore ==
false &&
"init list ignored");
1451 if (
E->getNumInits() == 2) {
1455 }
else if (
E->getNumInits() == 1) {
1456 return Visit(
E->getInit(0));
1460 assert(
E->getNumInits() == 0 &&
"Unexpected number of inits");
1463 llvm::Value* zeroConstant = llvm::Constant::getNullValue(LTy);
1475 llvm::Value *
U = llvm::PoisonValue::get(EltTy);
1491 "Invalid complex expression to emit");
1493 return ComplexExprEmitter(*
this, IgnoreReal, IgnoreImag)
1494 .Visit(
const_cast<Expr *
>(
E));
1500 "Invalid complex expression to emit");
1501 ComplexExprEmitter
Emitter(*
this);
1503 Emitter.EmitStoreOfComplex(Val, dest, isInit);
1509 ComplexExprEmitter(*this).EmitStoreOfComplex(
V, dest, isInit);
1515 return ComplexExprEmitter(*this).EmitLoadOfLValue(src, loc);
1519 assert(
E->getOpcode() == BO_Assign);
1521 LValue LVal = ComplexExprEmitter(*this).EmitBinAssignLValue(
E, Val);
1529 const ComplexExprEmitter::BinOpInfo &);
1533 case BO_MulAssign:
return &ComplexExprEmitter::EmitBinMul;
1534 case BO_DivAssign:
return &ComplexExprEmitter::EmitBinDiv;
1535 case BO_SubAssign:
return &ComplexExprEmitter::EmitBinSub;
1536 case BO_AddAssign:
return &ComplexExprEmitter::EmitBinAdd;
1538 llvm_unreachable(
"unexpected complex compound assignment");
1547 return ComplexExprEmitter(*this).EmitCompoundAssignLValue(
E, Op, Val);
1557 LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(
E, Op, Val);
static const ComplexType * getComplexType(QualType type)
Return the complex type that we are meant to emit.
CodeGenFunction::ComplexPairTy ComplexPairTy
static llvm::Value * EmitllvmFAbs(CodeGenFunction &CGF, llvm::Value *Value)
static StringRef getComplexMultiplyLibCallName(llvm::Type *Ty)
Lookup the libcall name for a given floating point type complex multiply.
static CompoundFunc getComplexOp(BinaryOperatorKind op)
static const ComplexType * getComplexType(QualType type)
Return the complex type that we are meant to emit.
mlir::Value(ComplexExprEmitter::*)(const ComplexExprEmitter::BinOpInfo &) CompoundFunc
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
const QualType GetHigherPrecisionFPType(QualType ElementType) const
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
QualType getComplexType(QualType T) const
Return the uniqued reference to the type for a complex number with the specified element type.
const TargetInfo & getTargetInfo() const
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
A builtin binary operation expression such as "x + y" or "x <= y".
A default argument (C++ [dcl.fct.default]).
A use of a default initializer in a constructor or in aggregate initialization.
Expr * getExpr()
Get the initialization expression that will be used.
A rewritten comparison expression that was originally written using operator syntax.
An expression "T()" which creates an rvalue of a non-class type T.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Represents a 'co_await' expression.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::StringRef getName() const
Return the IR name of the pointer value.
A scoped helper to set the current source atom group for CGDebugInfo::addInstToCurrentSourceAtom.
A scoped helper to set the current debug location to the specified location or preferred location of ...
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
All available information about a concrete callee.
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
CGFunctionInfo - Class to encapsulate the information about a function definition.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
The scope of a CXXDefaultInitExpr.
An object to manage conditionally-evaluated expressions.
LValue getReferenceLValue(CodeGenFunction &CGF, const Expr *RefExpr) const
llvm::Constant * getValue() const
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
An RAII object to record that we're evaluating a statement expression.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
RValue EmitObjCMessageExpr(const ObjCMessageExpr *E, ReturnValueSlot Return=ReturnValueSlot())
ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, bool isInc, bool isPre)
void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)
EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...
llvm::Type * ConvertType(QualType T)
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
RValue EmitVAArg(VAArgExpr *VE, Address &VAListAddr, AggValueSlot Slot=AggValueSlot::ignored())
Generate code to get an argument from the passed in pointer and update it accordingly.
RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e, AggValueSlot slot=AggValueSlot::ignored())
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)
See CGDebugInfo::addInstToCurrentSourceAtom.
llvm::Value * EmitPromotedScalarExpr(const Expr *E, QualType PromotionType)
const LangOptions & getLangOpts() const
LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E)
ComplexPairTy EmitPromotedComplexExpr(const Expr *E, QualType PromotionType)
LValue EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E, llvm::Value *&Result)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue=ReturnValueSlot(), llvm::CallBase **CallOrInvoke=nullptr)
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
Address emitAddrOfImagComponent(Address complex, QualType complexType)
RValue EmitCoyieldExpr(const CoyieldExpr &E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its RValue mapping if it exists, otherwise create one.
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
CGDebugInfo * getDebugInfo()
LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its LValue mapping if it exists, otherwise create one.
ComplexPairTy EmitComplexExpr(const Expr *E, bool IgnoreReal=false, bool IgnoreImag=false)
EmitComplexExpr - Emit the computation of the specified expression of complex type,...
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast=false, AggValueSlot AVS=AggValueSlot::ignored())
EmitCompoundStmt - Emit a compound statement {..} node.
LValue EmitComplexAssignmentLValue(const BinaryOperator *E)
Emit an l-value for an assignment (simple or compound) of complex type.
llvm::Type * ConvertTypeForMem(QualType T)
RValue EmitAtomicExpr(AtomicExpr *E)
RValue EmitCoawaitExpr(const CoawaitExpr &E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
bool LValueIsSuitableForInlineAtomic(LValue Src)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
Address emitAddrOfRealComponent(Address complex, QualType complexType)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
ComplexPairTy EmitUnPromotedValue(ComplexPairTy result, QualType PromotionType)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
void ErrorUnsupported(const Stmt *S, const char *Type)
ErrorUnsupported - Print out an error that codegen doesn't support the specified stmt yet.
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
llvm::LLVMContext & getLLVMContext()
ComplexPairTy EmitPromotedValue(ComplexPairTy result, QualType PromotionType)
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExplicitCastExprType(const ExplicitCastExpr *E, CodeGenFunction *CGF=nullptr)
Emit type info if type of an expression is a variably modified type.
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
CodeGenTypes & getTypes()
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeFreeFunctionCall(const CallArgList &Args, const FunctionType *Ty, bool ChainCall)
Figure out the rules for calling a function with the given formal type using the given arguments.
LValue - This represents an lvalue references.
bool isVolatileQualified() const
void setTBAAInfo(TBAAAccessInfo Info)
Address getAddress() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Complex values, per C99 6.2.5p11.
QualType getElementType() const
CompoundAssignOperator - For compound assignments (e.g.
CompoundLiteralExpr - [C99 6.5.2.5].
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
Represents a 'co_yield' expression.
A reference to a declared variable, function, enum, etc.
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
This represents one expression.
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Returns the set of floating point options that apply to this expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a prototype with parameter type info, e.g.
Represents a C11 generic selection.
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
const Expr * getSubExpr() const
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Represents an implicitly-generated value initialization of an object of a given type.
Describes an C or C++ initializer list.
@ CX_Full
Implementation of complex division and multiplication using a call to runtime library functions(gener...
@ CX_Basic
Implementation of complex division and multiplication using algebraic formulas at source precision.
@ CX_Promoted
Implementation of complex division using algebraic formulas at higher precision.
@ CX_Improved
Implementation of complex division offering an improved handling for overflow in intermediate calcula...
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
An expression that sends a message to the given Objective-C object or class.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
ParenExpr - This represents a parenthesized expression, e.g.
const Expr * getSubExpr() const
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool UseExcessPrecision(const ASTContext &Ctx)
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
RetTy Visit(PTR(Stmt) S, ParamTys... P)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Expr * getReplacement() const
virtual bool hasLongDoubleType() const
Determine whether the long double type is supported on this target.
const T * castAs() const
Member-template castAs<specific type>.
bool isAnyComplexType() const
bool isAtomicType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const T * getAs() const
Member-template getAs<specific type>'.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represents a call to the builtin function __builtin_va_arg.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
Matches C99 complex types.
bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Descriptor *Desc)
bool GE(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
CastKind
CastKind - The kind of operation required for a conversion.
@ EST_BasicNoexcept
noexcept
Diagnostic wrappers for TextAPI types for error reporting.
cl::opt< bool > EnableSingleByteCoverage
llvm::CallingConv::ID getRuntimeCC() const
static TBAAAccessInfo getMayAliasInfo()
Holds information about the various types of exception specification.
Extra information about a function prototype.
ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &ESI)