| 1 | //===--- CGExprComplex.cpp - Emit LLVM Code for Complex Exprs -------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This contains code to emit Expr nodes with complex types as LLVM code. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "CGDebugInfo.h" |
| 14 | #include "CGOpenMPRuntime.h" |
| 15 | #include "CodeGenFunction.h" |
| 16 | #include "CodeGenModule.h" |
| 17 | #include "ConstantEmitter.h" |
| 18 | #include "clang/AST/StmtVisitor.h" |
| 19 | #include "llvm/IR/Constants.h" |
| 20 | #include "llvm/IR/Instructions.h" |
| 21 | #include "llvm/IR/MDBuilder.h" |
| 22 | #include "llvm/IR/Metadata.h" |
| 23 | using namespace clang; |
| 24 | using namespace CodeGen; |
| 25 | |
| 26 | //===----------------------------------------------------------------------===// |
| 27 | // Complex Expression Emitter |
| 28 | //===----------------------------------------------------------------------===// |
| 29 | |
| 30 | namespace llvm { |
| 31 | extern cl::opt<bool> EnableSingleByteCoverage; |
| 32 | } // namespace llvm |
| 33 | |
| 34 | typedef CodeGenFunction::ComplexPairTy ComplexPairTy; |
| 35 | |
| 36 | /// Return the complex type that we are meant to emit. |
| 37 | static const ComplexType *getComplexType(QualType type) { |
| 38 | type = type.getCanonicalType(); |
| 39 | if (const ComplexType *comp = dyn_cast<ComplexType>(Val&: type)) { |
| 40 | return comp; |
| 41 | } else { |
| 42 | return cast<ComplexType>(Val: cast<AtomicType>(Val&: type)->getValueType()); |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | namespace { |
| 47 | class ComplexExprEmitter |
| 48 | : public StmtVisitor<ComplexExprEmitter, ComplexPairTy> { |
| 49 | CodeGenFunction &CGF; |
| 50 | CGBuilderTy &Builder; |
| 51 | bool IgnoreReal; |
| 52 | bool IgnoreImag; |
| 53 | bool FPHasBeenPromoted; |
| 54 | |
| 55 | public: |
| 56 | ComplexExprEmitter(CodeGenFunction &cgf, bool ir = false, bool ii = false) |
| 57 | : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii), |
| 58 | FPHasBeenPromoted(false) {} |
| 59 | |
| 60 | //===--------------------------------------------------------------------===// |
| 61 | // Utilities |
| 62 | //===--------------------------------------------------------------------===// |
| 63 | |
| 64 | bool TestAndClearIgnoreReal() { |
| 65 | bool I = IgnoreReal; |
| 66 | IgnoreReal = false; |
| 67 | return I; |
| 68 | } |
| 69 | bool TestAndClearIgnoreImag() { |
| 70 | bool I = IgnoreImag; |
| 71 | IgnoreImag = false; |
| 72 | return I; |
| 73 | } |
| 74 | |
| 75 | /// EmitLoadOfLValue - Given an expression with complex type that represents a |
| 76 | /// value l-value, this method emits the address of the l-value, then loads |
| 77 | /// and returns the result. |
| 78 | ComplexPairTy EmitLoadOfLValue(const Expr *E) { |
| 79 | return EmitLoadOfLValue(LV: CGF.EmitLValue(E), Loc: E->getExprLoc()); |
| 80 | } |
| 81 | |
| 82 | ComplexPairTy EmitLoadOfLValue(LValue LV, SourceLocation Loc); |
| 83 | |
| 84 | /// EmitStoreOfComplex - Store the specified real/imag parts into the |
| 85 | /// specified value pointer. |
| 86 | void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit); |
| 87 | |
| 88 | /// Emit a cast from complex value Val to DestType. |
| 89 | ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType, |
| 90 | QualType DestType, SourceLocation Loc); |
| 91 | /// Emit a cast from scalar value Val to DestType. |
| 92 | ComplexPairTy EmitScalarToComplexCast(llvm::Value *Val, QualType SrcType, |
| 93 | QualType DestType, SourceLocation Loc); |
| 94 | |
| 95 | //===--------------------------------------------------------------------===// |
| 96 | // Visitor Methods |
| 97 | //===--------------------------------------------------------------------===// |
| 98 | |
| 99 | ComplexPairTy Visit(Expr *E) { |
| 100 | ApplyDebugLocation DL(CGF, E); |
| 101 | return StmtVisitor<ComplexExprEmitter, ComplexPairTy>::Visit(S: E); |
| 102 | } |
| 103 | |
| 104 | ComplexPairTy VisitStmt(Stmt *S) { |
| 105 | S->dump(OS&: llvm::errs(), Context: CGF.getContext()); |
| 106 | llvm_unreachable("Stmt can't have complex result type!" ); |
| 107 | } |
| 108 | ComplexPairTy VisitExpr(Expr *S); |
| 109 | ComplexPairTy VisitConstantExpr(ConstantExpr *E) { |
| 110 | if (llvm::Constant *Result = ConstantEmitter(CGF).tryEmitConstantExpr(CE: E)) |
| 111 | return ComplexPairTy(Result->getAggregateElement(Elt: 0U), |
| 112 | Result->getAggregateElement(Elt: 1U)); |
| 113 | return Visit(E: E->getSubExpr()); |
| 114 | } |
| 115 | ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(E: PE->getSubExpr());} |
| 116 | ComplexPairTy VisitGenericSelectionExpr(GenericSelectionExpr *GE) { |
| 117 | return Visit(E: GE->getResultExpr()); |
| 118 | } |
| 119 | ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL); |
| 120 | ComplexPairTy |
| 121 | VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE) { |
| 122 | return Visit(E: PE->getReplacement()); |
| 123 | } |
| 124 | ComplexPairTy VisitCoawaitExpr(CoawaitExpr *S) { |
| 125 | return CGF.EmitCoawaitExpr(E: *S).getComplexVal(); |
| 126 | } |
| 127 | ComplexPairTy VisitCoyieldExpr(CoyieldExpr *S) { |
| 128 | return CGF.EmitCoyieldExpr(E: *S).getComplexVal(); |
| 129 | } |
| 130 | ComplexPairTy VisitUnaryCoawait(const UnaryOperator *E) { |
| 131 | return Visit(E: E->getSubExpr()); |
| 132 | } |
| 133 | |
| 134 | ComplexPairTy emitConstant(const CodeGenFunction::ConstantEmission &Constant, |
| 135 | Expr *E) { |
| 136 | assert(Constant && "not a constant" ); |
| 137 | if (Constant.isReference()) |
| 138 | return EmitLoadOfLValue(LV: Constant.getReferenceLValue(CGF, RefExpr: E), |
| 139 | Loc: E->getExprLoc()); |
| 140 | |
| 141 | llvm::Constant *pair = Constant.getValue(); |
| 142 | return ComplexPairTy(pair->getAggregateElement(Elt: 0U), |
| 143 | pair->getAggregateElement(Elt: 1U)); |
| 144 | } |
| 145 | |
| 146 | // l-values. |
| 147 | ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) { |
| 148 | if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(RefExpr: E)) |
| 149 | return emitConstant(Constant, E); |
| 150 | return EmitLoadOfLValue(E); |
| 151 | } |
| 152 | ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { |
| 153 | return EmitLoadOfLValue(E); |
| 154 | } |
| 155 | ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) { |
| 156 | return CGF.EmitObjCMessageExpr(E).getComplexVal(); |
| 157 | } |
| 158 | ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); } |
| 159 | ComplexPairTy VisitMemberExpr(MemberExpr *ME) { |
| 160 | if (CodeGenFunction::ConstantEmission Constant = |
| 161 | CGF.tryEmitAsConstant(ME)) { |
| 162 | CGF.EmitIgnoredExpr(E: ME->getBase()); |
| 163 | return emitConstant(Constant, E: ME); |
| 164 | } |
| 165 | return EmitLoadOfLValue(E: ME); |
| 166 | } |
| 167 | ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) { |
| 168 | if (E->isGLValue()) |
| 169 | return EmitLoadOfLValue(LV: CGF.getOrCreateOpaqueLValueMapping(e: E), |
| 170 | Loc: E->getExprLoc()); |
| 171 | return CGF.getOrCreateOpaqueRValueMapping(e: E).getComplexVal(); |
| 172 | } |
| 173 | |
| 174 | ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) { |
| 175 | return CGF.EmitPseudoObjectRValue(e: E).getComplexVal(); |
| 176 | } |
| 177 | |
| 178 | // FIXME: CompoundLiteralExpr |
| 179 | |
| 180 | ComplexPairTy EmitCast(CastKind CK, Expr *Op, QualType DestTy); |
| 181 | ComplexPairTy VisitImplicitCastExpr(ImplicitCastExpr *E) { |
| 182 | // Unlike for scalars, we don't have to worry about function->ptr demotion |
| 183 | // here. |
| 184 | if (E->changesVolatileQualification()) |
| 185 | return EmitLoadOfLValue(E); |
| 186 | return EmitCast(CK: E->getCastKind(), Op: E->getSubExpr(), DestTy: E->getType()); |
| 187 | } |
| 188 | ComplexPairTy VisitCastExpr(CastExpr *E) { |
| 189 | if (const auto *ECE = dyn_cast<ExplicitCastExpr>(Val: E)) |
| 190 | CGF.CGM.EmitExplicitCastExprType(E: ECE, CGF: &CGF); |
| 191 | if (E->changesVolatileQualification()) |
| 192 | return EmitLoadOfLValue(E); |
| 193 | return EmitCast(CK: E->getCastKind(), Op: E->getSubExpr(), DestTy: E->getType()); |
| 194 | } |
| 195 | ComplexPairTy VisitCallExpr(const CallExpr *E); |
| 196 | ComplexPairTy VisitStmtExpr(const StmtExpr *E); |
| 197 | |
| 198 | // Operators. |
| 199 | ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E, |
| 200 | bool isInc, bool isPre) { |
| 201 | LValue LV = CGF.EmitLValue(E: E->getSubExpr()); |
| 202 | return CGF.EmitComplexPrePostIncDec(E, LV, isInc, isPre); |
| 203 | } |
| 204 | ComplexPairTy VisitUnaryPostDec(const UnaryOperator *E) { |
| 205 | return VisitPrePostIncDec(E, isInc: false, isPre: false); |
| 206 | } |
| 207 | ComplexPairTy VisitUnaryPostInc(const UnaryOperator *E) { |
| 208 | return VisitPrePostIncDec(E, isInc: true, isPre: false); |
| 209 | } |
| 210 | ComplexPairTy VisitUnaryPreDec(const UnaryOperator *E) { |
| 211 | return VisitPrePostIncDec(E, isInc: false, isPre: true); |
| 212 | } |
| 213 | ComplexPairTy VisitUnaryPreInc(const UnaryOperator *E) { |
| 214 | return VisitPrePostIncDec(E, isInc: true, isPre: true); |
| 215 | } |
| 216 | ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); } |
| 217 | |
| 218 | ComplexPairTy VisitUnaryPlus(const UnaryOperator *E, |
| 219 | QualType PromotionType = QualType()); |
| 220 | ComplexPairTy VisitPlus(const UnaryOperator *E, QualType PromotionType); |
| 221 | ComplexPairTy VisitUnaryMinus(const UnaryOperator *E, |
| 222 | QualType PromotionType = QualType()); |
| 223 | ComplexPairTy VisitMinus(const UnaryOperator *E, QualType PromotionType); |
| 224 | ComplexPairTy VisitUnaryNot (const UnaryOperator *E); |
| 225 | // LNot,Real,Imag never return complex. |
| 226 | ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) { |
| 227 | return Visit(E: E->getSubExpr()); |
| 228 | } |
| 229 | ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { |
| 230 | CodeGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE); |
| 231 | return Visit(E: DAE->getExpr()); |
| 232 | } |
| 233 | ComplexPairTy VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { |
| 234 | CodeGenFunction::CXXDefaultInitExprScope Scope(CGF, DIE); |
| 235 | return Visit(E: DIE->getExpr()); |
| 236 | } |
| 237 | ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) { |
| 238 | CodeGenFunction::RunCleanupsScope Scope(CGF); |
| 239 | ComplexPairTy Vals = Visit(E: E->getSubExpr()); |
| 240 | // Defend against dominance problems caused by jumps out of expression |
| 241 | // evaluation through the shared cleanup block. |
| 242 | Scope.ForceCleanup(ValuesToReload: {&Vals.first, &Vals.second}); |
| 243 | return Vals; |
| 244 | } |
| 245 | ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { |
| 246 | assert(E->getType()->isAnyComplexType() && "Expected complex type!" ); |
| 247 | QualType Elem = E->getType()->castAs<ComplexType>()->getElementType(); |
| 248 | llvm::Constant *Null = llvm::Constant::getNullValue(Ty: CGF.ConvertType(T: Elem)); |
| 249 | return ComplexPairTy(Null, Null); |
| 250 | } |
| 251 | ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { |
| 252 | assert(E->getType()->isAnyComplexType() && "Expected complex type!" ); |
| 253 | QualType Elem = E->getType()->castAs<ComplexType>()->getElementType(); |
| 254 | llvm::Constant *Null = |
| 255 | llvm::Constant::getNullValue(Ty: CGF.ConvertType(T: Elem)); |
| 256 | return ComplexPairTy(Null, Null); |
| 257 | } |
| 258 | |
| 259 | struct BinOpInfo { |
| 260 | ComplexPairTy LHS; |
| 261 | ComplexPairTy RHS; |
| 262 | QualType Ty; // Computation Type. |
| 263 | FPOptions FPFeatures; |
| 264 | }; |
| 265 | |
| 266 | BinOpInfo EmitBinOps(const BinaryOperator *E, |
| 267 | QualType PromotionTy = QualType()); |
| 268 | ComplexPairTy EmitPromoted(const Expr *E, QualType PromotionTy); |
| 269 | ComplexPairTy EmitPromotedComplexOperand(const Expr *E, QualType PromotionTy); |
| 270 | LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E, |
| 271 | ComplexPairTy (ComplexExprEmitter::*Func) |
| 272 | (const BinOpInfo &), |
| 273 | RValue &Val); |
| 274 | ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E, |
| 275 | ComplexPairTy (ComplexExprEmitter::*Func) |
| 276 | (const BinOpInfo &)); |
| 277 | |
| 278 | ComplexPairTy EmitBinAdd(const BinOpInfo &Op); |
| 279 | ComplexPairTy EmitBinSub(const BinOpInfo &Op); |
| 280 | ComplexPairTy EmitBinMul(const BinOpInfo &Op); |
| 281 | ComplexPairTy EmitBinDiv(const BinOpInfo &Op); |
| 282 | ComplexPairTy EmitAlgebraicDiv(llvm::Value *A, llvm::Value *B, llvm::Value *C, |
| 283 | llvm::Value *D); |
| 284 | ComplexPairTy EmitRangeReductionDiv(llvm::Value *A, llvm::Value *B, |
| 285 | llvm::Value *C, llvm::Value *D); |
| 286 | |
| 287 | ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName, |
| 288 | const BinOpInfo &Op); |
| 289 | |
| 290 | QualType HigherPrecisionTypeForComplexArithmetic(QualType ElementType) { |
| 291 | ASTContext &Ctx = CGF.getContext(); |
| 292 | const QualType HigherElementType = |
| 293 | Ctx.GetHigherPrecisionFPType(ElementType); |
| 294 | const llvm::fltSemantics &ElementTypeSemantics = |
| 295 | Ctx.getFloatTypeSemantics(T: ElementType); |
| 296 | const llvm::fltSemantics &HigherElementTypeSemantics = |
| 297 | Ctx.getFloatTypeSemantics(T: HigherElementType); |
| 298 | // Check that the promoted type can handle the intermediate values without |
| 299 | // overflowing. This can be interpreted as: |
| 300 | // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal) * 2 <= |
| 301 | // LargerType.LargestFiniteVal. |
| 302 | // In terms of exponent it gives this formula: |
| 303 | // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal |
| 304 | // doubles the exponent of SmallerType.LargestFiniteVal) |
| 305 | if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <= |
| 306 | llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) { |
| 307 | if (!Ctx.getTargetInfo().hasLongDoubleType() && |
| 308 | HigherElementType.getCanonicalType().getUnqualifiedType() == |
| 309 | Ctx.LongDoubleTy) |
| 310 | return QualType(); |
| 311 | FPHasBeenPromoted = true; |
| 312 | return Ctx.getComplexType(T: HigherElementType); |
| 313 | } else { |
| 314 | // The intermediate values can't be represented in the promoted type |
| 315 | // without overflowing. |
| 316 | return QualType(); |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | QualType getPromotionType(FPOptionsOverride Features, QualType Ty, |
| 321 | bool IsComplexDivisor) { |
| 322 | if (auto *CT = Ty->getAs<ComplexType>()) { |
| 323 | QualType ElementType = CT->getElementType(); |
| 324 | bool IsFloatingType = ElementType->isFloatingType(); |
| 325 | bool IsComplexRangePromoted = CGF.getLangOpts().getComplexRange() == |
| 326 | LangOptions::ComplexRangeKind::CX_Promoted; |
| 327 | bool HasNoComplexRangeOverride = !Features.hasComplexRangeOverride(); |
| 328 | bool HasMatchingComplexRange = Features.hasComplexRangeOverride() && |
| 329 | Features.getComplexRangeOverride() == |
| 330 | CGF.getLangOpts().getComplexRange(); |
| 331 | |
| 332 | if (IsComplexDivisor && IsFloatingType && IsComplexRangePromoted && |
| 333 | (HasNoComplexRangeOverride || HasMatchingComplexRange)) |
| 334 | return HigherPrecisionTypeForComplexArithmetic(ElementType); |
| 335 | if (ElementType.UseExcessPrecision(Ctx: CGF.getContext())) |
| 336 | return CGF.getContext().getComplexType(T: CGF.getContext().FloatTy); |
| 337 | } |
| 338 | if (Ty.UseExcessPrecision(Ctx: CGF.getContext())) |
| 339 | return CGF.getContext().FloatTy; |
| 340 | return QualType(); |
| 341 | } |
| 342 | |
| 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()); \ |
| 352 | return result; \ |
| 353 | } |
| 354 | |
| 355 | HANDLEBINOP(Mul) |
| 356 | HANDLEBINOP(Div) |
| 357 | HANDLEBINOP(Add) |
| 358 | HANDLEBINOP(Sub) |
| 359 | #undef HANDLEBINOP |
| 360 | |
| 361 | ComplexPairTy VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *E) { |
| 362 | return Visit(E: E->getSemanticForm()); |
| 363 | } |
| 364 | |
| 365 | // Compound assignments. |
| 366 | ComplexPairTy VisitBinAddAssign(const CompoundAssignOperator *E) { |
| 367 | ApplyAtomGroup Grp(CGF.getDebugInfo()); |
| 368 | return EmitCompoundAssign(E, Func: &ComplexExprEmitter::EmitBinAdd); |
| 369 | } |
| 370 | ComplexPairTy VisitBinSubAssign(const CompoundAssignOperator *E) { |
| 371 | ApplyAtomGroup Grp(CGF.getDebugInfo()); |
| 372 | return EmitCompoundAssign(E, Func: &ComplexExprEmitter::EmitBinSub); |
| 373 | } |
| 374 | ComplexPairTy VisitBinMulAssign(const CompoundAssignOperator *E) { |
| 375 | ApplyAtomGroup Grp(CGF.getDebugInfo()); |
| 376 | return EmitCompoundAssign(E, Func: &ComplexExprEmitter::EmitBinMul); |
| 377 | } |
| 378 | ComplexPairTy VisitBinDivAssign(const CompoundAssignOperator *E) { |
| 379 | ApplyAtomGroup Grp(CGF.getDebugInfo()); |
| 380 | return EmitCompoundAssign(E, Func: &ComplexExprEmitter::EmitBinDiv); |
| 381 | } |
| 382 | |
| 383 | // GCC rejects rem/and/or/xor for integer complex. |
| 384 | // Logical and/or always return int, never complex. |
| 385 | |
| 386 | // No comparisons produce a complex result. |
| 387 | |
| 388 | LValue EmitBinAssignLValue(const BinaryOperator *E, |
| 389 | ComplexPairTy &Val); |
| 390 | ComplexPairTy VisitBinAssign (const BinaryOperator *E); |
| 391 | ComplexPairTy VisitBinComma (const BinaryOperator *E); |
| 392 | |
| 393 | |
| 394 | ComplexPairTy |
| 395 | VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO); |
| 396 | ComplexPairTy VisitChooseExpr(ChooseExpr *CE); |
| 397 | |
| 398 | ComplexPairTy VisitInitListExpr(InitListExpr *E); |
| 399 | |
| 400 | ComplexPairTy VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { |
| 401 | return EmitLoadOfLValue(E); |
| 402 | } |
| 403 | |
| 404 | ComplexPairTy VisitVAArgExpr(VAArgExpr *E); |
| 405 | |
| 406 | ComplexPairTy VisitAtomicExpr(AtomicExpr *E) { |
| 407 | return CGF.EmitAtomicExpr(E).getComplexVal(); |
| 408 | } |
| 409 | |
| 410 | ComplexPairTy VisitPackIndexingExpr(PackIndexingExpr *E) { |
| 411 | return Visit(E: E->getSelectedExpr()); |
| 412 | } |
| 413 | }; |
| 414 | } // end anonymous namespace. |
| 415 | |
| 416 | //===----------------------------------------------------------------------===// |
| 417 | // Utilities |
| 418 | //===----------------------------------------------------------------------===// |
| 419 | |
| 420 | Address CodeGenFunction::emitAddrOfRealComponent(Address addr, |
| 421 | QualType complexType) { |
| 422 | return Builder.CreateStructGEP(Addr: addr, Index: 0, Name: addr.getName() + ".realp" ); |
| 423 | } |
| 424 | |
| 425 | Address CodeGenFunction::emitAddrOfImagComponent(Address addr, |
| 426 | QualType complexType) { |
| 427 | return Builder.CreateStructGEP(Addr: addr, Index: 1, Name: addr.getName() + ".imagp" ); |
| 428 | } |
| 429 | |
| 430 | /// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to |
| 431 | /// load the real and imaginary pieces, returning them as Real/Imag. |
| 432 | ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue, |
| 433 | SourceLocation loc) { |
| 434 | assert(lvalue.isSimple() && "non-simple complex l-value?" ); |
| 435 | if (lvalue.getType()->isAtomicType()) |
| 436 | return CGF.EmitAtomicLoad(LV: lvalue, SL: loc).getComplexVal(); |
| 437 | |
| 438 | Address SrcPtr = lvalue.getAddress(); |
| 439 | bool isVolatile = lvalue.isVolatileQualified(); |
| 440 | |
| 441 | llvm::Value *Real = nullptr, *Imag = nullptr; |
| 442 | |
| 443 | if (!IgnoreReal || isVolatile) { |
| 444 | Address RealP = CGF.emitAddrOfRealComponent(addr: SrcPtr, complexType: lvalue.getType()); |
| 445 | Real = Builder.CreateLoad(Addr: RealP, IsVolatile: isVolatile, Name: SrcPtr.getName() + ".real" ); |
| 446 | } |
| 447 | |
| 448 | if (!IgnoreImag || isVolatile) { |
| 449 | Address ImagP = CGF.emitAddrOfImagComponent(addr: SrcPtr, complexType: lvalue.getType()); |
| 450 | Imag = Builder.CreateLoad(Addr: ImagP, IsVolatile: isVolatile, Name: SrcPtr.getName() + ".imag" ); |
| 451 | } |
| 452 | |
| 453 | return ComplexPairTy(Real, Imag); |
| 454 | } |
| 455 | |
| 456 | /// EmitStoreOfComplex - Store the specified real/imag parts into the |
| 457 | /// specified value pointer. |
| 458 | void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue, |
| 459 | bool isInit) { |
| 460 | if (lvalue.getType()->isAtomicType() || |
| 461 | (!isInit && CGF.LValueIsSuitableForInlineAtomic(Src: lvalue))) |
| 462 | return CGF.EmitAtomicStore(rvalue: RValue::getComplex(C: Val), lvalue, isInit); |
| 463 | |
| 464 | Address Ptr = lvalue.getAddress(); |
| 465 | Address RealPtr = CGF.emitAddrOfRealComponent(addr: Ptr, complexType: lvalue.getType()); |
| 466 | Address ImagPtr = CGF.emitAddrOfImagComponent(addr: Ptr, complexType: lvalue.getType()); |
| 467 | |
| 468 | auto *R = |
| 469 | Builder.CreateStore(Val: Val.first, Addr: RealPtr, IsVolatile: lvalue.isVolatileQualified()); |
| 470 | CGF.addInstToCurrentSourceAtom(KeyInstruction: R, Backup: Val.first); |
| 471 | auto *I = |
| 472 | Builder.CreateStore(Val: Val.second, Addr: ImagPtr, IsVolatile: lvalue.isVolatileQualified()); |
| 473 | CGF.addInstToCurrentSourceAtom(KeyInstruction: I, Backup: Val.second); |
| 474 | } |
| 475 | |
| 476 | |
| 477 | |
| 478 | //===----------------------------------------------------------------------===// |
| 479 | // Visitor Methods |
| 480 | //===----------------------------------------------------------------------===// |
| 481 | |
| 482 | ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) { |
| 483 | CGF.ErrorUnsupported(S: E, Type: "complex expression" ); |
| 484 | llvm::Type *EltTy = |
| 485 | CGF.ConvertType(T: getComplexType(type: E->getType())->getElementType()); |
| 486 | llvm::Value *U = llvm::PoisonValue::get(T: EltTy); |
| 487 | return ComplexPairTy(U, U); |
| 488 | } |
| 489 | |
| 490 | ComplexPairTy ComplexExprEmitter:: |
| 491 | VisitImaginaryLiteral(const ImaginaryLiteral *IL) { |
| 492 | llvm::Value *Imag = CGF.EmitScalarExpr(E: IL->getSubExpr()); |
| 493 | return ComplexPairTy(llvm::Constant::getNullValue(Ty: Imag->getType()), Imag); |
| 494 | } |
| 495 | |
| 496 | |
| 497 | ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) { |
| 498 | if (E->getCallReturnType(Ctx: CGF.getContext())->isReferenceType()) |
| 499 | return EmitLoadOfLValue(E); |
| 500 | |
| 501 | return CGF.EmitCallExpr(E).getComplexVal(); |
| 502 | } |
| 503 | |
| 504 | ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) { |
| 505 | CodeGenFunction::StmtExprEvaluation eval(CGF); |
| 506 | Address RetAlloca = CGF.EmitCompoundStmt(S: *E->getSubStmt(), GetLast: true); |
| 507 | assert(RetAlloca.isValid() && "Expected complex return value" ); |
| 508 | return EmitLoadOfLValue(lvalue: CGF.MakeAddrLValue(Addr: RetAlloca, T: E->getType()), |
| 509 | loc: E->getExprLoc()); |
| 510 | } |
| 511 | |
| 512 | /// Emit a cast from complex value Val to DestType. |
| 513 | ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val, |
| 514 | QualType SrcType, |
| 515 | QualType DestType, |
| 516 | SourceLocation Loc) { |
| 517 | // Get the src/dest element type. |
| 518 | SrcType = SrcType->castAs<ComplexType>()->getElementType(); |
| 519 | DestType = DestType->castAs<ComplexType>()->getElementType(); |
| 520 | |
| 521 | // C99 6.3.1.6: When a value of complex type is converted to another |
| 522 | // complex type, both the real and imaginary parts follow the conversion |
| 523 | // rules for the corresponding real types. |
| 524 | if (Val.first) |
| 525 | Val.first = CGF.EmitScalarConversion(Src: Val.first, SrcTy: SrcType, DstTy: DestType, Loc); |
| 526 | if (Val.second) |
| 527 | Val.second = CGF.EmitScalarConversion(Src: Val.second, SrcTy: SrcType, DstTy: DestType, Loc); |
| 528 | return Val; |
| 529 | } |
| 530 | |
| 531 | ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val, |
| 532 | QualType SrcType, |
| 533 | QualType DestType, |
| 534 | SourceLocation Loc) { |
| 535 | // Convert the input element to the element type of the complex. |
| 536 | DestType = DestType->castAs<ComplexType>()->getElementType(); |
| 537 | Val = CGF.EmitScalarConversion(Src: Val, SrcTy: SrcType, DstTy: DestType, Loc); |
| 538 | |
| 539 | // Return (realval, 0). |
| 540 | return ComplexPairTy(Val, llvm::Constant::getNullValue(Ty: Val->getType())); |
| 541 | } |
| 542 | |
| 543 | ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, |
| 544 | QualType DestTy) { |
| 545 | switch (CK) { |
| 546 | case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!" ); |
| 547 | |
| 548 | // Atomic to non-atomic casts may be more than a no-op for some platforms and |
| 549 | // for some types. |
| 550 | case CK_AtomicToNonAtomic: |
| 551 | case CK_NonAtomicToAtomic: |
| 552 | case CK_NoOp: |
| 553 | case CK_LValueToRValue: |
| 554 | case CK_UserDefinedConversion: |
| 555 | return Visit(E: Op); |
| 556 | |
| 557 | case CK_LValueBitCast: { |
| 558 | LValue origLV = CGF.EmitLValue(E: Op); |
| 559 | Address V = origLV.getAddress().withElementType(ElemTy: CGF.ConvertType(T: DestTy)); |
| 560 | return EmitLoadOfLValue(lvalue: CGF.MakeAddrLValue(Addr: V, T: DestTy), loc: Op->getExprLoc()); |
| 561 | } |
| 562 | |
| 563 | case CK_LValueToRValueBitCast: { |
| 564 | LValue SourceLVal = CGF.EmitLValue(E: Op); |
| 565 | Address Addr = |
| 566 | SourceLVal.getAddress().withElementType(ElemTy: CGF.ConvertTypeForMem(T: DestTy)); |
| 567 | LValue DestLV = CGF.MakeAddrLValue(Addr, T: DestTy); |
| 568 | DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo()); |
| 569 | return EmitLoadOfLValue(lvalue: DestLV, loc: Op->getExprLoc()); |
| 570 | } |
| 571 | |
| 572 | case CK_BitCast: |
| 573 | case CK_BaseToDerived: |
| 574 | case CK_DerivedToBase: |
| 575 | case CK_UncheckedDerivedToBase: |
| 576 | case CK_Dynamic: |
| 577 | case CK_ToUnion: |
| 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: |
| 590 | case CK_ToVoid: |
| 591 | case CK_VectorSplat: |
| 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: |
| 622 | case CK_MatrixCast: |
| 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" ); |
| 628 | |
| 629 | case CK_FloatingRealToComplex: |
| 630 | case CK_IntegralRealToComplex: { |
| 631 | CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op); |
| 632 | return EmitScalarToComplexCast(Val: CGF.EmitScalarExpr(E: Op), SrcType: Op->getType(), |
| 633 | DestType: DestTy, Loc: Op->getExprLoc()); |
| 634 | } |
| 635 | |
| 636 | case CK_FloatingComplexCast: |
| 637 | case CK_FloatingComplexToIntegralComplex: |
| 638 | case CK_IntegralComplexCast: |
| 639 | case CK_IntegralComplexToFloatingComplex: { |
| 640 | CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op); |
| 641 | return EmitComplexToComplexCast(Val: Visit(E: Op), SrcType: Op->getType(), DestType: DestTy, |
| 642 | Loc: Op->getExprLoc()); |
| 643 | } |
| 644 | } |
| 645 | |
| 646 | llvm_unreachable("unknown cast resulting in complex value" ); |
| 647 | } |
| 648 | |
| 649 | ComplexPairTy ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *E, |
| 650 | QualType PromotionType) { |
| 651 | QualType promotionTy = |
| 652 | PromotionType.isNull() |
| 653 | ? getPromotionType(Features: E->getStoredFPFeaturesOrDefault(), |
| 654 | Ty: E->getSubExpr()->getType(), |
| 655 | /*IsComplexDivisor=*/false) |
| 656 | : PromotionType; |
| 657 | ComplexPairTy result = VisitPlus(E, PromotionType: promotionTy); |
| 658 | if (!promotionTy.isNull()) |
| 659 | return CGF.EmitUnPromotedValue(result, PromotionType: E->getSubExpr()->getType()); |
| 660 | return result; |
| 661 | } |
| 662 | |
| 663 | ComplexPairTy ComplexExprEmitter::VisitPlus(const UnaryOperator *E, |
| 664 | QualType PromotionType) { |
| 665 | TestAndClearIgnoreReal(); |
| 666 | TestAndClearIgnoreImag(); |
| 667 | if (!PromotionType.isNull()) |
| 668 | return CGF.EmitPromotedComplexExpr(E: E->getSubExpr(), PromotionType); |
| 669 | return Visit(E: E->getSubExpr()); |
| 670 | } |
| 671 | |
| 672 | ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E, |
| 673 | QualType PromotionType) { |
| 674 | QualType promotionTy = |
| 675 | PromotionType.isNull() |
| 676 | ? getPromotionType(Features: E->getStoredFPFeaturesOrDefault(), |
| 677 | Ty: E->getSubExpr()->getType(), |
| 678 | /*IsComplexDivisor=*/false) |
| 679 | : PromotionType; |
| 680 | ComplexPairTy result = VisitMinus(E, PromotionType: promotionTy); |
| 681 | if (!promotionTy.isNull()) |
| 682 | return CGF.EmitUnPromotedValue(result, PromotionType: E->getSubExpr()->getType()); |
| 683 | return result; |
| 684 | } |
| 685 | ComplexPairTy ComplexExprEmitter::VisitMinus(const UnaryOperator *E, |
| 686 | QualType PromotionType) { |
| 687 | TestAndClearIgnoreReal(); |
| 688 | TestAndClearIgnoreImag(); |
| 689 | ComplexPairTy Op; |
| 690 | if (!PromotionType.isNull()) |
| 691 | Op = CGF.EmitPromotedComplexExpr(E: E->getSubExpr(), PromotionType); |
| 692 | else |
| 693 | Op = Visit(E: E->getSubExpr()); |
| 694 | |
| 695 | llvm::Value *ResR, *ResI; |
| 696 | if (Op.first->getType()->isFloatingPointTy()) { |
| 697 | ResR = Builder.CreateFNeg(V: Op.first, Name: "neg.r" ); |
| 698 | ResI = Builder.CreateFNeg(V: Op.second, Name: "neg.i" ); |
| 699 | } else { |
| 700 | ResR = Builder.CreateNeg(V: Op.first, Name: "neg.r" ); |
| 701 | ResI = Builder.CreateNeg(V: Op.second, Name: "neg.i" ); |
| 702 | } |
| 703 | return ComplexPairTy(ResR, ResI); |
| 704 | } |
| 705 | |
| 706 | ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) { |
| 707 | TestAndClearIgnoreReal(); |
| 708 | TestAndClearIgnoreImag(); |
| 709 | // ~(a+ib) = a + i*-b |
| 710 | ComplexPairTy Op = Visit(E: E->getSubExpr()); |
| 711 | llvm::Value *ResI; |
| 712 | if (Op.second->getType()->isFloatingPointTy()) |
| 713 | ResI = Builder.CreateFNeg(V: Op.second, Name: "conj.i" ); |
| 714 | else |
| 715 | ResI = Builder.CreateNeg(V: Op.second, Name: "conj.i" ); |
| 716 | |
| 717 | return ComplexPairTy(Op.first, ResI); |
| 718 | } |
| 719 | |
| 720 | ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) { |
| 721 | llvm::Value *ResR, *ResI; |
| 722 | |
| 723 | if (Op.LHS.first->getType()->isFloatingPointTy()) { |
| 724 | CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); |
| 725 | ResR = Builder.CreateFAdd(L: Op.LHS.first, R: Op.RHS.first, Name: "add.r" ); |
| 726 | if (Op.LHS.second && Op.RHS.second) |
| 727 | ResI = Builder.CreateFAdd(L: Op.LHS.second, R: Op.RHS.second, Name: "add.i" ); |
| 728 | else |
| 729 | ResI = Op.LHS.second ? Op.LHS.second : Op.RHS.second; |
| 730 | assert(ResI && "Only one operand may be real!" ); |
| 731 | } else { |
| 732 | ResR = Builder.CreateAdd(LHS: Op.LHS.first, RHS: Op.RHS.first, Name: "add.r" ); |
| 733 | assert(Op.LHS.second && Op.RHS.second && |
| 734 | "Both operands of integer complex operators must be complex!" ); |
| 735 | ResI = Builder.CreateAdd(LHS: Op.LHS.second, RHS: Op.RHS.second, Name: "add.i" ); |
| 736 | } |
| 737 | return ComplexPairTy(ResR, ResI); |
| 738 | } |
| 739 | |
| 740 | ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) { |
| 741 | llvm::Value *ResR, *ResI; |
| 742 | if (Op.LHS.first->getType()->isFloatingPointTy()) { |
| 743 | CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); |
| 744 | ResR = Builder.CreateFSub(L: Op.LHS.first, R: Op.RHS.first, Name: "sub.r" ); |
| 745 | if (Op.LHS.second && Op.RHS.second) |
| 746 | ResI = Builder.CreateFSub(L: Op.LHS.second, R: Op.RHS.second, Name: "sub.i" ); |
| 747 | else |
| 748 | ResI = Op.LHS.second ? Op.LHS.second |
| 749 | : Builder.CreateFNeg(V: Op.RHS.second, Name: "sub.i" ); |
| 750 | assert(ResI && "Only one operand may be real!" ); |
| 751 | } else { |
| 752 | ResR = Builder.CreateSub(LHS: Op.LHS.first, RHS: Op.RHS.first, Name: "sub.r" ); |
| 753 | assert(Op.LHS.second && Op.RHS.second && |
| 754 | "Both operands of integer complex operators must be complex!" ); |
| 755 | ResI = Builder.CreateSub(LHS: Op.LHS.second, RHS: Op.RHS.second, Name: "sub.i" ); |
| 756 | } |
| 757 | return ComplexPairTy(ResR, ResI); |
| 758 | } |
| 759 | |
| 760 | /// Emit a libcall for a binary operation on complex types. |
| 761 | ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName, |
| 762 | const BinOpInfo &Op) { |
| 763 | CallArgList Args; |
| 764 | Args.add(rvalue: RValue::get(V: Op.LHS.first), |
| 765 | type: Op.Ty->castAs<ComplexType>()->getElementType()); |
| 766 | Args.add(rvalue: RValue::get(V: Op.LHS.second), |
| 767 | type: Op.Ty->castAs<ComplexType>()->getElementType()); |
| 768 | Args.add(rvalue: RValue::get(V: Op.RHS.first), |
| 769 | type: Op.Ty->castAs<ComplexType>()->getElementType()); |
| 770 | Args.add(rvalue: RValue::get(V: Op.RHS.second), |
| 771 | type: Op.Ty->castAs<ComplexType>()->getElementType()); |
| 772 | |
| 773 | // We *must* use the full CG function call building logic here because the |
| 774 | // complex type has special ABI handling. We also should not forget about |
| 775 | // special calling convention which may be used for compiler builtins. |
| 776 | |
| 777 | // We create a function qualified type to state that this call does not have |
| 778 | // any exceptions. |
| 779 | FunctionProtoType::ExtProtoInfo EPI; |
| 780 | EPI = EPI.withExceptionSpec( |
| 781 | ESI: FunctionProtoType::ExceptionSpecInfo(EST_BasicNoexcept)); |
| 782 | SmallVector<QualType, 4> ArgsQTys( |
| 783 | 4, Op.Ty->castAs<ComplexType>()->getElementType()); |
| 784 | QualType FQTy = CGF.getContext().getFunctionType(ResultTy: Op.Ty, Args: ArgsQTys, EPI); |
| 785 | const CGFunctionInfo &FuncInfo = CGF.CGM.getTypes().arrangeFreeFunctionCall( |
| 786 | Args, Ty: cast<FunctionType>(Val: FQTy.getTypePtr()), ChainCall: false); |
| 787 | |
| 788 | llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(Info: FuncInfo); |
| 789 | llvm::FunctionCallee Func = CGF.CGM.CreateRuntimeFunction( |
| 790 | Ty: FTy, Name: LibCallName, ExtraAttrs: llvm::AttributeList(), Local: true); |
| 791 | CGCallee Callee = CGCallee::forDirect(functionPtr: Func, abstractInfo: FQTy->getAs<FunctionProtoType>()); |
| 792 | |
| 793 | llvm::CallBase *Call; |
| 794 | RValue Res = CGF.EmitCall(CallInfo: FuncInfo, Callee, ReturnValue: ReturnValueSlot(), Args, CallOrInvoke: &Call); |
| 795 | Call->setCallingConv(CGF.CGM.getRuntimeCC()); |
| 796 | return Res.getComplexVal(); |
| 797 | } |
| 798 | |
| 799 | /// Lookup the libcall name for a given floating point type complex |
| 800 | /// multiply. |
| 801 | static StringRef getComplexMultiplyLibCallName(llvm::Type *Ty) { |
| 802 | switch (Ty->getTypeID()) { |
| 803 | default: |
| 804 | llvm_unreachable("Unsupported floating point type!" ); |
| 805 | case llvm::Type::HalfTyID: |
| 806 | return "__mulhc3" ; |
| 807 | case llvm::Type::FloatTyID: |
| 808 | return "__mulsc3" ; |
| 809 | case llvm::Type::DoubleTyID: |
| 810 | return "__muldc3" ; |
| 811 | case llvm::Type::PPC_FP128TyID: |
| 812 | return "__multc3" ; |
| 813 | case llvm::Type::X86_FP80TyID: |
| 814 | return "__mulxc3" ; |
| 815 | case llvm::Type::FP128TyID: |
| 816 | return "__multc3" ; |
| 817 | } |
| 818 | } |
| 819 | |
| 820 | // See C11 Annex G.5.1 for the semantics of multiplicative operators on complex |
| 821 | // typed values. |
| 822 | ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { |
| 823 | using llvm::Value; |
| 824 | Value *ResR, *ResI; |
| 825 | llvm::MDBuilder MDHelper(CGF.getLLVMContext()); |
| 826 | |
| 827 | if (Op.LHS.first->getType()->isFloatingPointTy()) { |
| 828 | // The general formulation is: |
| 829 | // (a + ib) * (c + id) = (a * c - b * d) + i(a * d + b * c) |
| 830 | // |
| 831 | // But we can fold away components which would be zero due to a real |
| 832 | // operand according to C11 Annex G.5.1p2. |
| 833 | |
| 834 | CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); |
| 835 | if (Op.LHS.second && Op.RHS.second) { |
| 836 | // If both operands are complex, emit the core math directly, and then |
| 837 | // test for NaNs. If we find NaNs in the result, we delegate to a libcall |
| 838 | // to carefully re-compute the correct infinity representation if |
| 839 | // possible. The expectation is that the presence of NaNs here is |
| 840 | // *extremely* rare, and so the cost of the libcall is almost irrelevant. |
| 841 | // This is good, because the libcall re-computes the core multiplication |
| 842 | // exactly the same as we do here and re-tests for NaNs in order to be |
| 843 | // a generic complex*complex libcall. |
| 844 | |
| 845 | // First compute the four products. |
| 846 | Value *AC = Builder.CreateFMul(L: Op.LHS.first, R: Op.RHS.first, Name: "mul_ac" ); |
| 847 | Value *BD = Builder.CreateFMul(L: Op.LHS.second, R: Op.RHS.second, Name: "mul_bd" ); |
| 848 | Value *AD = Builder.CreateFMul(L: Op.LHS.first, R: Op.RHS.second, Name: "mul_ad" ); |
| 849 | Value *BC = Builder.CreateFMul(L: Op.LHS.second, R: Op.RHS.first, Name: "mul_bc" ); |
| 850 | |
| 851 | // The real part is the difference of the first two, the imaginary part is |
| 852 | // the sum of the second. |
| 853 | ResR = Builder.CreateFSub(L: AC, R: BD, Name: "mul_r" ); |
| 854 | ResI = Builder.CreateFAdd(L: AD, R: BC, Name: "mul_i" ); |
| 855 | |
| 856 | if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic || |
| 857 | Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved || |
| 858 | Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted) |
| 859 | return ComplexPairTy(ResR, ResI); |
| 860 | |
| 861 | // Emit the test for the real part becoming NaN and create a branch to |
| 862 | // handle it. We test for NaN by comparing the number to itself. |
| 863 | Value *IsRNaN = Builder.CreateFCmpUNO(LHS: ResR, RHS: ResR, Name: "isnan_cmp" ); |
| 864 | llvm::BasicBlock *ContBB = CGF.createBasicBlock(name: "complex_mul_cont" ); |
| 865 | llvm::BasicBlock *INaNBB = CGF.createBasicBlock(name: "complex_mul_imag_nan" ); |
| 866 | llvm::Instruction *Branch = Builder.CreateCondBr(Cond: IsRNaN, True: INaNBB, False: ContBB); |
| 867 | llvm::BasicBlock *OrigBB = Branch->getParent(); |
| 868 | |
| 869 | // Give hint that we very much don't expect to see NaNs. |
| 870 | llvm::MDNode *BrWeight = MDHelper.createUnlikelyBranchWeights(); |
| 871 | Branch->setMetadata(KindID: llvm::LLVMContext::MD_prof, Node: BrWeight); |
| 872 | |
| 873 | // Now test the imaginary part and create its branch. |
| 874 | CGF.EmitBlock(BB: INaNBB); |
| 875 | Value *IsINaN = Builder.CreateFCmpUNO(LHS: ResI, RHS: ResI, Name: "isnan_cmp" ); |
| 876 | llvm::BasicBlock *LibCallBB = CGF.createBasicBlock(name: "complex_mul_libcall" ); |
| 877 | Branch = Builder.CreateCondBr(Cond: IsINaN, True: LibCallBB, False: ContBB); |
| 878 | Branch->setMetadata(KindID: llvm::LLVMContext::MD_prof, Node: BrWeight); |
| 879 | |
| 880 | // Now emit the libcall on this slowest of the slow paths. |
| 881 | CGF.EmitBlock(BB: LibCallBB); |
| 882 | Value *LibCallR, *LibCallI; |
| 883 | std::tie(args&: LibCallR, args&: LibCallI) = EmitComplexBinOpLibCall( |
| 884 | LibCallName: getComplexMultiplyLibCallName(Ty: Op.LHS.first->getType()), Op); |
| 885 | Builder.CreateBr(Dest: ContBB); |
| 886 | |
| 887 | // Finally continue execution by phi-ing together the different |
| 888 | // computation paths. |
| 889 | CGF.EmitBlock(BB: ContBB); |
| 890 | llvm::PHINode *RealPHI = Builder.CreatePHI(Ty: ResR->getType(), NumReservedValues: 3, Name: "real_mul_phi" ); |
| 891 | RealPHI->addIncoming(V: ResR, BB: OrigBB); |
| 892 | RealPHI->addIncoming(V: ResR, BB: INaNBB); |
| 893 | RealPHI->addIncoming(V: LibCallR, BB: LibCallBB); |
| 894 | llvm::PHINode *ImagPHI = Builder.CreatePHI(Ty: ResI->getType(), NumReservedValues: 3, Name: "imag_mul_phi" ); |
| 895 | ImagPHI->addIncoming(V: ResI, BB: OrigBB); |
| 896 | ImagPHI->addIncoming(V: ResI, BB: INaNBB); |
| 897 | ImagPHI->addIncoming(V: LibCallI, BB: LibCallBB); |
| 898 | return ComplexPairTy(RealPHI, ImagPHI); |
| 899 | } |
| 900 | assert((Op.LHS.second || Op.RHS.second) && |
| 901 | "At least one operand must be complex!" ); |
| 902 | |
| 903 | // If either of the operands is a real rather than a complex, the |
| 904 | // imaginary component is ignored when computing the real component of the |
| 905 | // result. |
| 906 | ResR = Builder.CreateFMul(L: Op.LHS.first, R: Op.RHS.first, Name: "mul.rl" ); |
| 907 | |
| 908 | ResI = Op.LHS.second |
| 909 | ? Builder.CreateFMul(L: Op.LHS.second, R: Op.RHS.first, Name: "mul.il" ) |
| 910 | : Builder.CreateFMul(L: Op.LHS.first, R: Op.RHS.second, Name: "mul.ir" ); |
| 911 | } else { |
| 912 | assert(Op.LHS.second && Op.RHS.second && |
| 913 | "Both operands of integer complex operators must be complex!" ); |
| 914 | Value *ResRl = Builder.CreateMul(LHS: Op.LHS.first, RHS: Op.RHS.first, Name: "mul.rl" ); |
| 915 | Value *ResRr = Builder.CreateMul(LHS: Op.LHS.second, RHS: Op.RHS.second, Name: "mul.rr" ); |
| 916 | ResR = Builder.CreateSub(LHS: ResRl, RHS: ResRr, Name: "mul.r" ); |
| 917 | |
| 918 | Value *ResIl = Builder.CreateMul(LHS: Op.LHS.second, RHS: Op.RHS.first, Name: "mul.il" ); |
| 919 | Value *ResIr = Builder.CreateMul(LHS: Op.LHS.first, RHS: Op.RHS.second, Name: "mul.ir" ); |
| 920 | ResI = Builder.CreateAdd(LHS: ResIl, RHS: ResIr, Name: "mul.i" ); |
| 921 | } |
| 922 | return ComplexPairTy(ResR, ResI); |
| 923 | } |
| 924 | |
| 925 | ComplexPairTy ComplexExprEmitter::EmitAlgebraicDiv(llvm::Value *LHSr, |
| 926 | llvm::Value *LHSi, |
| 927 | llvm::Value *RHSr, |
| 928 | llvm::Value *RHSi) { |
| 929 | // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) |
| 930 | llvm::Value *DSTr, *DSTi; |
| 931 | |
| 932 | llvm::Value *AC = Builder.CreateFMul(L: LHSr, R: RHSr); // a*c |
| 933 | llvm::Value *BD = Builder.CreateFMul(L: LHSi, R: RHSi); // b*d |
| 934 | llvm::Value *ACpBD = Builder.CreateFAdd(L: AC, R: BD); // ac+bd |
| 935 | |
| 936 | llvm::Value *CC = Builder.CreateFMul(L: RHSr, R: RHSr); // c*c |
| 937 | llvm::Value *DD = Builder.CreateFMul(L: RHSi, R: RHSi); // d*d |
| 938 | llvm::Value *CCpDD = Builder.CreateFAdd(L: CC, R: DD); // cc+dd |
| 939 | |
| 940 | llvm::Value *BC = Builder.CreateFMul(L: LHSi, R: RHSr); // b*c |
| 941 | llvm::Value *AD = Builder.CreateFMul(L: LHSr, R: RHSi); // a*d |
| 942 | llvm::Value *BCmAD = Builder.CreateFSub(L: BC, R: AD); // bc-ad |
| 943 | |
| 944 | DSTr = Builder.CreateFDiv(L: ACpBD, R: CCpDD); |
| 945 | DSTi = Builder.CreateFDiv(L: BCmAD, R: CCpDD); |
| 946 | return ComplexPairTy(DSTr, DSTi); |
| 947 | } |
| 948 | |
| 949 | // EmitFAbs - Emit a call to @llvm.fabs. |
| 950 | static llvm::Value *EmitllvmFAbs(CodeGenFunction &CGF, llvm::Value *Value) { |
| 951 | llvm::Function *Func = |
| 952 | CGF.CGM.getIntrinsic(IID: llvm::Intrinsic::fabs, Tys: Value->getType()); |
| 953 | llvm::Value *Call = CGF.Builder.CreateCall(Callee: Func, Args: Value); |
| 954 | return Call; |
| 955 | } |
| 956 | |
| 957 | // EmitRangeReductionDiv - Implements Smith's algorithm for complex division. |
| 958 | // SMITH, R. L. Algorithm 116: Complex division. Commun. ACM 5, 8 (1962). |
| 959 | ComplexPairTy ComplexExprEmitter::EmitRangeReductionDiv(llvm::Value *LHSr, |
| 960 | llvm::Value *LHSi, |
| 961 | llvm::Value *RHSr, |
| 962 | llvm::Value *RHSi) { |
| 963 | // FIXME: This could eventually be replaced by an LLVM intrinsic to |
| 964 | // avoid this long IR sequence. |
| 965 | |
| 966 | // (a + ib) / (c + id) = (e + if) |
| 967 | llvm::Value *FAbsRHSr = EmitllvmFAbs(CGF, Value: RHSr); // |c| |
| 968 | llvm::Value *FAbsRHSi = EmitllvmFAbs(CGF, Value: RHSi); // |d| |
| 969 | // |c| >= |d| |
| 970 | llvm::Value *IsR = Builder.CreateFCmpUGT(LHS: FAbsRHSr, RHS: FAbsRHSi, Name: "abs_cmp" ); |
| 971 | |
| 972 | llvm::BasicBlock *TrueBB = |
| 973 | CGF.createBasicBlock(name: "abs_rhsr_greater_or_equal_abs_rhsi" ); |
| 974 | llvm::BasicBlock *FalseBB = |
| 975 | CGF.createBasicBlock(name: "abs_rhsr_less_than_abs_rhsi" ); |
| 976 | llvm::BasicBlock *ContBB = CGF.createBasicBlock(name: "complex_div" ); |
| 977 | Builder.CreateCondBr(Cond: IsR, True: TrueBB, False: FalseBB); |
| 978 | |
| 979 | CGF.EmitBlock(BB: TrueBB); |
| 980 | // abs(c) >= abs(d) |
| 981 | // r = d/c |
| 982 | // tmp = c + rd |
| 983 | // e = (a + br)/tmp |
| 984 | // f = (b - ar)/tmp |
| 985 | llvm::Value *DdC = Builder.CreateFDiv(L: RHSi, R: RHSr); // r=d/c |
| 986 | |
| 987 | llvm::Value *RD = Builder.CreateFMul(L: DdC, R: RHSi); // rd |
| 988 | llvm::Value *CpRD = Builder.CreateFAdd(L: RHSr, R: RD); // tmp=c+rd |
| 989 | |
| 990 | llvm::Value *T3 = Builder.CreateFMul(L: LHSi, R: DdC); // br |
| 991 | llvm::Value *T4 = Builder.CreateFAdd(L: LHSr, R: T3); // a+br |
| 992 | llvm::Value *DSTTr = Builder.CreateFDiv(L: T4, R: CpRD); // (a+br)/tmp |
| 993 | |
| 994 | llvm::Value *T5 = Builder.CreateFMul(L: LHSr, R: DdC); // ar |
| 995 | llvm::Value *T6 = Builder.CreateFSub(L: LHSi, R: T5); // b-ar |
| 996 | llvm::Value *DSTTi = Builder.CreateFDiv(L: T6, R: CpRD); // (b-ar)/tmp |
| 997 | Builder.CreateBr(Dest: ContBB); |
| 998 | |
| 999 | CGF.EmitBlock(BB: FalseBB); |
| 1000 | // abs(c) < abs(d) |
| 1001 | // r = c/d |
| 1002 | // tmp = d + rc |
| 1003 | // e = (ar + b)/tmp |
| 1004 | // f = (br - a)/tmp |
| 1005 | llvm::Value *CdD = Builder.CreateFDiv(L: RHSr, R: RHSi); // r=c/d |
| 1006 | |
| 1007 | llvm::Value *RC = Builder.CreateFMul(L: CdD, R: RHSr); // rc |
| 1008 | llvm::Value *DpRC = Builder.CreateFAdd(L: RHSi, R: RC); // tmp=d+rc |
| 1009 | |
| 1010 | llvm::Value *T7 = Builder.CreateFMul(L: LHSr, R: CdD); // ar |
| 1011 | llvm::Value *T8 = Builder.CreateFAdd(L: T7, R: LHSi); // ar+b |
| 1012 | llvm::Value *DSTFr = Builder.CreateFDiv(L: T8, R: DpRC); // (ar+b)/tmp |
| 1013 | |
| 1014 | llvm::Value *T9 = Builder.CreateFMul(L: LHSi, R: CdD); // br |
| 1015 | llvm::Value *T10 = Builder.CreateFSub(L: T9, R: LHSr); // br-a |
| 1016 | llvm::Value *DSTFi = Builder.CreateFDiv(L: T10, R: DpRC); // (br-a)/tmp |
| 1017 | Builder.CreateBr(Dest: ContBB); |
| 1018 | |
| 1019 | // Phi together the computation paths. |
| 1020 | CGF.EmitBlock(BB: ContBB); |
| 1021 | llvm::PHINode *VALr = Builder.CreatePHI(Ty: DSTTr->getType(), NumReservedValues: 2); |
| 1022 | VALr->addIncoming(V: DSTTr, BB: TrueBB); |
| 1023 | VALr->addIncoming(V: DSTFr, BB: FalseBB); |
| 1024 | llvm::PHINode *VALi = Builder.CreatePHI(Ty: DSTTi->getType(), NumReservedValues: 2); |
| 1025 | VALi->addIncoming(V: DSTTi, BB: TrueBB); |
| 1026 | VALi->addIncoming(V: DSTFi, BB: FalseBB); |
| 1027 | return ComplexPairTy(VALr, VALi); |
| 1028 | } |
| 1029 | |
| 1030 | // See C11 Annex G.5.1 for the semantics of multiplicative operators on complex |
| 1031 | // typed values. |
| 1032 | ComplexPairTy 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()) { |
| 1037 | CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); |
| 1038 | if (!RHSi) { |
| 1039 | assert(LHSi && "Can have at most one non-complex operand!" ); |
| 1040 | |
| 1041 | DSTr = Builder.CreateFDiv(L: LHSr, R: RHSr); |
| 1042 | DSTi = Builder.CreateFDiv(L: LHSi, R: RHSr); |
| 1043 | return ComplexPairTy(DSTr, DSTi); |
| 1044 | } |
| 1045 | llvm::Value *OrigLHSi = LHSi; |
| 1046 | if (!LHSi) |
| 1047 | LHSi = llvm::Constant::getNullValue(Ty: RHSi->getType()); |
| 1048 | if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved || |
| 1049 | (Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted && |
| 1050 | !FPHasBeenPromoted)) |
| 1051 | return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi); |
| 1052 | else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic || |
| 1053 | Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted) |
| 1054 | return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi); |
| 1055 | // '-ffast-math' is used in the command line but followed by an |
| 1056 | // '-fno-cx-limited-range' or '-fcomplex-arithmetic=full'. |
| 1057 | else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Full) { |
| 1058 | LHSi = OrigLHSi; |
| 1059 | // If we have a complex operand on the RHS and FastMath is not allowed, we |
| 1060 | // delegate to a libcall to handle all of the complexities and minimize |
| 1061 | // underflow/overflow cases. When FastMath is allowed we construct the |
| 1062 | // divide inline using the same algorithm as for integer operands. |
| 1063 | BinOpInfo LibCallOp = Op; |
| 1064 | // If LHS was a real, supply a null imaginary part. |
| 1065 | if (!LHSi) |
| 1066 | LibCallOp.LHS.second = llvm::Constant::getNullValue(Ty: LHSr->getType()); |
| 1067 | |
| 1068 | switch (LHSr->getType()->getTypeID()) { |
| 1069 | default: |
| 1070 | llvm_unreachable("Unsupported floating point type!" ); |
| 1071 | case llvm::Type::HalfTyID: |
| 1072 | return EmitComplexBinOpLibCall(LibCallName: "__divhc3" , Op: LibCallOp); |
| 1073 | case llvm::Type::FloatTyID: |
| 1074 | return EmitComplexBinOpLibCall(LibCallName: "__divsc3" , Op: LibCallOp); |
| 1075 | case llvm::Type::DoubleTyID: |
| 1076 | return EmitComplexBinOpLibCall(LibCallName: "__divdc3" , Op: LibCallOp); |
| 1077 | case llvm::Type::PPC_FP128TyID: |
| 1078 | return EmitComplexBinOpLibCall(LibCallName: "__divtc3" , Op: LibCallOp); |
| 1079 | case llvm::Type::X86_FP80TyID: |
| 1080 | return EmitComplexBinOpLibCall(LibCallName: "__divxc3" , Op: LibCallOp); |
| 1081 | case llvm::Type::FP128TyID: |
| 1082 | return EmitComplexBinOpLibCall(LibCallName: "__divtc3" , Op: LibCallOp); |
| 1083 | } |
| 1084 | } else { |
| 1085 | return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi); |
| 1086 | } |
| 1087 | } else { |
| 1088 | assert(Op.LHS.second && Op.RHS.second && |
| 1089 | "Both operands of integer complex operators must be complex!" ); |
| 1090 | // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) |
| 1091 | llvm::Value *Tmp1 = Builder.CreateMul(LHS: LHSr, RHS: RHSr); // a*c |
| 1092 | llvm::Value *Tmp2 = Builder.CreateMul(LHS: LHSi, RHS: RHSi); // b*d |
| 1093 | llvm::Value *Tmp3 = Builder.CreateAdd(LHS: Tmp1, RHS: Tmp2); // ac+bd |
| 1094 | |
| 1095 | llvm::Value *Tmp4 = Builder.CreateMul(LHS: RHSr, RHS: RHSr); // c*c |
| 1096 | llvm::Value *Tmp5 = Builder.CreateMul(LHS: RHSi, RHS: RHSi); // d*d |
| 1097 | llvm::Value *Tmp6 = Builder.CreateAdd(LHS: Tmp4, RHS: Tmp5); // cc+dd |
| 1098 | |
| 1099 | llvm::Value *Tmp7 = Builder.CreateMul(LHS: LHSi, RHS: RHSr); // b*c |
| 1100 | llvm::Value *Tmp8 = Builder.CreateMul(LHS: LHSr, RHS: RHSi); // a*d |
| 1101 | llvm::Value *Tmp9 = Builder.CreateSub(LHS: Tmp7, RHS: Tmp8); // bc-ad |
| 1102 | |
| 1103 | if (Op.Ty->castAs<ComplexType>()->getElementType()->isUnsignedIntegerType()) { |
| 1104 | DSTr = Builder.CreateUDiv(LHS: Tmp3, RHS: Tmp6); |
| 1105 | DSTi = Builder.CreateUDiv(LHS: Tmp9, RHS: Tmp6); |
| 1106 | } else { |
| 1107 | DSTr = Builder.CreateSDiv(LHS: Tmp3, RHS: Tmp6); |
| 1108 | DSTi = Builder.CreateSDiv(LHS: Tmp9, RHS: Tmp6); |
| 1109 | } |
| 1110 | } |
| 1111 | |
| 1112 | return ComplexPairTy(DSTr, DSTi); |
| 1113 | } |
| 1114 | |
| 1115 | ComplexPairTy CodeGenFunction::EmitUnPromotedValue(ComplexPairTy result, |
| 1116 | QualType UnPromotionType) { |
| 1117 | llvm::Type *ComplexElementTy = |
| 1118 | ConvertType(T: UnPromotionType->castAs<ComplexType>()->getElementType()); |
| 1119 | if (result.first) |
| 1120 | result.first = |
| 1121 | Builder.CreateFPTrunc(V: result.first, DestTy: ComplexElementTy, Name: "unpromotion" ); |
| 1122 | if (result.second) |
| 1123 | result.second = |
| 1124 | Builder.CreateFPTrunc(V: result.second, DestTy: ComplexElementTy, Name: "unpromotion" ); |
| 1125 | return result; |
| 1126 | } |
| 1127 | |
| 1128 | ComplexPairTy CodeGenFunction::EmitPromotedValue(ComplexPairTy result, |
| 1129 | QualType PromotionType) { |
| 1130 | llvm::Type *ComplexElementTy = |
| 1131 | ConvertType(T: PromotionType->castAs<ComplexType>()->getElementType()); |
| 1132 | if (result.first) |
| 1133 | result.first = Builder.CreateFPExt(V: result.first, DestTy: ComplexElementTy, Name: "ext" ); |
| 1134 | if (result.second) |
| 1135 | result.second = Builder.CreateFPExt(V: result.second, DestTy: ComplexElementTy, Name: "ext" ); |
| 1136 | |
| 1137 | return result; |
| 1138 | } |
| 1139 | |
| 1140 | ComplexPairTy ComplexExprEmitter::EmitPromoted(const Expr *E, |
| 1141 | QualType PromotionType) { |
| 1142 | E = E->IgnoreParens(); |
| 1143 | if (auto BO = dyn_cast<BinaryOperator>(Val: E)) { |
| 1144 | switch (BO->getOpcode()) { |
| 1145 | #define HANDLE_BINOP(OP) \ |
| 1146 | case BO_##OP: \ |
| 1147 | return EmitBin##OP(EmitBinOps(BO, PromotionType)); |
| 1148 | HANDLE_BINOP(Add) |
| 1149 | HANDLE_BINOP(Sub) |
| 1150 | HANDLE_BINOP(Mul) |
| 1151 | HANDLE_BINOP(Div) |
| 1152 | #undef HANDLE_BINOP |
| 1153 | default: |
| 1154 | break; |
| 1155 | } |
| 1156 | } else if (auto UO = dyn_cast<UnaryOperator>(Val: E)) { |
| 1157 | switch (UO->getOpcode()) { |
| 1158 | case UO_Minus: |
| 1159 | return VisitMinus(E: UO, PromotionType); |
| 1160 | case UO_Plus: |
| 1161 | return VisitPlus(E: UO, PromotionType); |
| 1162 | default: |
| 1163 | break; |
| 1164 | } |
| 1165 | } |
| 1166 | auto result = Visit(E: const_cast<Expr *>(E)); |
| 1167 | if (!PromotionType.isNull()) |
| 1168 | return CGF.EmitPromotedValue(result, PromotionType); |
| 1169 | else |
| 1170 | return result; |
| 1171 | } |
| 1172 | |
| 1173 | ComplexPairTy CodeGenFunction::EmitPromotedComplexExpr(const Expr *E, |
| 1174 | QualType DstTy) { |
| 1175 | return ComplexExprEmitter(*this).EmitPromoted(E, PromotionType: DstTy); |
| 1176 | } |
| 1177 | |
| 1178 | ComplexPairTy |
| 1179 | ComplexExprEmitter::EmitPromotedComplexOperand(const Expr *E, |
| 1180 | QualType OverallPromotionType) { |
| 1181 | if (E->getType()->isAnyComplexType()) { |
| 1182 | if (!OverallPromotionType.isNull()) |
| 1183 | return CGF.EmitPromotedComplexExpr(E, DstTy: OverallPromotionType); |
| 1184 | else |
| 1185 | return Visit(E: const_cast<Expr *>(E)); |
| 1186 | } else { |
| 1187 | if (!OverallPromotionType.isNull()) { |
| 1188 | QualType ComplexElementTy = |
| 1189 | OverallPromotionType->castAs<ComplexType>()->getElementType(); |
| 1190 | return ComplexPairTy(CGF.EmitPromotedScalarExpr(E, PromotionType: ComplexElementTy), |
| 1191 | nullptr); |
| 1192 | } else { |
| 1193 | return ComplexPairTy(CGF.EmitScalarExpr(E), nullptr); |
| 1194 | } |
| 1195 | } |
| 1196 | } |
| 1197 | |
| 1198 | ComplexExprEmitter::BinOpInfo |
| 1199 | ComplexExprEmitter::EmitBinOps(const BinaryOperator *E, |
| 1200 | QualType PromotionType) { |
| 1201 | TestAndClearIgnoreReal(); |
| 1202 | TestAndClearIgnoreImag(); |
| 1203 | BinOpInfo Ops; |
| 1204 | |
| 1205 | Ops.LHS = EmitPromotedComplexOperand(E: E->getLHS(), OverallPromotionType: PromotionType); |
| 1206 | Ops.RHS = EmitPromotedComplexOperand(E: E->getRHS(), OverallPromotionType: PromotionType); |
| 1207 | if (!PromotionType.isNull()) |
| 1208 | Ops.Ty = PromotionType; |
| 1209 | else |
| 1210 | Ops.Ty = E->getType(); |
| 1211 | Ops.FPFeatures = E->getFPFeaturesInEffect(LO: CGF.getLangOpts()); |
| 1212 | return Ops; |
| 1213 | } |
| 1214 | |
| 1215 | |
| 1216 | LValue ComplexExprEmitter:: |
| 1217 | EmitCompoundAssignLValue(const CompoundAssignOperator *E, |
| 1218 | ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&), |
| 1219 | RValue &Val) { |
| 1220 | TestAndClearIgnoreReal(); |
| 1221 | TestAndClearIgnoreImag(); |
| 1222 | QualType LHSTy = E->getLHS()->getType(); |
| 1223 | if (const AtomicType *AT = LHSTy->getAs<AtomicType>()) |
| 1224 | LHSTy = AT->getValueType(); |
| 1225 | |
| 1226 | BinOpInfo OpInfo; |
| 1227 | OpInfo.FPFeatures = E->getFPFeaturesInEffect(LO: CGF.getLangOpts()); |
| 1228 | CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, OpInfo.FPFeatures); |
| 1229 | |
| 1230 | const bool IsComplexDivisor = E->getOpcode() == BO_DivAssign && |
| 1231 | E->getRHS()->getType()->isAnyComplexType(); |
| 1232 | |
| 1233 | // Load the RHS and LHS operands. |
| 1234 | // __block variables need to have the rhs evaluated first, plus this should |
| 1235 | // improve codegen a little. |
| 1236 | QualType PromotionTypeCR; |
| 1237 | PromotionTypeCR = |
| 1238 | getPromotionType(Features: E->getStoredFPFeaturesOrDefault(), |
| 1239 | Ty: E->getComputationResultType(), IsComplexDivisor); |
| 1240 | if (PromotionTypeCR.isNull()) |
| 1241 | PromotionTypeCR = E->getComputationResultType(); |
| 1242 | OpInfo.Ty = PromotionTypeCR; |
| 1243 | QualType ComplexElementTy = |
| 1244 | OpInfo.Ty->castAs<ComplexType>()->getElementType(); |
| 1245 | QualType PromotionTypeRHS = |
| 1246 | getPromotionType(Features: E->getStoredFPFeaturesOrDefault(), |
| 1247 | Ty: E->getRHS()->getType(), IsComplexDivisor); |
| 1248 | |
| 1249 | // The RHS should have been converted to the computation type. |
| 1250 | if (E->getRHS()->getType()->isRealFloatingType()) { |
| 1251 | if (!PromotionTypeRHS.isNull()) |
| 1252 | OpInfo.RHS = ComplexPairTy( |
| 1253 | CGF.EmitPromotedScalarExpr(E: E->getRHS(), PromotionType: PromotionTypeRHS), nullptr); |
| 1254 | else { |
| 1255 | assert(CGF.getContext().hasSameUnqualifiedType(ComplexElementTy, |
| 1256 | E->getRHS()->getType())); |
| 1257 | |
| 1258 | OpInfo.RHS = ComplexPairTy(CGF.EmitScalarExpr(E: E->getRHS()), nullptr); |
| 1259 | } |
| 1260 | } else { |
| 1261 | if (!PromotionTypeRHS.isNull()) { |
| 1262 | OpInfo.RHS = ComplexPairTy( |
| 1263 | CGF.EmitPromotedComplexExpr(E: E->getRHS(), DstTy: PromotionTypeRHS)); |
| 1264 | } else { |
| 1265 | assert(CGF.getContext().hasSameUnqualifiedType(OpInfo.Ty, |
| 1266 | E->getRHS()->getType())); |
| 1267 | OpInfo.RHS = Visit(E: E->getRHS()); |
| 1268 | } |
| 1269 | } |
| 1270 | |
| 1271 | LValue LHS = CGF.EmitLValue(E: E->getLHS()); |
| 1272 | |
| 1273 | // Load from the l-value and convert it. |
| 1274 | SourceLocation Loc = E->getExprLoc(); |
| 1275 | QualType PromotionTypeLHS = |
| 1276 | getPromotionType(Features: E->getStoredFPFeaturesOrDefault(), |
| 1277 | Ty: E->getComputationLHSType(), IsComplexDivisor); |
| 1278 | if (LHSTy->isAnyComplexType()) { |
| 1279 | ComplexPairTy LHSVal = EmitLoadOfLValue(lvalue: LHS, loc: Loc); |
| 1280 | if (!PromotionTypeLHS.isNull()) |
| 1281 | OpInfo.LHS = |
| 1282 | EmitComplexToComplexCast(Val: LHSVal, SrcType: LHSTy, DestType: PromotionTypeLHS, Loc); |
| 1283 | else |
| 1284 | OpInfo.LHS = EmitComplexToComplexCast(Val: LHSVal, SrcType: LHSTy, DestType: OpInfo.Ty, Loc); |
| 1285 | } else { |
| 1286 | llvm::Value *LHSVal = CGF.EmitLoadOfScalar(lvalue: LHS, Loc); |
| 1287 | // For floating point real operands we can directly pass the scalar form |
| 1288 | // to the binary operator emission and potentially get more efficient code. |
| 1289 | if (LHSTy->isRealFloatingType()) { |
| 1290 | QualType PromotedComplexElementTy; |
| 1291 | if (!PromotionTypeLHS.isNull()) { |
| 1292 | PromotedComplexElementTy = |
| 1293 | cast<ComplexType>(Val&: PromotionTypeLHS)->getElementType(); |
| 1294 | if (!CGF.getContext().hasSameUnqualifiedType(T1: PromotedComplexElementTy, |
| 1295 | T2: PromotionTypeLHS)) |
| 1296 | LHSVal = CGF.EmitScalarConversion(Src: LHSVal, SrcTy: LHSTy, |
| 1297 | DstTy: PromotedComplexElementTy, Loc); |
| 1298 | } else { |
| 1299 | if (!CGF.getContext().hasSameUnqualifiedType(T1: ComplexElementTy, T2: LHSTy)) |
| 1300 | LHSVal = |
| 1301 | CGF.EmitScalarConversion(Src: LHSVal, SrcTy: LHSTy, DstTy: ComplexElementTy, Loc); |
| 1302 | } |
| 1303 | OpInfo.LHS = ComplexPairTy(LHSVal, nullptr); |
| 1304 | } else { |
| 1305 | OpInfo.LHS = EmitScalarToComplexCast(Val: LHSVal, SrcType: LHSTy, DestType: OpInfo.Ty, Loc); |
| 1306 | } |
| 1307 | } |
| 1308 | |
| 1309 | // Expand the binary operator. |
| 1310 | ComplexPairTy Result = (this->*Func)(OpInfo); |
| 1311 | |
| 1312 | // Truncate the result and store it into the LHS lvalue. |
| 1313 | if (LHSTy->isAnyComplexType()) { |
| 1314 | ComplexPairTy ResVal = |
| 1315 | EmitComplexToComplexCast(Val: Result, SrcType: OpInfo.Ty, DestType: LHSTy, Loc); |
| 1316 | EmitStoreOfComplex(Val: ResVal, lvalue: LHS, /*isInit*/ false); |
| 1317 | Val = RValue::getComplex(C: ResVal); |
| 1318 | } else { |
| 1319 | llvm::Value *ResVal = |
| 1320 | CGF.EmitComplexToScalarConversion(Src: Result, SrcTy: OpInfo.Ty, DstTy: LHSTy, Loc); |
| 1321 | CGF.EmitStoreOfScalar(value: ResVal, lvalue: LHS, /*isInit*/ false); |
| 1322 | Val = RValue::get(V: ResVal); |
| 1323 | } |
| 1324 | |
| 1325 | return LHS; |
| 1326 | } |
| 1327 | |
| 1328 | // Compound assignments. |
| 1329 | ComplexPairTy ComplexExprEmitter:: |
| 1330 | EmitCompoundAssign(const CompoundAssignOperator *E, |
| 1331 | ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){ |
| 1332 | RValue Val; |
| 1333 | LValue LV = EmitCompoundAssignLValue(E, Func, Val); |
| 1334 | |
| 1335 | // The result of an assignment in C is the assigned r-value. |
| 1336 | if (!CGF.getLangOpts().CPlusPlus) |
| 1337 | return Val.getComplexVal(); |
| 1338 | |
| 1339 | // If the lvalue is non-volatile, return the computed value of the assignment. |
| 1340 | if (!LV.isVolatileQualified()) |
| 1341 | return Val.getComplexVal(); |
| 1342 | |
| 1343 | return EmitLoadOfLValue(lvalue: LV, loc: E->getExprLoc()); |
| 1344 | } |
| 1345 | |
| 1346 | LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E, |
| 1347 | ComplexPairTy &Val) { |
| 1348 | assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), |
| 1349 | E->getRHS()->getType()) && |
| 1350 | "Invalid assignment" ); |
| 1351 | TestAndClearIgnoreReal(); |
| 1352 | TestAndClearIgnoreImag(); |
| 1353 | |
| 1354 | // Emit the RHS. __block variables need the RHS evaluated first. |
| 1355 | Val = Visit(E: E->getRHS()); |
| 1356 | |
| 1357 | // Compute the address to store into. |
| 1358 | LValue LHS = CGF.EmitLValue(E: E->getLHS()); |
| 1359 | |
| 1360 | // Store the result value into the LHS lvalue. |
| 1361 | EmitStoreOfComplex(Val, lvalue: LHS, /*isInit*/ false); |
| 1362 | |
| 1363 | return LHS; |
| 1364 | } |
| 1365 | |
| 1366 | ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { |
| 1367 | ComplexPairTy Val; |
| 1368 | ApplyAtomGroup Grp(CGF.getDebugInfo()); |
| 1369 | LValue LV = EmitBinAssignLValue(E, Val); |
| 1370 | |
| 1371 | // The result of an assignment in C is the assigned r-value. |
| 1372 | if (!CGF.getLangOpts().CPlusPlus) |
| 1373 | return Val; |
| 1374 | |
| 1375 | // If the lvalue is non-volatile, return the computed value of the assignment. |
| 1376 | if (!LV.isVolatileQualified()) |
| 1377 | return Val; |
| 1378 | |
| 1379 | return EmitLoadOfLValue(lvalue: LV, loc: E->getExprLoc()); |
| 1380 | } |
| 1381 | |
| 1382 | ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) { |
| 1383 | CGF.EmitIgnoredExpr(E: E->getLHS()); |
| 1384 | return Visit(E: E->getRHS()); |
| 1385 | } |
| 1386 | |
| 1387 | ComplexPairTy ComplexExprEmitter:: |
| 1388 | VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { |
| 1389 | TestAndClearIgnoreReal(); |
| 1390 | TestAndClearIgnoreImag(); |
| 1391 | llvm::BasicBlock *LHSBlock = CGF.createBasicBlock(name: "cond.true" ); |
| 1392 | llvm::BasicBlock *RHSBlock = CGF.createBasicBlock(name: "cond.false" ); |
| 1393 | llvm::BasicBlock *ContBlock = CGF.createBasicBlock(name: "cond.end" ); |
| 1394 | |
| 1395 | // Bind the common expression if necessary. |
| 1396 | CodeGenFunction::OpaqueValueMapping binding(CGF, E); |
| 1397 | |
| 1398 | |
| 1399 | CodeGenFunction::ConditionalEvaluation eval(CGF); |
| 1400 | CGF.EmitBranchOnBoolExpr(Cond: E->getCond(), TrueBlock: LHSBlock, FalseBlock: RHSBlock, |
| 1401 | TrueCount: CGF.getProfileCount(S: E)); |
| 1402 | |
| 1403 | eval.begin(CGF); |
| 1404 | CGF.EmitBlock(BB: LHSBlock); |
| 1405 | if (llvm::EnableSingleByteCoverage) |
| 1406 | CGF.incrementProfileCounter(S: E->getTrueExpr()); |
| 1407 | else |
| 1408 | CGF.incrementProfileCounter(S: E); |
| 1409 | |
| 1410 | ComplexPairTy LHS = Visit(E: E->getTrueExpr()); |
| 1411 | LHSBlock = Builder.GetInsertBlock(); |
| 1412 | CGF.EmitBranch(Block: ContBlock); |
| 1413 | eval.end(CGF); |
| 1414 | |
| 1415 | eval.begin(CGF); |
| 1416 | CGF.EmitBlock(BB: RHSBlock); |
| 1417 | if (llvm::EnableSingleByteCoverage) |
| 1418 | CGF.incrementProfileCounter(S: E->getFalseExpr()); |
| 1419 | ComplexPairTy RHS = Visit(E: E->getFalseExpr()); |
| 1420 | RHSBlock = Builder.GetInsertBlock(); |
| 1421 | CGF.EmitBlock(BB: ContBlock); |
| 1422 | if (llvm::EnableSingleByteCoverage) |
| 1423 | CGF.incrementProfileCounter(S: E); |
| 1424 | eval.end(CGF); |
| 1425 | |
| 1426 | // Create a PHI node for the real part. |
| 1427 | llvm::PHINode *RealPN = Builder.CreatePHI(Ty: LHS.first->getType(), NumReservedValues: 2, Name: "cond.r" ); |
| 1428 | RealPN->addIncoming(V: LHS.first, BB: LHSBlock); |
| 1429 | RealPN->addIncoming(V: RHS.first, BB: RHSBlock); |
| 1430 | |
| 1431 | // Create a PHI node for the imaginary part. |
| 1432 | llvm::PHINode *ImagPN = Builder.CreatePHI(Ty: LHS.first->getType(), NumReservedValues: 2, Name: "cond.i" ); |
| 1433 | ImagPN->addIncoming(V: LHS.second, BB: LHSBlock); |
| 1434 | ImagPN->addIncoming(V: RHS.second, BB: RHSBlock); |
| 1435 | |
| 1436 | return ComplexPairTy(RealPN, ImagPN); |
| 1437 | } |
| 1438 | |
| 1439 | ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) { |
| 1440 | return Visit(E: E->getChosenSubExpr()); |
| 1441 | } |
| 1442 | |
| 1443 | ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) { |
| 1444 | bool Ignore = TestAndClearIgnoreReal(); |
| 1445 | (void)Ignore; |
| 1446 | assert (Ignore == false && "init list ignored" ); |
| 1447 | Ignore = TestAndClearIgnoreImag(); |
| 1448 | (void)Ignore; |
| 1449 | assert (Ignore == false && "init list ignored" ); |
| 1450 | |
| 1451 | if (E->getNumInits() == 2) { |
| 1452 | llvm::Value *Real = CGF.EmitScalarExpr(E: E->getInit(Init: 0)); |
| 1453 | llvm::Value *Imag = CGF.EmitScalarExpr(E: E->getInit(Init: 1)); |
| 1454 | return ComplexPairTy(Real, Imag); |
| 1455 | } else if (E->getNumInits() == 1) { |
| 1456 | return Visit(E: E->getInit(Init: 0)); |
| 1457 | } |
| 1458 | |
| 1459 | // Empty init list initializes to null |
| 1460 | assert(E->getNumInits() == 0 && "Unexpected number of inits" ); |
| 1461 | QualType Ty = E->getType()->castAs<ComplexType>()->getElementType(); |
| 1462 | llvm::Type* LTy = CGF.ConvertType(T: Ty); |
| 1463 | llvm::Value* zeroConstant = llvm::Constant::getNullValue(Ty: LTy); |
| 1464 | return ComplexPairTy(zeroConstant, zeroConstant); |
| 1465 | } |
| 1466 | |
| 1467 | ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) { |
| 1468 | Address ArgValue = Address::invalid(); |
| 1469 | RValue RV = CGF.EmitVAArg(VE: E, VAListAddr&: ArgValue); |
| 1470 | |
| 1471 | if (!ArgValue.isValid()) { |
| 1472 | CGF.ErrorUnsupported(S: E, Type: "complex va_arg expression" ); |
| 1473 | llvm::Type *EltTy = |
| 1474 | CGF.ConvertType(T: E->getType()->castAs<ComplexType>()->getElementType()); |
| 1475 | llvm::Value *U = llvm::PoisonValue::get(T: EltTy); |
| 1476 | return ComplexPairTy(U, U); |
| 1477 | } |
| 1478 | |
| 1479 | return RV.getComplexVal(); |
| 1480 | } |
| 1481 | |
| 1482 | //===----------------------------------------------------------------------===// |
| 1483 | // Entry Point into this File |
| 1484 | //===----------------------------------------------------------------------===// |
| 1485 | |
| 1486 | /// EmitComplexExpr - Emit the computation of the specified expression of |
| 1487 | /// complex type, ignoring the result. |
| 1488 | ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal, |
| 1489 | bool IgnoreImag) { |
| 1490 | assert(E && getComplexType(E->getType()) && |
| 1491 | "Invalid complex expression to emit" ); |
| 1492 | |
| 1493 | return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag) |
| 1494 | .Visit(E: const_cast<Expr *>(E)); |
| 1495 | } |
| 1496 | |
| 1497 | void CodeGenFunction::EmitComplexExprIntoLValue(const Expr *E, LValue dest, |
| 1498 | bool isInit) { |
| 1499 | assert(E && getComplexType(E->getType()) && |
| 1500 | "Invalid complex expression to emit" ); |
| 1501 | ComplexExprEmitter Emitter(*this); |
| 1502 | ComplexPairTy Val = Emitter.Visit(E: const_cast<Expr*>(E)); |
| 1503 | Emitter.EmitStoreOfComplex(Val, lvalue: dest, isInit); |
| 1504 | } |
| 1505 | |
| 1506 | /// EmitStoreOfComplex - Store a complex number into the specified l-value. |
| 1507 | void CodeGenFunction::EmitStoreOfComplex(ComplexPairTy V, LValue dest, |
| 1508 | bool isInit) { |
| 1509 | ComplexExprEmitter(*this).EmitStoreOfComplex(Val: V, lvalue: dest, isInit); |
| 1510 | } |
| 1511 | |
| 1512 | /// EmitLoadOfComplex - Load a complex number from the specified address. |
| 1513 | ComplexPairTy CodeGenFunction::EmitLoadOfComplex(LValue src, |
| 1514 | SourceLocation loc) { |
| 1515 | return ComplexExprEmitter(*this).EmitLoadOfLValue(lvalue: src, loc); |
| 1516 | } |
| 1517 | |
| 1518 | LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) { |
| 1519 | assert(E->getOpcode() == BO_Assign); |
| 1520 | ComplexPairTy Val; // ignored |
| 1521 | LValue LVal = ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val); |
| 1522 | if (getLangOpts().OpenMP) |
| 1523 | CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF&: *this, |
| 1524 | LHS: E->getLHS()); |
| 1525 | return LVal; |
| 1526 | } |
| 1527 | |
| 1528 | typedef ComplexPairTy (ComplexExprEmitter::*CompoundFunc)( |
| 1529 | const ComplexExprEmitter::BinOpInfo &); |
| 1530 | |
| 1531 | static CompoundFunc getComplexOp(BinaryOperatorKind Op) { |
| 1532 | switch (Op) { |
| 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; |
| 1537 | default: |
| 1538 | llvm_unreachable("unexpected complex compound assignment" ); |
| 1539 | } |
| 1540 | } |
| 1541 | |
| 1542 | LValue CodeGenFunction:: |
| 1543 | EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) { |
| 1544 | ApplyAtomGroup Grp(getDebugInfo()); |
| 1545 | CompoundFunc Op = getComplexOp(Op: E->getOpcode()); |
| 1546 | RValue Val; |
| 1547 | return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Func: Op, Val); |
| 1548 | } |
| 1549 | |
| 1550 | LValue CodeGenFunction:: |
| 1551 | EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E, |
| 1552 | llvm::Value *&Result) { |
| 1553 | // Key Instructions: Don't need to create an atom group here; one will already |
| 1554 | // be active through scalar handling code. |
| 1555 | CompoundFunc Op = getComplexOp(Op: E->getOpcode()); |
| 1556 | RValue Val; |
| 1557 | LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Func: Op, Val); |
| 1558 | Result = Val.getScalarVal(); |
| 1559 | return Ret; |
| 1560 | } |
| 1561 | |