2007-08-24 10:22:53 +08:00
|
|
|
//===--- CGExprComplex.cpp - Emit LLVM Code for Complex Exprs -------------===//
|
2007-08-21 13:54:00 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2007-08-21 13:54:00 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This contains code to emit Expr nodes with complex types as LLVM code.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-27 22:44:43 +08:00
|
|
|
#include "CGOpenMPRuntime.h"
|
2007-08-21 13:54:00 +08:00
|
|
|
#include "CodeGenFunction.h"
|
|
|
|
#include "CodeGenModule.h"
|
2020-06-14 20:39:14 +08:00
|
|
|
#include "ConstantEmitter.h"
|
2008-08-11 13:00:27 +08:00
|
|
|
#include "clang/AST/StmtVisitor.h"
|
2014-10-20 03:13:49 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2013-01-02 19:45:17 +08:00
|
|
|
#include "llvm/IR/Constants.h"
|
2014-10-20 03:13:49 +08:00
|
|
|
#include "llvm/IR/Instructions.h"
|
|
|
|
#include "llvm/IR/MDBuilder.h"
|
|
|
|
#include "llvm/IR/Metadata.h"
|
2013-07-17 13:57:42 +08:00
|
|
|
#include <algorithm>
|
2007-08-21 13:54:00 +08:00
|
|
|
using namespace clang;
|
|
|
|
using namespace CodeGen;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
2007-08-21 13:54:53 +08:00
|
|
|
// Complex Expression Emitter
|
2007-08-21 13:54:00 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-08-22 00:57:55 +08:00
|
|
|
typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
|
2007-08-21 13:54:00 +08:00
|
|
|
|
2013-03-08 05:37:08 +08:00
|
|
|
/// Return the complex type that we are meant to emit.
|
|
|
|
static const ComplexType *getComplexType(QualType type) {
|
|
|
|
type = type.getCanonicalType();
|
|
|
|
if (const ComplexType *comp = dyn_cast<ComplexType>(type)) {
|
|
|
|
return comp;
|
|
|
|
} else {
|
|
|
|
return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
namespace {
|
2009-11-29 03:45:26 +08:00
|
|
|
class ComplexExprEmitter
|
2007-08-21 13:54:00 +08:00
|
|
|
: public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
|
|
|
|
CodeGenFunction &CGF;
|
2008-11-01 09:53:16 +08:00
|
|
|
CGBuilderTy &Builder;
|
2009-05-29 23:46:01 +08:00
|
|
|
bool IgnoreReal;
|
|
|
|
bool IgnoreImag;
|
2007-08-21 13:54:00 +08:00
|
|
|
public:
|
2010-11-16 18:08:07 +08:00
|
|
|
ComplexExprEmitter(CodeGenFunction &cgf, bool ir=false, bool ii=false)
|
|
|
|
: CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii) {
|
2007-08-21 13:54:00 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// Utilities
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
|
2009-05-29 23:46:01 +08:00
|
|
|
bool TestAndClearIgnoreReal() {
|
|
|
|
bool I = IgnoreReal;
|
|
|
|
IgnoreReal = false;
|
|
|
|
return I;
|
|
|
|
}
|
|
|
|
bool TestAndClearIgnoreImag() {
|
|
|
|
bool I = IgnoreImag;
|
|
|
|
IgnoreImag = false;
|
|
|
|
return I;
|
|
|
|
}
|
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
/// EmitLoadOfLValue - Given an expression with complex type that represents a
|
|
|
|
/// value l-value, this method emits the address of the l-value, then loads
|
|
|
|
/// and returns the result.
|
2007-08-22 01:28:34 +08:00
|
|
|
ComplexPairTy EmitLoadOfLValue(const Expr *E) {
|
2013-10-02 10:29:49 +08:00
|
|
|
return EmitLoadOfLValue(CGF.EmitLValue(E), E->getExprLoc());
|
2010-12-04 16:14:53 +08:00
|
|
|
}
|
|
|
|
|
2013-10-02 10:29:49 +08:00
|
|
|
ComplexPairTy EmitLoadOfLValue(LValue LV, SourceLocation Loc);
|
2010-12-04 16:14:53 +08:00
|
|
|
|
2007-08-22 01:28:34 +08:00
|
|
|
/// EmitStoreOfComplex - Store the specified real/imag parts into the
|
|
|
|
/// specified value pointer.
|
2015-01-14 15:38:27 +08:00
|
|
|
void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit);
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2015-08-05 14:19:26 +08:00
|
|
|
/// Emit a cast from complex value Val to DestType.
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
|
2015-08-11 12:19:28 +08:00
|
|
|
QualType DestType, SourceLocation Loc);
|
2015-08-05 14:19:26 +08:00
|
|
|
/// Emit a cast from scalar value Val to DestType.
|
2013-06-12 09:40:06 +08:00
|
|
|
ComplexPairTy EmitScalarToComplexCast(llvm::Value *Val, QualType SrcType,
|
2015-08-11 12:19:28 +08:00
|
|
|
QualType DestType, SourceLocation Loc);
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// Visitor Methods
|
|
|
|
//===--------------------------------------------------------------------===//
|
2007-08-22 02:51:13 +08:00
|
|
|
|
2010-09-21 07:50:22 +08:00
|
|
|
ComplexPairTy Visit(Expr *E) {
|
DebugInfo: Use the preferred location rather than the start location for expression line info
This causes things like assignment to refer to the '=' rather than the
LHS when attributing the store instruction, for example.
There were essentially 3 options for this:
* The beginning of an expression (this was the behavior prior to this
commit). This meant that stepping through subexpressions would bounce
around from subexpressions back to the start of the outer expression,
etc. (eg: x + y + z would go x, y, x, z, x (the repeated 'x's would be
where the actual addition occurred)).
* The end of an expression. This seems to be what GCC does /mostly/, and
certainly this for function calls. This has the advantage that
progress is always 'forwards' (never jumping backwards - except for
independent subexpressions if they're evaluated in interesting orders,
etc). "x + y + z" would go "x y z" with the additions occurring at y
and z after the respective loads.
The problem with this is that the user would still have to think
fairly hard about precedence to realize which subexpression is being
evaluated or which operator overload is being called in, say, an asan
backtrace.
* The preferred location or 'exprloc'. In this case you get sort of what
you'd expect, though it's a bit confusing in its own way due to going
'backwards'. In this case the locations would be: "x y + z +" in
lovely postfix arithmetic order. But this does mean that if the op+
were an operator overload, say, and in a backtrace, the backtrace will
point to the exact '+' that's being called, not to the end of one of
its operands.
(actually the operator overload case doesn't work yet for other reasons,
but that's being fixed - but this at least gets scalar/complex
assignments and other plain operators right)
llvm-svn: 227027
2015-01-25 09:19:10 +08:00
|
|
|
ApplyDebugLocation DL(CGF, E);
|
2011-02-18 03:02:56 +08:00
|
|
|
return StmtVisitor<ComplexExprEmitter, ComplexPairTy>::Visit(E);
|
2010-09-21 07:50:22 +08:00
|
|
|
}
|
2013-11-22 18:20:40 +08:00
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
ComplexPairTy VisitStmt(Stmt *S) {
|
2020-07-03 20:54:10 +08:00
|
|
|
S->dump(llvm::errs(), CGF.getContext());
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Stmt can't have complex result type!");
|
2007-08-21 13:54:00 +08:00
|
|
|
}
|
2007-08-22 02:51:13 +08:00
|
|
|
ComplexPairTy VisitExpr(Expr *S);
|
2018-11-09 08:41:36 +08:00
|
|
|
ComplexPairTy VisitConstantExpr(ConstantExpr *E) {
|
2020-06-14 20:39:14 +08:00
|
|
|
if (llvm::Constant *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E))
|
|
|
|
return ComplexPairTy(Result->getAggregateElement(0U),
|
|
|
|
Result->getAggregateElement(1U));
|
2018-11-09 08:41:36 +08:00
|
|
|
return Visit(E->getSubExpr());
|
|
|
|
}
|
2007-08-21 13:54:00 +08:00
|
|
|
ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());}
|
2011-04-15 08:35:48 +08:00
|
|
|
ComplexPairTy VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
|
|
|
|
return Visit(GE->getResultExpr());
|
|
|
|
}
|
2007-08-26 13:57:57 +08:00
|
|
|
ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL);
|
2011-07-15 13:09:51 +08:00
|
|
|
ComplexPairTy
|
|
|
|
VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE) {
|
|
|
|
return Visit(PE->getReplacement());
|
|
|
|
}
|
2017-03-26 10:18:05 +08:00
|
|
|
ComplexPairTy VisitCoawaitExpr(CoawaitExpr *S) {
|
|
|
|
return CGF.EmitCoawaitExpr(*S).getComplexVal();
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitCoyieldExpr(CoyieldExpr *S) {
|
|
|
|
return CGF.EmitCoyieldExpr(*S).getComplexVal();
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitUnaryCoawait(const UnaryOperator *E) {
|
|
|
|
return Visit(E->getSubExpr());
|
|
|
|
}
|
|
|
|
|
2017-08-25 18:07:00 +08:00
|
|
|
ComplexPairTy emitConstant(const CodeGenFunction::ConstantEmission &Constant,
|
|
|
|
Expr *E) {
|
|
|
|
assert(Constant && "not a constant");
|
|
|
|
if (Constant.isReference())
|
|
|
|
return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E),
|
|
|
|
E->getExprLoc());
|
|
|
|
|
|
|
|
llvm::Constant *pair = Constant.getValue();
|
|
|
|
return ComplexPairTy(pair->getAggregateElement(0U),
|
|
|
|
pair->getAggregateElement(1U));
|
|
|
|
}
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
// l-values.
|
2012-03-10 17:33:50 +08:00
|
|
|
ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) {
|
2017-08-25 18:07:00 +08:00
|
|
|
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
|
|
|
|
return emitConstant(Constant, E);
|
2012-03-10 17:33:50 +08:00
|
|
|
return EmitLoadOfLValue(E);
|
2012-03-10 11:05:10 +08:00
|
|
|
}
|
2009-09-09 21:00:44 +08:00
|
|
|
ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
|
2009-06-10 12:38:50 +08:00
|
|
|
return EmitLoadOfLValue(E);
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) {
|
|
|
|
return CGF.EmitObjCMessageExpr(E).getComplexVal();
|
|
|
|
}
|
2007-08-22 02:03:58 +08:00
|
|
|
ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
|
2017-08-25 18:07:00 +08:00
|
|
|
ComplexPairTy VisitMemberExpr(MemberExpr *ME) {
|
|
|
|
if (CodeGenFunction::ConstantEmission Constant =
|
|
|
|
CGF.tryEmitAsConstant(ME)) {
|
|
|
|
CGF.EmitIgnoredExpr(ME->getBase());
|
|
|
|
return emitConstant(Constant, ME);
|
|
|
|
}
|
|
|
|
return EmitLoadOfLValue(ME);
|
|
|
|
}
|
2011-02-16 16:02:54 +08:00
|
|
|
ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
|
2011-02-17 18:25:35 +08:00
|
|
|
if (E->isGLValue())
|
2018-03-20 09:47:58 +08:00
|
|
|
return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
|
|
|
|
E->getExprLoc());
|
|
|
|
return CGF.getOrCreateOpaqueRValueMapping(E).getComplexVal();
|
2011-02-16 16:02:54 +08:00
|
|
|
}
|
2007-08-21 13:54:00 +08:00
|
|
|
|
2011-11-06 17:01:30 +08:00
|
|
|
ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) {
|
|
|
|
return CGF.EmitPseudoObjectRValue(E).getComplexVal();
|
|
|
|
}
|
|
|
|
|
2007-08-22 06:33:41 +08:00
|
|
|
// FIXME: CompoundLiteralExpr
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2014-10-31 14:57:10 +08:00
|
|
|
ComplexPairTy EmitCast(CastKind CK, Expr *Op, QualType DestTy);
|
2007-08-26 13:57:57 +08:00
|
|
|
ComplexPairTy VisitImplicitCastExpr(ImplicitCastExpr *E) {
|
|
|
|
// Unlike for scalars, we don't have to worry about function->ptr demotion
|
|
|
|
// here.
|
2010-07-15 05:35:45 +08:00
|
|
|
return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
|
2007-08-26 13:57:57 +08:00
|
|
|
}
|
|
|
|
ComplexPairTy VisitCastExpr(CastExpr *E) {
|
2015-10-20 12:24:12 +08:00
|
|
|
if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
|
|
|
|
CGF.CGM.EmitExplicitCastExprType(ECE, &CGF);
|
2010-07-15 05:35:45 +08:00
|
|
|
return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
|
2007-08-26 13:57:57 +08:00
|
|
|
}
|
2007-08-24 05:38:16 +08:00
|
|
|
ComplexPairTy VisitCallExpr(const CallExpr *E);
|
2007-09-01 06:51:38 +08:00
|
|
|
ComplexPairTy VisitStmtExpr(const StmtExpr *E);
|
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
// Operators.
|
2007-08-22 06:25:29 +08:00
|
|
|
ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E,
|
2010-01-10 05:40:03 +08:00
|
|
|
bool isInc, bool isPre) {
|
|
|
|
LValue LV = CGF.EmitLValue(E->getSubExpr());
|
|
|
|
return CGF.EmitComplexPrePostIncDec(E, LV, isInc, isPre);
|
|
|
|
}
|
2007-08-22 06:25:29 +08:00
|
|
|
ComplexPairTy VisitUnaryPostDec(const UnaryOperator *E) {
|
|
|
|
return VisitPrePostIncDec(E, false, false);
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitUnaryPostInc(const UnaryOperator *E) {
|
|
|
|
return VisitPrePostIncDec(E, true, false);
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitUnaryPreDec(const UnaryOperator *E) {
|
|
|
|
return VisitPrePostIncDec(E, false, true);
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitUnaryPreInc(const UnaryOperator *E) {
|
|
|
|
return VisitPrePostIncDec(E, true, true);
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
|
2007-08-22 04:08:23 +08:00
|
|
|
ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) {
|
2009-05-29 23:46:01 +08:00
|
|
|
TestAndClearIgnoreReal();
|
|
|
|
TestAndClearIgnoreImag();
|
2007-08-22 04:08:23 +08:00
|
|
|
return Visit(E->getSubExpr());
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitUnaryMinus (const UnaryOperator *E);
|
2007-08-22 04:41:44 +08:00
|
|
|
ComplexPairTy VisitUnaryNot (const UnaryOperator *E);
|
2008-11-12 01:56:53 +08:00
|
|
|
// LNot,Real,Imag never return complex.
|
2007-08-22 04:41:44 +08:00
|
|
|
ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) {
|
|
|
|
return Visit(E->getSubExpr());
|
|
|
|
}
|
2008-04-08 12:40:51 +08:00
|
|
|
ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
|
Implement __builtin_LINE() et. al. to support source location capture.
Summary:
This patch implements the source location builtins `__builtin_LINE(), `__builtin_FUNCTION()`, `__builtin_FILE()` and `__builtin_COLUMN()`. These builtins are needed to implement [`std::experimental::source_location`](https://rawgit.com/cplusplus/fundamentals-ts/v2/main.html#reflection.src_loc.creation).
With the exception of `__builtin_COLUMN`, GCC also implements these builtins, and Clangs behavior is intended to match as closely as possible.
Reviewers: rsmith, joerg, aaron.ballman, bogner, majnemer, shafik, martong
Reviewed By: rsmith
Subscribers: rnkovacs, loskutov, riccibruno, mgorny, kunitoki, alexr, majnemer, hfinkel, cfe-commits
Differential Revision: https://reviews.llvm.org/D37035
llvm-svn: 360937
2019-05-17 05:04:15 +08:00
|
|
|
CodeGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE);
|
2008-04-08 12:40:51 +08:00
|
|
|
return Visit(DAE->getExpr());
|
|
|
|
}
|
2013-04-21 06:23:05 +08:00
|
|
|
ComplexPairTy VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
|
Implement __builtin_LINE() et. al. to support source location capture.
Summary:
This patch implements the source location builtins `__builtin_LINE(), `__builtin_FUNCTION()`, `__builtin_FILE()` and `__builtin_COLUMN()`. These builtins are needed to implement [`std::experimental::source_location`](https://rawgit.com/cplusplus/fundamentals-ts/v2/main.html#reflection.src_loc.creation).
With the exception of `__builtin_COLUMN`, GCC also implements these builtins, and Clangs behavior is intended to match as closely as possible.
Reviewers: rsmith, joerg, aaron.ballman, bogner, majnemer, shafik, martong
Reviewed By: rsmith
Subscribers: rnkovacs, loskutov, riccibruno, mgorny, kunitoki, alexr, majnemer, hfinkel, cfe-commits
Differential Revision: https://reviews.llvm.org/D37035
llvm-svn: 360937
2019-05-17 05:04:15 +08:00
|
|
|
CodeGenFunction::CXXDefaultInitExprScope Scope(CGF, DIE);
|
2013-04-21 06:23:05 +08:00
|
|
|
return Visit(DIE->getExpr());
|
|
|
|
}
|
2010-12-06 16:20:24 +08:00
|
|
|
ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
|
2011-11-10 16:15:53 +08:00
|
|
|
CodeGenFunction::RunCleanupsScope Scope(CGF);
|
2017-03-07 06:18:34 +08:00
|
|
|
ComplexPairTy Vals = Visit(E->getSubExpr());
|
|
|
|
// Defend against dominance problems caused by jumps out of expression
|
|
|
|
// evaluation through the shared cleanup block.
|
|
|
|
Scope.ForceCleanup({&Vals.first, &Vals.second});
|
|
|
|
return Vals;
|
2009-05-31 08:12:05 +08:00
|
|
|
}
|
2010-07-08 14:14:04 +08:00
|
|
|
ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
|
2008-08-24 03:35:47 +08:00
|
|
|
assert(E->getType()->isAnyComplexType() && "Expected complex type!");
|
2013-03-08 05:37:08 +08:00
|
|
|
QualType Elem = E->getType()->castAs<ComplexType>()->getElementType();
|
2009-09-09 21:00:44 +08:00
|
|
|
llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem));
|
2008-08-24 03:35:47 +08:00
|
|
|
return ComplexPairTy(Null, Null);
|
|
|
|
}
|
2009-01-30 01:44:32 +08:00
|
|
|
ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
|
|
|
|
assert(E->getType()->isAnyComplexType() && "Expected complex type!");
|
2013-03-08 05:37:08 +08:00
|
|
|
QualType Elem = E->getType()->castAs<ComplexType>()->getElementType();
|
2009-09-09 21:00:44 +08:00
|
|
|
llvm::Constant *Null =
|
2009-08-01 04:28:54 +08:00
|
|
|
llvm::Constant::getNullValue(CGF.ConvertType(Elem));
|
2009-01-30 01:44:32 +08:00
|
|
|
return ComplexPairTy(Null, Null);
|
|
|
|
}
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-27 06:09:01 +08:00
|
|
|
struct BinOpInfo {
|
|
|
|
ComplexPairTy LHS;
|
|
|
|
ComplexPairTy RHS;
|
|
|
|
QualType Ty; // Computation Type.
|
2009-09-09 21:00:44 +08:00
|
|
|
};
|
|
|
|
|
2007-08-27 06:09:01 +08:00
|
|
|
BinOpInfo EmitBinOps(const BinaryOperator *E);
|
2010-11-16 18:08:07 +08:00
|
|
|
LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
|
|
|
|
ComplexPairTy (ComplexExprEmitter::*Func)
|
|
|
|
(const BinOpInfo &),
|
2013-06-12 09:40:06 +08:00
|
|
|
RValue &Val);
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E,
|
|
|
|
ComplexPairTy (ComplexExprEmitter::*Func)
|
|
|
|
(const BinOpInfo &));
|
|
|
|
|
|
|
|
ComplexPairTy EmitBinAdd(const BinOpInfo &Op);
|
|
|
|
ComplexPairTy EmitBinSub(const BinOpInfo &Op);
|
|
|
|
ComplexPairTy EmitBinMul(const BinOpInfo &Op);
|
|
|
|
ComplexPairTy EmitBinDiv(const BinOpInfo &Op);
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2014-10-11 08:57:18 +08:00
|
|
|
ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName,
|
|
|
|
const BinOpInfo &Op);
|
|
|
|
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexPairTy VisitBinAdd(const BinaryOperator *E) {
|
|
|
|
return EmitBinAdd(EmitBinOps(E));
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitBinSub(const BinaryOperator *E) {
|
|
|
|
return EmitBinSub(EmitBinOps(E));
|
|
|
|
}
|
2010-11-16 18:08:07 +08:00
|
|
|
ComplexPairTy VisitBinMul(const BinaryOperator *E) {
|
|
|
|
return EmitBinMul(EmitBinOps(E));
|
|
|
|
}
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexPairTy VisitBinDiv(const BinaryOperator *E) {
|
|
|
|
return EmitBinDiv(EmitBinOps(E));
|
|
|
|
}
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2019-10-19 08:04:38 +08:00
|
|
|
ComplexPairTy VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *E) {
|
|
|
|
return Visit(E->getSemanticForm());
|
|
|
|
}
|
|
|
|
|
2007-08-27 06:09:01 +08:00
|
|
|
// Compound assignments.
|
|
|
|
ComplexPairTy VisitBinAddAssign(const CompoundAssignOperator *E) {
|
|
|
|
return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinAdd);
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitBinSubAssign(const CompoundAssignOperator *E) {
|
|
|
|
return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinSub);
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitBinMulAssign(const CompoundAssignOperator *E) {
|
|
|
|
return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinMul);
|
|
|
|
}
|
|
|
|
ComplexPairTy VisitBinDivAssign(const CompoundAssignOperator *E) {
|
|
|
|
return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinDiv);
|
|
|
|
}
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-27 05:27:07 +08:00
|
|
|
// GCC rejects rem/and/or/xor for integer complex.
|
2007-08-22 01:12:50 +08:00
|
|
|
// Logical and/or always return int, never complex.
|
2007-08-22 00:57:55 +08:00
|
|
|
|
|
|
|
// No comparisons produce a complex result.
|
2010-11-16 18:08:07 +08:00
|
|
|
|
|
|
|
LValue EmitBinAssignLValue(const BinaryOperator *E,
|
|
|
|
ComplexPairTy &Val);
|
2007-08-21 13:54:00 +08:00
|
|
|
ComplexPairTy VisitBinAssign (const BinaryOperator *E);
|
2007-08-22 01:15:50 +08:00
|
|
|
ComplexPairTy VisitBinComma (const BinaryOperator *E);
|
|
|
|
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2011-02-17 18:25:35 +08:00
|
|
|
ComplexPairTy
|
|
|
|
VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
|
2007-08-24 10:18:47 +08:00
|
|
|
ComplexPairTy VisitChooseExpr(ChooseExpr *CE);
|
2008-05-14 07:11:35 +08:00
|
|
|
|
|
|
|
ComplexPairTy VisitInitListExpr(InitListExpr *E);
|
2009-02-10 11:03:30 +08:00
|
|
|
|
2012-02-28 04:26:13 +08:00
|
|
|
ComplexPairTy VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
|
|
|
|
return EmitLoadOfLValue(E);
|
|
|
|
}
|
|
|
|
|
2009-02-10 11:03:30 +08:00
|
|
|
ComplexPairTy VisitVAArgExpr(VAArgExpr *E);
|
2011-10-11 10:20:01 +08:00
|
|
|
|
|
|
|
ComplexPairTy VisitAtomicExpr(AtomicExpr *E) {
|
|
|
|
return CGF.EmitAtomicExpr(E).getComplexVal();
|
|
|
|
}
|
2007-08-21 13:54:00 +08:00
|
|
|
};
|
|
|
|
} // end anonymous namespace.
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Utilities
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
Address CodeGenFunction::emitAddrOfRealComponent(Address addr,
|
|
|
|
QualType complexType) {
|
2019-02-10 06:22:28 +08:00
|
|
|
return Builder.CreateStructGEP(addr, 0, addr.getName() + ".realp");
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Address CodeGenFunction::emitAddrOfImagComponent(Address addr,
|
|
|
|
QualType complexType) {
|
2019-02-10 06:22:28 +08:00
|
|
|
return Builder.CreateStructGEP(addr, 1, addr.getName() + ".imagp");
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
}
|
|
|
|
|
2013-03-08 05:37:08 +08:00
|
|
|
/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
|
2007-08-22 01:28:34 +08:00
|
|
|
/// load the real and imaginary pieces, returning them as Real/Imag.
|
2013-10-02 10:29:49 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue,
|
|
|
|
SourceLocation loc) {
|
2013-03-08 05:37:08 +08:00
|
|
|
assert(lvalue.isSimple() && "non-simple complex l-value?");
|
2013-03-08 05:37:17 +08:00
|
|
|
if (lvalue.getType()->isAtomicType())
|
2013-10-02 10:29:49 +08:00
|
|
|
return CGF.EmitAtomicLoad(lvalue, loc).getComplexVal();
|
2013-03-08 05:37:17 +08:00
|
|
|
|
2019-12-04 07:17:01 +08:00
|
|
|
Address SrcPtr = lvalue.getAddress(CGF);
|
2013-03-08 05:37:08 +08:00
|
|
|
bool isVolatile = lvalue.isVolatileQualified();
|
|
|
|
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
llvm::Value *Real = nullptr, *Imag = nullptr;
|
2007-08-27 06:47:40 +08:00
|
|
|
|
2010-11-14 17:40:28 +08:00
|
|
|
if (!IgnoreReal || isVolatile) {
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
Address RealP = CGF.emitAddrOfRealComponent(SrcPtr, lvalue.getType());
|
|
|
|
Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr.getName() + ".real");
|
2009-05-29 23:46:01 +08:00
|
|
|
}
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2010-11-14 17:40:28 +08:00
|
|
|
if (!IgnoreImag || isVolatile) {
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
Address ImagP = CGF.emitAddrOfImagComponent(SrcPtr, lvalue.getType());
|
|
|
|
Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr.getName() + ".imag");
|
2009-05-29 23:46:01 +08:00
|
|
|
}
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
return ComplexPairTy(Real, Imag);
|
|
|
|
}
|
|
|
|
|
2007-08-22 01:28:34 +08:00
|
|
|
/// EmitStoreOfComplex - Store the specified real/imag parts into the
|
|
|
|
/// specified value pointer.
|
2014-12-10 04:52:24 +08:00
|
|
|
void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue,
|
2015-01-14 15:38:27 +08:00
|
|
|
bool isInit) {
|
2015-02-14 09:35:12 +08:00
|
|
|
if (lvalue.getType()->isAtomicType() ||
|
|
|
|
(!isInit && CGF.LValueIsSuitableForInlineAtomic(lvalue)))
|
2013-03-08 05:37:17 +08:00
|
|
|
return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit);
|
|
|
|
|
2019-12-04 07:17:01 +08:00
|
|
|
Address Ptr = lvalue.getAddress(CGF);
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType());
|
|
|
|
Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType());
|
|
|
|
|
|
|
|
Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
|
|
|
|
Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
|
2007-08-22 01:28:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Visitor Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-08-22 02:51:13 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) {
|
2011-09-03 04:03:16 +08:00
|
|
|
CGF.ErrorUnsupported(E, "complex expression");
|
|
|
|
llvm::Type *EltTy =
|
2013-03-08 05:37:08 +08:00
|
|
|
CGF.ConvertType(getComplexType(E->getType())->getElementType());
|
2011-09-03 04:03:16 +08:00
|
|
|
llvm::Value *U = llvm::UndefValue::get(EltTy);
|
|
|
|
return ComplexPairTy(U, U);
|
2007-08-21 13:54:00 +08:00
|
|
|
}
|
|
|
|
|
2007-08-26 13:57:57 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::
|
|
|
|
VisitImaginaryLiteral(const ImaginaryLiteral *IL) {
|
2007-08-26 11:51:12 +08:00
|
|
|
llvm::Value *Imag = CGF.EmitScalarExpr(IL->getSubExpr());
|
2011-01-13 10:03:06 +08:00
|
|
|
return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag);
|
2007-08-26 11:51:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-24 05:38:16 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
|
2015-02-26 01:36:15 +08:00
|
|
|
if (E->getCallReturnType(CGF.getContext())->isReferenceType())
|
2009-05-27 11:37:57 +08:00
|
|
|
return EmitLoadOfLValue(E);
|
|
|
|
|
2007-09-01 06:49:20 +08:00
|
|
|
return CGF.EmitCallExpr(E).getComplexVal();
|
2008-01-31 04:50:20 +08:00
|
|
|
}
|
|
|
|
|
2007-09-01 06:51:38 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) {
|
2011-01-26 12:00:11 +08:00
|
|
|
CodeGenFunction::StmtExprEvaluation eval(CGF);
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
Address RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(), true);
|
|
|
|
assert(RetAlloca.isValid() && "Expected complex return value");
|
2013-10-02 10:29:49 +08:00
|
|
|
return EmitLoadOfLValue(CGF.MakeAddrLValue(RetAlloca, E->getType()),
|
|
|
|
E->getExprLoc());
|
2007-09-01 06:51:38 +08:00
|
|
|
}
|
|
|
|
|
2015-08-05 14:19:26 +08:00
|
|
|
/// Emit a cast from complex value Val to DestType.
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val,
|
|
|
|
QualType SrcType,
|
2015-08-11 12:19:28 +08:00
|
|
|
QualType DestType,
|
|
|
|
SourceLocation Loc) {
|
2007-08-27 06:09:01 +08:00
|
|
|
// Get the src/dest element type.
|
2013-03-08 05:37:08 +08:00
|
|
|
SrcType = SrcType->castAs<ComplexType>()->getElementType();
|
|
|
|
DestType = DestType->castAs<ComplexType>()->getElementType();
|
2007-08-27 06:09:01 +08:00
|
|
|
|
2009-01-29 14:44:03 +08:00
|
|
|
// C99 6.3.1.6: When a value of complex type is converted to another
|
2009-01-27 02:02:34 +08:00
|
|
|
// complex type, both the real and imaginary parts follow the conversion
|
2007-08-27 06:09:01 +08:00
|
|
|
// rules for the corresponding real types.
|
2020-01-29 02:04:32 +08:00
|
|
|
if (Val.first)
|
|
|
|
Val.first = CGF.EmitScalarConversion(Val.first, SrcType, DestType, Loc);
|
|
|
|
if (Val.second)
|
|
|
|
Val.second = CGF.EmitScalarConversion(Val.second, SrcType, DestType, Loc);
|
2007-08-27 06:09:01 +08:00
|
|
|
return Val;
|
|
|
|
}
|
2007-08-26 13:57:57 +08:00
|
|
|
|
2013-06-12 09:40:06 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val,
|
|
|
|
QualType SrcType,
|
2015-08-11 12:19:28 +08:00
|
|
|
QualType DestType,
|
|
|
|
SourceLocation Loc) {
|
2013-06-12 09:40:06 +08:00
|
|
|
// Convert the input element to the element type of the complex.
|
|
|
|
DestType = DestType->castAs<ComplexType>()->getElementType();
|
2015-08-11 12:19:28 +08:00
|
|
|
Val = CGF.EmitScalarConversion(Val, SrcType, DestType, Loc);
|
2013-06-12 09:40:06 +08:00
|
|
|
|
|
|
|
// Return (realval, 0).
|
|
|
|
return ComplexPairTy(Val, llvm::Constant::getNullValue(Val->getType()));
|
|
|
|
}
|
|
|
|
|
2014-10-31 14:57:10 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
|
2010-07-15 05:35:45 +08:00
|
|
|
QualType DestTy) {
|
2010-12-04 11:47:34 +08:00
|
|
|
switch (CK) {
|
2011-06-25 10:58:47 +08:00
|
|
|
case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
|
2010-12-04 11:47:34 +08:00
|
|
|
|
2012-01-17 01:27:18 +08:00
|
|
|
// Atomic to non-atomic casts may be more than a no-op for some platforms and
|
|
|
|
// for some types.
|
|
|
|
case CK_AtomicToNonAtomic:
|
|
|
|
case CK_NonAtomicToAtomic:
|
2010-12-04 11:47:34 +08:00
|
|
|
case CK_NoOp:
|
|
|
|
case CK_LValueToRValue:
|
2011-06-25 10:58:47 +08:00
|
|
|
case CK_UserDefinedConversion:
|
2010-12-04 11:47:34 +08:00
|
|
|
return Visit(Op);
|
|
|
|
|
2011-06-25 10:58:47 +08:00
|
|
|
case CK_LValueBitCast: {
|
2013-03-08 05:37:08 +08:00
|
|
|
LValue origLV = CGF.EmitLValue(Op);
|
2019-12-04 07:17:01 +08:00
|
|
|
Address V = origLV.getAddress(CGF);
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
V = Builder.CreateElementBitCast(V, CGF.ConvertType(DestTy));
|
|
|
|
return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy), Op->getExprLoc());
|
2010-07-15 05:35:45 +08:00
|
|
|
}
|
2007-08-26 13:57:57 +08:00
|
|
|
|
2019-07-03 02:28:13 +08:00
|
|
|
case CK_LValueToRValueBitCast: {
|
|
|
|
LValue SourceLVal = CGF.EmitLValue(Op);
|
2019-12-04 07:17:01 +08:00
|
|
|
Address Addr = Builder.CreateElementBitCast(SourceLVal.getAddress(CGF),
|
2019-07-03 02:28:13 +08:00
|
|
|
CGF.ConvertTypeForMem(DestTy));
|
|
|
|
LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
|
|
|
|
DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
|
|
|
|
return EmitLoadOfLValue(DestLV, Op->getExprLoc());
|
|
|
|
}
|
|
|
|
|
2011-06-25 10:58:47 +08:00
|
|
|
case CK_BitCast:
|
|
|
|
case CK_BaseToDerived:
|
|
|
|
case CK_DerivedToBase:
|
|
|
|
case CK_UncheckedDerivedToBase:
|
|
|
|
case CK_Dynamic:
|
|
|
|
case CK_ToUnion:
|
|
|
|
case CK_ArrayToPointerDecay:
|
|
|
|
case CK_FunctionToPointerDecay:
|
|
|
|
case CK_NullToPointer:
|
|
|
|
case CK_NullToMemberPointer:
|
|
|
|
case CK_BaseToDerivedMemberPointer:
|
|
|
|
case CK_DerivedToBaseMemberPointer:
|
|
|
|
case CK_MemberPointerToBoolean:
|
2012-02-15 09:22:51 +08:00
|
|
|
case CK_ReinterpretMemberPointer:
|
2011-06-25 10:58:47 +08:00
|
|
|
case CK_ConstructorConversion:
|
|
|
|
case CK_IntegralToPointer:
|
|
|
|
case CK_PointerToIntegral:
|
|
|
|
case CK_PointerToBoolean:
|
|
|
|
case CK_ToVoid:
|
|
|
|
case CK_VectorSplat:
|
|
|
|
case CK_IntegralCast:
|
2016-01-13 09:52:39 +08:00
|
|
|
case CK_BooleanToSignedIntegral:
|
2011-06-25 10:58:47 +08:00
|
|
|
case CK_IntegralToBoolean:
|
|
|
|
case CK_IntegralToFloating:
|
|
|
|
case CK_FloatingToIntegral:
|
|
|
|
case CK_FloatingToBoolean:
|
|
|
|
case CK_FloatingCast:
|
2011-09-09 13:25:32 +08:00
|
|
|
case CK_CPointerToObjCPointerCast:
|
|
|
|
case CK_BlockPointerToObjCPointerCast:
|
2011-06-25 10:58:47 +08:00
|
|
|
case CK_AnyPointerToBlockPointerCast:
|
|
|
|
case CK_ObjCObjectLValueCast:
|
|
|
|
case CK_FloatingComplexToReal:
|
|
|
|
case CK_FloatingComplexToBoolean:
|
|
|
|
case CK_IntegralComplexToReal:
|
|
|
|
case CK_IntegralComplexToBoolean:
|
2011-09-10 14:18:15 +08:00
|
|
|
case CK_ARCProduceObject:
|
|
|
|
case CK_ARCConsumeObject:
|
|
|
|
case CK_ARCReclaimReturnedObject:
|
|
|
|
case CK_ARCExtendBlockObject:
|
2012-02-22 13:02:47 +08:00
|
|
|
case CK_CopyAndAutoreleaseBlockObject:
|
2012-08-31 08:14:07 +08:00
|
|
|
case CK_BuiltinFnToFnPtr:
|
2018-10-23 23:19:20 +08:00
|
|
|
case CK_ZeroToOCLOpaqueType:
|
2013-12-11 21:39:46 +08:00
|
|
|
case CK_AddressSpaceConversion:
|
2016-07-29 03:26:30 +08:00
|
|
|
case CK_IntToOCLSampler:
|
2018-10-16 00:07:02 +08:00
|
|
|
case CK_FixedPointCast:
|
2018-10-24 01:55:35 +08:00
|
|
|
case CK_FixedPointToBoolean:
|
2019-03-06 08:28:43 +08:00
|
|
|
case CK_FixedPointToIntegral:
|
|
|
|
case CK_IntegralToFixedPoint:
|
2011-06-25 10:58:47 +08:00
|
|
|
llvm_unreachable("invalid cast kind for complex value");
|
|
|
|
|
|
|
|
case CK_FloatingRealToComplex:
|
2013-06-12 09:40:06 +08:00
|
|
|
case CK_IntegralRealToComplex:
|
2015-08-11 12:19:28 +08:00
|
|
|
return EmitScalarToComplexCast(CGF.EmitScalarExpr(Op), Op->getType(),
|
|
|
|
DestTy, Op->getExprLoc());
|
2011-06-25 10:58:47 +08:00
|
|
|
|
|
|
|
case CK_FloatingComplexCast:
|
|
|
|
case CK_FloatingComplexToIntegralComplex:
|
|
|
|
case CK_IntegralComplexCast:
|
|
|
|
case CK_IntegralComplexToFloatingComplex:
|
2015-08-11 12:19:28 +08:00
|
|
|
return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy,
|
|
|
|
Op->getExprLoc());
|
2011-06-25 10:58:47 +08:00
|
|
|
}
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2011-06-25 10:58:47 +08:00
|
|
|
llvm_unreachable("unknown cast resulting in complex value");
|
2007-08-26 13:57:57 +08:00
|
|
|
}
|
|
|
|
|
2007-08-22 04:08:23 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
|
2009-05-29 23:46:01 +08:00
|
|
|
TestAndClearIgnoreReal();
|
|
|
|
TestAndClearIgnoreImag();
|
2007-08-22 04:08:23 +08:00
|
|
|
ComplexPairTy Op = Visit(E->getSubExpr());
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2009-06-17 14:36:24 +08:00
|
|
|
llvm::Value *ResR, *ResI;
|
2010-02-16 00:14:01 +08:00
|
|
|
if (Op.first->getType()->isFloatingPointTy()) {
|
2009-06-17 14:36:24 +08:00
|
|
|
ResR = Builder.CreateFNeg(Op.first, "neg.r");
|
|
|
|
ResI = Builder.CreateFNeg(Op.second, "neg.i");
|
|
|
|
} else {
|
|
|
|
ResR = Builder.CreateNeg(Op.first, "neg.r");
|
|
|
|
ResI = Builder.CreateNeg(Op.second, "neg.i");
|
|
|
|
}
|
2007-08-22 04:08:23 +08:00
|
|
|
return ComplexPairTy(ResR, ResI);
|
|
|
|
}
|
|
|
|
|
2007-08-22 04:41:44 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
|
2009-05-29 23:46:01 +08:00
|
|
|
TestAndClearIgnoreReal();
|
|
|
|
TestAndClearIgnoreImag();
|
2007-08-22 04:41:44 +08:00
|
|
|
// ~(a+ib) = a + i*-b
|
|
|
|
ComplexPairTy Op = Visit(E->getSubExpr());
|
2009-06-17 14:36:24 +08:00
|
|
|
llvm::Value *ResI;
|
2010-02-16 00:14:01 +08:00
|
|
|
if (Op.second->getType()->isFloatingPointTy())
|
2009-06-17 14:36:24 +08:00
|
|
|
ResI = Builder.CreateFNeg(Op.second, "conj.i");
|
|
|
|
else
|
|
|
|
ResI = Builder.CreateNeg(Op.second, "conj.i");
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-22 04:41:44 +08:00
|
|
|
return ComplexPairTy(Op.first, ResI);
|
|
|
|
}
|
2007-08-22 04:08:23 +08:00
|
|
|
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) {
|
2009-06-17 14:36:24 +08:00
|
|
|
llvm::Value *ResR, *ResI;
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2010-02-16 00:14:01 +08:00
|
|
|
if (Op.LHS.first->getType()->isFloatingPointTy()) {
|
2009-06-17 14:36:24 +08:00
|
|
|
ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r");
|
2014-10-11 08:57:18 +08:00
|
|
|
if (Op.LHS.second && Op.RHS.second)
|
|
|
|
ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i");
|
|
|
|
else
|
|
|
|
ResI = Op.LHS.second ? Op.LHS.second : Op.RHS.second;
|
|
|
|
assert(ResI && "Only one operand may be real!");
|
2009-06-17 14:36:24 +08:00
|
|
|
} else {
|
|
|
|
ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
|
2014-10-11 08:57:18 +08:00
|
|
|
assert(Op.LHS.second && Op.RHS.second &&
|
|
|
|
"Both operands of integer complex operators must be complex!");
|
2009-06-17 14:36:24 +08:00
|
|
|
ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
|
|
|
|
}
|
2007-08-21 13:54:00 +08:00
|
|
|
return ComplexPairTy(ResR, ResI);
|
|
|
|
}
|
|
|
|
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) {
|
2009-06-17 14:36:24 +08:00
|
|
|
llvm::Value *ResR, *ResI;
|
2010-02-16 00:14:01 +08:00
|
|
|
if (Op.LHS.first->getType()->isFloatingPointTy()) {
|
2014-10-11 08:57:18 +08:00
|
|
|
ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r");
|
|
|
|
if (Op.LHS.second && Op.RHS.second)
|
|
|
|
ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i");
|
|
|
|
else
|
|
|
|
ResI = Op.LHS.second ? Op.LHS.second
|
|
|
|
: Builder.CreateFNeg(Op.RHS.second, "sub.i");
|
|
|
|
assert(ResI && "Only one operand may be real!");
|
2009-06-17 14:36:24 +08:00
|
|
|
} else {
|
2014-10-11 08:57:18 +08:00
|
|
|
ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
|
|
|
|
assert(Op.LHS.second && Op.RHS.second &&
|
|
|
|
"Both operands of integer complex operators must be complex!");
|
2009-06-17 14:36:24 +08:00
|
|
|
ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
|
|
|
|
}
|
2007-08-24 07:46:33 +08:00
|
|
|
return ComplexPairTy(ResR, ResI);
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Emit a libcall for a binary operation on complex types.
|
2014-10-11 08:57:18 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
|
|
|
|
const BinOpInfo &Op) {
|
|
|
|
CallArgList Args;
|
|
|
|
Args.add(RValue::get(Op.LHS.first),
|
|
|
|
Op.Ty->castAs<ComplexType>()->getElementType());
|
|
|
|
Args.add(RValue::get(Op.LHS.second),
|
|
|
|
Op.Ty->castAs<ComplexType>()->getElementType());
|
|
|
|
Args.add(RValue::get(Op.RHS.first),
|
|
|
|
Op.Ty->castAs<ComplexType>()->getElementType());
|
|
|
|
Args.add(RValue::get(Op.RHS.second),
|
|
|
|
Op.Ty->castAs<ComplexType>()->getElementType());
|
|
|
|
|
|
|
|
// We *must* use the full CG function call building logic here because the
|
2014-12-03 00:04:58 +08:00
|
|
|
// complex type has special ABI handling. We also should not forget about
|
|
|
|
// special calling convention which may be used for compiler builtins.
|
2015-11-24 06:04:44 +08:00
|
|
|
|
|
|
|
// We create a function qualified type to state that this call does not have
|
|
|
|
// any exceptions.
|
|
|
|
FunctionProtoType::ExtProtoInfo EPI;
|
|
|
|
EPI = EPI.withExceptionSpec(
|
|
|
|
FunctionProtoType::ExceptionSpecInfo(EST_BasicNoexcept));
|
|
|
|
SmallVector<QualType, 4> ArgsQTys(
|
|
|
|
4, Op.Ty->castAs<ComplexType>()->getElementType());
|
|
|
|
QualType FQTy = CGF.getContext().getFunctionType(Op.Ty, ArgsQTys, EPI);
|
|
|
|
const CGFunctionInfo &FuncInfo = CGF.CGM.getTypes().arrangeFreeFunctionCall(
|
|
|
|
Args, cast<FunctionType>(FQTy.getTypePtr()), false);
|
|
|
|
|
2014-10-11 08:57:18 +08:00
|
|
|
llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(FuncInfo);
|
2019-02-06 00:42:33 +08:00
|
|
|
llvm::FunctionCallee Func = CGF.CGM.CreateRuntimeFunction(
|
|
|
|
FTy, LibCallName, llvm::AttributeList(), true);
|
2016-10-27 07:46:34 +08:00
|
|
|
CGCallee Callee = CGCallee::forDirect(Func, FQTy->getAs<FunctionProtoType>());
|
2014-10-11 08:57:18 +08:00
|
|
|
|
2019-01-30 10:54:28 +08:00
|
|
|
llvm::CallBase *Call;
|
2016-10-27 07:46:34 +08:00
|
|
|
RValue Res = CGF.EmitCall(FuncInfo, Callee, ReturnValueSlot(), Args, &Call);
|
2019-01-30 10:54:28 +08:00
|
|
|
Call->setCallingConv(CGF.CGM.getRuntimeCC());
|
2014-12-03 00:04:58 +08:00
|
|
|
return Res.getComplexVal();
|
2014-10-11 08:57:18 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Lookup the libcall name for a given floating point type complex
|
2014-10-20 03:13:49 +08:00
|
|
|
/// multiply.
|
|
|
|
static StringRef getComplexMultiplyLibCallName(llvm::Type *Ty) {
|
|
|
|
switch (Ty->getTypeID()) {
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Unsupported floating point type!");
|
|
|
|
case llvm::Type::HalfTyID:
|
|
|
|
return "__mulhc3";
|
|
|
|
case llvm::Type::FloatTyID:
|
|
|
|
return "__mulsc3";
|
|
|
|
case llvm::Type::DoubleTyID:
|
|
|
|
return "__muldc3";
|
|
|
|
case llvm::Type::PPC_FP128TyID:
|
|
|
|
return "__multc3";
|
|
|
|
case llvm::Type::X86_FP80TyID:
|
|
|
|
return "__mulxc3";
|
2014-10-21 09:34:34 +08:00
|
|
|
case llvm::Type::FP128TyID:
|
|
|
|
return "__multc3";
|
2014-10-20 03:13:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-11 08:57:18 +08:00
|
|
|
// See C11 Annex G.5.1 for the semantics of multiplicative operators on complex
|
|
|
|
// typed values.
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
|
2009-06-17 14:36:24 +08:00
|
|
|
using llvm::Value;
|
|
|
|
Value *ResR, *ResI;
|
2014-10-20 03:13:49 +08:00
|
|
|
llvm::MDBuilder MDHelper(CGF.getLLVMContext());
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2010-02-16 00:14:01 +08:00
|
|
|
if (Op.LHS.first->getType()->isFloatingPointTy()) {
|
2014-10-11 08:57:18 +08:00
|
|
|
// The general formulation is:
|
|
|
|
// (a + ib) * (c + id) = (a * c - b * d) + i(a * d + b * c)
|
|
|
|
//
|
|
|
|
// But we can fold away components which would be zero due to a real
|
|
|
|
// operand according to C11 Annex G.5.1p2.
|
|
|
|
// FIXME: C11 also provides for imaginary types which would allow folding
|
|
|
|
// still more of this within the type system.
|
|
|
|
|
|
|
|
if (Op.LHS.second && Op.RHS.second) {
|
2014-10-20 03:13:49 +08:00
|
|
|
// If both operands are complex, emit the core math directly, and then
|
|
|
|
// test for NaNs. If we find NaNs in the result, we delegate to a libcall
|
|
|
|
// to carefully re-compute the correct infinity representation if
|
|
|
|
// possible. The expectation is that the presence of NaNs here is
|
|
|
|
// *extremely* rare, and so the cost of the libcall is almost irrelevant.
|
|
|
|
// This is good, because the libcall re-computes the core multiplication
|
|
|
|
// exactly the same as we do here and re-tests for NaNs in order to be
|
|
|
|
// a generic complex*complex libcall.
|
|
|
|
|
|
|
|
// First compute the four products.
|
|
|
|
Value *AC = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul_ac");
|
|
|
|
Value *BD = Builder.CreateFMul(Op.LHS.second, Op.RHS.second, "mul_bd");
|
|
|
|
Value *AD = Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul_ad");
|
|
|
|
Value *BC = Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul_bc");
|
|
|
|
|
|
|
|
// The real part is the difference of the first two, the imaginary part is
|
|
|
|
// the sum of the second.
|
|
|
|
ResR = Builder.CreateFSub(AC, BD, "mul_r");
|
|
|
|
ResI = Builder.CreateFAdd(AD, BC, "mul_i");
|
|
|
|
|
|
|
|
// Emit the test for the real part becoming NaN and create a branch to
|
|
|
|
// handle it. We test for NaN by comparing the number to itself.
|
|
|
|
Value *IsRNaN = Builder.CreateFCmpUNO(ResR, ResR, "isnan_cmp");
|
|
|
|
llvm::BasicBlock *ContBB = CGF.createBasicBlock("complex_mul_cont");
|
|
|
|
llvm::BasicBlock *INaNBB = CGF.createBasicBlock("complex_mul_imag_nan");
|
|
|
|
llvm::Instruction *Branch = Builder.CreateCondBr(IsRNaN, INaNBB, ContBB);
|
|
|
|
llvm::BasicBlock *OrigBB = Branch->getParent();
|
|
|
|
|
|
|
|
// Give hint that we very much don't expect to see NaNs.
|
|
|
|
// Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp
|
|
|
|
llvm::MDNode *BrWeight = MDHelper.createBranchWeights(1, (1U << 20) - 1);
|
|
|
|
Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight);
|
|
|
|
|
|
|
|
// Now test the imaginary part and create its branch.
|
|
|
|
CGF.EmitBlock(INaNBB);
|
|
|
|
Value *IsINaN = Builder.CreateFCmpUNO(ResI, ResI, "isnan_cmp");
|
|
|
|
llvm::BasicBlock *LibCallBB = CGF.createBasicBlock("complex_mul_libcall");
|
|
|
|
Branch = Builder.CreateCondBr(IsINaN, LibCallBB, ContBB);
|
|
|
|
Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight);
|
|
|
|
|
|
|
|
// Now emit the libcall on this slowest of the slow paths.
|
|
|
|
CGF.EmitBlock(LibCallBB);
|
|
|
|
Value *LibCallR, *LibCallI;
|
|
|
|
std::tie(LibCallR, LibCallI) = EmitComplexBinOpLibCall(
|
|
|
|
getComplexMultiplyLibCallName(Op.LHS.first->getType()), Op);
|
|
|
|
Builder.CreateBr(ContBB);
|
|
|
|
|
|
|
|
// Finally continue execution by phi-ing together the different
|
|
|
|
// computation paths.
|
|
|
|
CGF.EmitBlock(ContBB);
|
|
|
|
llvm::PHINode *RealPHI = Builder.CreatePHI(ResR->getType(), 3, "real_mul_phi");
|
|
|
|
RealPHI->addIncoming(ResR, OrigBB);
|
|
|
|
RealPHI->addIncoming(ResR, INaNBB);
|
|
|
|
RealPHI->addIncoming(LibCallR, LibCallBB);
|
|
|
|
llvm::PHINode *ImagPHI = Builder.CreatePHI(ResI->getType(), 3, "imag_mul_phi");
|
|
|
|
ImagPHI->addIncoming(ResI, OrigBB);
|
|
|
|
ImagPHI->addIncoming(ResI, INaNBB);
|
|
|
|
ImagPHI->addIncoming(LibCallI, LibCallBB);
|
|
|
|
return ComplexPairTy(RealPHI, ImagPHI);
|
2014-10-11 08:57:18 +08:00
|
|
|
}
|
|
|
|
assert((Op.LHS.second || Op.RHS.second) &&
|
|
|
|
"At least one operand must be complex!");
|
|
|
|
|
|
|
|
// If either of the operands is a real rather than a complex, the
|
|
|
|
// imaginary component is ignored when computing the real component of the
|
|
|
|
// result.
|
|
|
|
ResR = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul.rl");
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2014-10-11 08:57:18 +08:00
|
|
|
ResI = Op.LHS.second
|
|
|
|
? Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul.il")
|
|
|
|
: Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul.ir");
|
2009-06-17 14:36:24 +08:00
|
|
|
} else {
|
2014-10-11 08:57:18 +08:00
|
|
|
assert(Op.LHS.second && Op.RHS.second &&
|
|
|
|
"Both operands of integer complex operators must be complex!");
|
2009-06-17 14:36:24 +08:00
|
|
|
Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
|
2014-10-11 08:57:18 +08:00
|
|
|
Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second, "mul.rr");
|
|
|
|
ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2009-06-17 14:36:24 +08:00
|
|
|
Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
|
|
|
|
Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
|
2014-10-11 08:57:18 +08:00
|
|
|
ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
|
2009-06-17 14:36:24 +08:00
|
|
|
}
|
2007-08-22 00:34:16 +08:00
|
|
|
return ComplexPairTy(ResR, ResI);
|
|
|
|
}
|
|
|
|
|
2014-10-11 08:57:18 +08:00
|
|
|
// See C11 Annex G.5.1 for the semantics of multiplicative operators on complex
|
|
|
|
// typed values.
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
|
|
|
|
llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second;
|
|
|
|
llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second;
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-27 05:24:19 +08:00
|
|
|
llvm::Value *DSTr, *DSTi;
|
2014-10-11 08:57:18 +08:00
|
|
|
if (LHSr->getType()->isFloatingPointTy()) {
|
2017-12-20 23:50:52 +08:00
|
|
|
// If we have a complex operand on the RHS and FastMath is not allowed, we
|
|
|
|
// delegate to a libcall to handle all of the complexities and minimize
|
|
|
|
// underflow/overflow cases. When FastMath is allowed we construct the
|
|
|
|
// divide inline using the same algorithm as for integer operands.
|
2014-10-11 08:57:18 +08:00
|
|
|
//
|
|
|
|
// FIXME: We would be able to avoid the libcall in many places if we
|
|
|
|
// supported imaginary types in addition to complex types.
|
2017-12-20 23:50:52 +08:00
|
|
|
if (RHSi && !CGF.getLangOpts().FastMath) {
|
2014-10-11 08:57:18 +08:00
|
|
|
BinOpInfo LibCallOp = Op;
|
|
|
|
// If LHS was a real, supply a null imaginary part.
|
|
|
|
if (!LHSi)
|
|
|
|
LibCallOp.LHS.second = llvm::Constant::getNullValue(LHSr->getType());
|
|
|
|
|
|
|
|
switch (LHSr->getType()->getTypeID()) {
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Unsupported floating point type!");
|
|
|
|
case llvm::Type::HalfTyID:
|
|
|
|
return EmitComplexBinOpLibCall("__divhc3", LibCallOp);
|
|
|
|
case llvm::Type::FloatTyID:
|
|
|
|
return EmitComplexBinOpLibCall("__divsc3", LibCallOp);
|
|
|
|
case llvm::Type::DoubleTyID:
|
|
|
|
return EmitComplexBinOpLibCall("__divdc3", LibCallOp);
|
2014-10-17 19:51:19 +08:00
|
|
|
case llvm::Type::PPC_FP128TyID:
|
|
|
|
return EmitComplexBinOpLibCall("__divtc3", LibCallOp);
|
2014-10-11 08:57:18 +08:00
|
|
|
case llvm::Type::X86_FP80TyID:
|
|
|
|
return EmitComplexBinOpLibCall("__divxc3", LibCallOp);
|
2014-10-21 09:34:34 +08:00
|
|
|
case llvm::Type::FP128TyID:
|
|
|
|
return EmitComplexBinOpLibCall("__divtc3", LibCallOp);
|
2014-10-11 08:57:18 +08:00
|
|
|
}
|
2017-12-20 23:50:52 +08:00
|
|
|
} else if (RHSi) {
|
|
|
|
if (!LHSi)
|
|
|
|
LHSi = llvm::Constant::getNullValue(RHSi->getType());
|
|
|
|
|
|
|
|
// (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
|
|
|
|
llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr); // a*c
|
|
|
|
llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi); // b*d
|
|
|
|
llvm::Value *ACpBD = Builder.CreateFAdd(AC, BD); // ac+bd
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2017-12-20 23:50:52 +08:00
|
|
|
llvm::Value *CC = Builder.CreateFMul(RHSr, RHSr); // c*c
|
|
|
|
llvm::Value *DD = Builder.CreateFMul(RHSi, RHSi); // d*d
|
|
|
|
llvm::Value *CCpDD = Builder.CreateFAdd(CC, DD); // cc+dd
|
|
|
|
|
|
|
|
llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr); // b*c
|
|
|
|
llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi); // a*d
|
|
|
|
llvm::Value *BCmAD = Builder.CreateFSub(BC, AD); // bc-ad
|
|
|
|
|
|
|
|
DSTr = Builder.CreateFDiv(ACpBD, CCpDD);
|
|
|
|
DSTi = Builder.CreateFDiv(BCmAD, CCpDD);
|
|
|
|
} else {
|
|
|
|
assert(LHSi && "Can have at most one non-complex operand!");
|
|
|
|
|
|
|
|
DSTr = Builder.CreateFDiv(LHSr, RHSr);
|
|
|
|
DSTi = Builder.CreateFDiv(LHSi, RHSr);
|
|
|
|
}
|
2007-08-27 05:24:19 +08:00
|
|
|
} else {
|
2014-10-11 08:57:18 +08:00
|
|
|
assert(Op.LHS.second && Op.RHS.second &&
|
|
|
|
"Both operands of integer complex operators must be complex!");
|
2009-06-17 14:36:24 +08:00
|
|
|
// (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
|
2011-09-28 05:06:10 +08:00
|
|
|
llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c
|
|
|
|
llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d
|
|
|
|
llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2); // ac+bd
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2011-09-28 05:06:10 +08:00
|
|
|
llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr); // c*c
|
|
|
|
llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi); // d*d
|
|
|
|
llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5); // cc+dd
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2011-09-28 05:06:10 +08:00
|
|
|
llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr); // b*c
|
|
|
|
llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi); // a*d
|
|
|
|
llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8); // bc-ad
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2013-03-08 05:37:08 +08:00
|
|
|
if (Op.Ty->castAs<ComplexType>()->getElementType()->isUnsignedIntegerType()) {
|
2011-09-28 05:06:10 +08:00
|
|
|
DSTr = Builder.CreateUDiv(Tmp3, Tmp6);
|
|
|
|
DSTi = Builder.CreateUDiv(Tmp9, Tmp6);
|
2007-08-27 05:24:19 +08:00
|
|
|
} else {
|
2011-09-28 05:06:10 +08:00
|
|
|
DSTr = Builder.CreateSDiv(Tmp3, Tmp6);
|
|
|
|
DSTi = Builder.CreateSDiv(Tmp9, Tmp6);
|
2007-08-27 05:24:19 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-27 05:24:19 +08:00
|
|
|
return ComplexPairTy(DSTr, DSTi);
|
|
|
|
}
|
|
|
|
|
2009-09-09 21:00:44 +08:00
|
|
|
ComplexExprEmitter::BinOpInfo
|
2007-08-27 06:09:01 +08:00
|
|
|
ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
|
2009-05-29 23:46:01 +08:00
|
|
|
TestAndClearIgnoreReal();
|
|
|
|
TestAndClearIgnoreImag();
|
2007-08-27 06:09:01 +08:00
|
|
|
BinOpInfo Ops;
|
2014-10-11 08:57:18 +08:00
|
|
|
if (E->getLHS()->getType()->isRealFloatingType())
|
|
|
|
Ops.LHS = ComplexPairTy(CGF.EmitScalarExpr(E->getLHS()), nullptr);
|
|
|
|
else
|
|
|
|
Ops.LHS = Visit(E->getLHS());
|
|
|
|
if (E->getRHS()->getType()->isRealFloatingType())
|
|
|
|
Ops.RHS = ComplexPairTy(CGF.EmitScalarExpr(E->getRHS()), nullptr);
|
|
|
|
else
|
|
|
|
Ops.RHS = Visit(E->getRHS());
|
|
|
|
|
2007-08-27 06:09:01 +08:00
|
|
|
Ops.Ty = E->getType();
|
|
|
|
return Ops;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-16 18:08:07 +08:00
|
|
|
LValue ComplexExprEmitter::
|
|
|
|
EmitCompoundAssignLValue(const CompoundAssignOperator *E,
|
|
|
|
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
|
2013-06-12 09:40:06 +08:00
|
|
|
RValue &Val) {
|
2009-05-29 23:46:01 +08:00
|
|
|
TestAndClearIgnoreReal();
|
|
|
|
TestAndClearIgnoreImag();
|
2011-01-18 10:00:16 +08:00
|
|
|
QualType LHSTy = E->getLHS()->getType();
|
2015-02-14 09:48:17 +08:00
|
|
|
if (const AtomicType *AT = LHSTy->getAs<AtomicType>())
|
|
|
|
LHSTy = AT->getValueType();
|
2007-08-27 06:09:01 +08:00
|
|
|
|
|
|
|
BinOpInfo OpInfo;
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2009-05-29 23:46:01 +08:00
|
|
|
// Load the RHS and LHS operands.
|
|
|
|
// __block variables need to have the rhs evaluated first, plus this should
|
2010-11-16 13:45:35 +08:00
|
|
|
// improve codegen a little.
|
2009-03-28 09:22:36 +08:00
|
|
|
OpInfo.Ty = E->getComputationResultType();
|
2014-10-11 08:57:18 +08:00
|
|
|
QualType ComplexElementTy = cast<ComplexType>(OpInfo.Ty)->getElementType();
|
2010-11-16 13:45:35 +08:00
|
|
|
|
|
|
|
// The RHS should have been converted to the computation type.
|
2014-10-11 08:57:18 +08:00
|
|
|
if (E->getRHS()->getType()->isRealFloatingType()) {
|
|
|
|
assert(
|
|
|
|
CGF.getContext()
|
|
|
|
.hasSameUnqualifiedType(ComplexElementTy, E->getRHS()->getType()));
|
|
|
|
OpInfo.RHS = ComplexPairTy(CGF.EmitScalarExpr(E->getRHS()), nullptr);
|
|
|
|
} else {
|
|
|
|
assert(CGF.getContext()
|
|
|
|
.hasSameUnqualifiedType(OpInfo.Ty, E->getRHS()->getType()));
|
|
|
|
OpInfo.RHS = Visit(E->getRHS());
|
|
|
|
}
|
2013-11-22 18:20:40 +08:00
|
|
|
|
2010-06-30 06:44:21 +08:00
|
|
|
LValue LHS = CGF.EmitLValue(E->getLHS());
|
2010-12-04 16:14:53 +08:00
|
|
|
|
2013-06-12 09:40:06 +08:00
|
|
|
// Load from the l-value and convert it.
|
2015-08-11 12:19:28 +08:00
|
|
|
SourceLocation Loc = E->getExprLoc();
|
2013-06-12 09:40:06 +08:00
|
|
|
if (LHSTy->isAnyComplexType()) {
|
2015-08-11 12:19:28 +08:00
|
|
|
ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, Loc);
|
|
|
|
OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc);
|
2013-06-12 09:40:06 +08:00
|
|
|
} else {
|
2015-08-11 12:19:28 +08:00
|
|
|
llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS, Loc);
|
2014-10-11 08:57:18 +08:00
|
|
|
// For floating point real operands we can directly pass the scalar form
|
|
|
|
// to the binary operator emission and potentially get more efficient code.
|
|
|
|
if (LHSTy->isRealFloatingType()) {
|
|
|
|
if (!CGF.getContext().hasSameUnqualifiedType(ComplexElementTy, LHSTy))
|
2015-08-11 12:19:28 +08:00
|
|
|
LHSVal = CGF.EmitScalarConversion(LHSVal, LHSTy, ComplexElementTy, Loc);
|
2014-10-11 08:57:18 +08:00
|
|
|
OpInfo.LHS = ComplexPairTy(LHSVal, nullptr);
|
|
|
|
} else {
|
2015-08-11 12:19:28 +08:00
|
|
|
OpInfo.LHS = EmitScalarToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc);
|
2014-10-11 08:57:18 +08:00
|
|
|
}
|
2013-06-12 09:40:06 +08:00
|
|
|
}
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-27 06:09:01 +08:00
|
|
|
// Expand the binary operator.
|
|
|
|
ComplexPairTy Result = (this->*Func)(OpInfo);
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2013-06-12 09:40:06 +08:00
|
|
|
// Truncate the result and store it into the LHS lvalue.
|
|
|
|
if (LHSTy->isAnyComplexType()) {
|
2015-08-11 12:19:28 +08:00
|
|
|
ComplexPairTy ResVal =
|
|
|
|
EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy, Loc);
|
2015-01-14 15:38:27 +08:00
|
|
|
EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false);
|
2013-06-12 09:40:06 +08:00
|
|
|
Val = RValue::getComplex(ResVal);
|
|
|
|
} else {
|
|
|
|
llvm::Value *ResVal =
|
2015-08-11 12:19:28 +08:00
|
|
|
CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy, Loc);
|
2013-06-12 09:40:06 +08:00
|
|
|
CGF.EmitStoreOfScalar(ResVal, LHS, /*isInit*/ false);
|
|
|
|
Val = RValue::get(ResVal);
|
|
|
|
}
|
2010-06-30 06:44:21 +08:00
|
|
|
|
2010-11-16 18:08:07 +08:00
|
|
|
return LHS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compound assignments.
|
|
|
|
ComplexPairTy ComplexExprEmitter::
|
|
|
|
EmitCompoundAssign(const CompoundAssignOperator *E,
|
|
|
|
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
|
2013-06-12 09:40:06 +08:00
|
|
|
RValue Val;
|
2010-11-16 18:08:07 +08:00
|
|
|
LValue LV = EmitCompoundAssignLValue(E, Func, Val);
|
|
|
|
|
|
|
|
// The result of an assignment in C is the assigned r-value.
|
2012-11-02 06:30:59 +08:00
|
|
|
if (!CGF.getLangOpts().CPlusPlus)
|
2013-06-12 09:40:06 +08:00
|
|
|
return Val.getComplexVal();
|
2010-11-16 18:08:07 +08:00
|
|
|
|
|
|
|
// If the lvalue is non-volatile, return the computed value of the assignment.
|
|
|
|
if (!LV.isVolatileQualified())
|
2013-06-12 09:40:06 +08:00
|
|
|
return Val.getComplexVal();
|
2010-11-16 18:08:07 +08:00
|
|
|
|
2013-10-02 10:29:49 +08:00
|
|
|
return EmitLoadOfLValue(LV, E->getExprLoc());
|
2007-08-27 06:09:01 +08:00
|
|
|
}
|
2007-08-27 05:24:19 +08:00
|
|
|
|
2010-11-16 18:08:07 +08:00
|
|
|
LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E,
|
|
|
|
ComplexPairTy &Val) {
|
2013-11-22 18:20:40 +08:00
|
|
|
assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(),
|
2010-07-14 02:40:04 +08:00
|
|
|
E->getRHS()->getType()) &&
|
2008-07-27 06:37:01 +08:00
|
|
|
"Invalid assignment");
|
2010-11-16 18:08:07 +08:00
|
|
|
TestAndClearIgnoreReal();
|
|
|
|
TestAndClearIgnoreImag();
|
|
|
|
|
2010-12-06 14:10:02 +08:00
|
|
|
// Emit the RHS. __block variables need the RHS evaluated first.
|
2010-11-16 18:08:07 +08:00
|
|
|
Val = Visit(E->getRHS());
|
2007-08-21 13:54:00 +08:00
|
|
|
|
|
|
|
// Compute the address to store into.
|
|
|
|
LValue LHS = CGF.EmitLValue(E->getLHS());
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2010-06-30 06:44:21 +08:00
|
|
|
// Store the result value into the LHS lvalue.
|
2015-01-14 15:38:27 +08:00
|
|
|
EmitStoreOfComplex(Val, LHS, /*isInit*/ false);
|
2009-06-10 12:38:50 +08:00
|
|
|
|
2010-11-16 18:08:07 +08:00
|
|
|
return LHS;
|
|
|
|
}
|
2010-06-30 06:44:21 +08:00
|
|
|
|
2010-11-16 18:08:07 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
|
|
|
ComplexPairTy Val;
|
|
|
|
LValue LV = EmitBinAssignLValue(E, Val);
|
|
|
|
|
|
|
|
// The result of an assignment in C is the assigned r-value.
|
2012-11-02 06:30:59 +08:00
|
|
|
if (!CGF.getLangOpts().CPlusPlus)
|
2010-11-16 18:08:07 +08:00
|
|
|
return Val;
|
|
|
|
|
|
|
|
// If the lvalue is non-volatile, return the computed value of the assignment.
|
|
|
|
if (!LV.isVolatileQualified())
|
|
|
|
return Val;
|
|
|
|
|
2013-10-02 10:29:49 +08:00
|
|
|
return EmitLoadOfLValue(LV, E->getExprLoc());
|
2007-08-21 13:54:00 +08:00
|
|
|
}
|
|
|
|
|
2007-08-22 01:15:50 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
|
2010-12-05 10:00:02 +08:00
|
|
|
CGF.EmitIgnoredExpr(E->getLHS());
|
2007-08-22 01:15:50 +08:00
|
|
|
return Visit(E->getRHS());
|
|
|
|
}
|
2007-08-21 13:54:00 +08:00
|
|
|
|
|
|
|
ComplexPairTy ComplexExprEmitter::
|
2011-02-17 18:25:35 +08:00
|
|
|
VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
|
2009-05-29 23:46:01 +08:00
|
|
|
TestAndClearIgnoreReal();
|
|
|
|
TestAndClearIgnoreImag();
|
2008-11-13 09:38:36 +08:00
|
|
|
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
|
|
|
|
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
|
|
|
|
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2011-02-17 18:25:35 +08:00
|
|
|
// Bind the common expression if necessary.
|
2012-01-07 04:42:20 +08:00
|
|
|
CodeGenFunction::OpaqueValueMapping binding(CGF, E);
|
2011-01-26 12:00:11 +08:00
|
|
|
|
2015-04-24 07:06:47 +08:00
|
|
|
|
2011-02-17 18:25:35 +08:00
|
|
|
CodeGenFunction::ConditionalEvaluation eval(CGF);
|
2015-04-24 07:06:47 +08:00
|
|
|
CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock,
|
|
|
|
CGF.getProfileCount(E));
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2011-01-26 12:00:11 +08:00
|
|
|
eval.begin(CGF);
|
2007-08-21 13:54:00 +08:00
|
|
|
CGF.EmitBlock(LHSBlock);
|
2015-04-24 07:06:47 +08:00
|
|
|
CGF.incrementProfileCounter(E);
|
2010-09-21 07:50:22 +08:00
|
|
|
ComplexPairTy LHS = Visit(E->getTrueExpr());
|
2007-08-22 01:39:38 +08:00
|
|
|
LHSBlock = Builder.GetInsertBlock();
|
2008-11-11 17:41:28 +08:00
|
|
|
CGF.EmitBranch(ContBlock);
|
2011-01-26 12:00:11 +08:00
|
|
|
eval.end(CGF);
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2011-01-26 12:00:11 +08:00
|
|
|
eval.begin(CGF);
|
2007-08-21 13:54:00 +08:00
|
|
|
CGF.EmitBlock(RHSBlock);
|
2011-02-17 18:25:35 +08:00
|
|
|
ComplexPairTy RHS = Visit(E->getFalseExpr());
|
2007-08-22 01:39:38 +08:00
|
|
|
RHSBlock = Builder.GetInsertBlock();
|
2007-08-21 13:54:00 +08:00
|
|
|
CGF.EmitBlock(ContBlock);
|
2011-01-26 12:00:11 +08:00
|
|
|
eval.end(CGF);
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
// Create a PHI node for the real part.
|
2011-03-30 19:28:58 +08:00
|
|
|
llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.r");
|
2007-08-21 13:54:00 +08:00
|
|
|
RealPN->addIncoming(LHS.first, LHSBlock);
|
|
|
|
RealPN->addIncoming(RHS.first, RHSBlock);
|
|
|
|
|
|
|
|
// Create a PHI node for the imaginary part.
|
2011-03-30 19:28:58 +08:00
|
|
|
llvm::PHINode *ImagPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.i");
|
2007-08-21 13:54:00 +08:00
|
|
|
ImagPN->addIncoming(LHS.second, LHSBlock);
|
|
|
|
ImagPN->addIncoming(RHS.second, RHSBlock);
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
return ComplexPairTy(RealPN, ImagPN);
|
|
|
|
}
|
|
|
|
|
2007-08-24 10:18:47 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) {
|
2013-07-20 08:40:58 +08:00
|
|
|
return Visit(E->getChosenSubExpr());
|
2007-08-24 10:18:47 +08:00
|
|
|
}
|
|
|
|
|
2008-05-14 07:11:35 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
2009-05-29 23:46:01 +08:00
|
|
|
bool Ignore = TestAndClearIgnoreReal();
|
|
|
|
(void)Ignore;
|
|
|
|
assert (Ignore == false && "init list ignored");
|
|
|
|
Ignore = TestAndClearIgnoreImag();
|
|
|
|
(void)Ignore;
|
|
|
|
assert (Ignore == false && "init list ignored");
|
2011-09-20 07:17:44 +08:00
|
|
|
|
|
|
|
if (E->getNumInits() == 2) {
|
|
|
|
llvm::Value *Real = CGF.EmitScalarExpr(E->getInit(0));
|
|
|
|
llvm::Value *Imag = CGF.EmitScalarExpr(E->getInit(1));
|
|
|
|
return ComplexPairTy(Real, Imag);
|
|
|
|
} else if (E->getNumInits() == 1) {
|
2008-05-14 07:11:35 +08:00
|
|
|
return Visit(E->getInit(0));
|
2011-09-20 07:17:44 +08:00
|
|
|
}
|
2008-05-14 07:11:35 +08:00
|
|
|
|
2018-04-06 23:14:32 +08:00
|
|
|
// Empty init list initializes to null
|
2011-09-20 07:17:44 +08:00
|
|
|
assert(E->getNumInits() == 0 && "Unexpected number of inits");
|
2013-03-08 05:37:08 +08:00
|
|
|
QualType Ty = E->getType()->castAs<ComplexType>()->getElementType();
|
2011-07-18 12:24:23 +08:00
|
|
|
llvm::Type* LTy = CGF.ConvertType(Ty);
|
2009-08-01 04:28:54 +08:00
|
|
|
llvm::Value* zeroConstant = llvm::Constant::getNullValue(LTy);
|
2008-05-14 07:11:35 +08:00
|
|
|
return ComplexPairTy(zeroConstant, zeroConstant);
|
|
|
|
}
|
|
|
|
|
2009-02-10 11:03:30 +08:00
|
|
|
ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
|
2015-09-18 04:55:33 +08:00
|
|
|
Address ArgValue = Address::invalid();
|
|
|
|
Address ArgPtr = CGF.EmitVAArg(E, ArgValue);
|
2009-02-10 11:03:30 +08:00
|
|
|
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
if (!ArgPtr.isValid()) {
|
2009-02-10 11:03:30 +08:00
|
|
|
CGF.ErrorUnsupported(E, "complex va_arg expression");
|
2011-07-18 12:24:23 +08:00
|
|
|
llvm::Type *EltTy =
|
2013-03-08 05:37:08 +08:00
|
|
|
CGF.ConvertType(E->getType()->castAs<ComplexType>()->getElementType());
|
2009-02-10 11:03:30 +08:00
|
|
|
llvm::Value *U = llvm::UndefValue::get(EltTy);
|
|
|
|
return ComplexPairTy(U, U);
|
|
|
|
}
|
|
|
|
|
Compute and preserve alignment more faithfully in IR-generation.
Introduce an Address type to bundle a pointer value with an
alignment. Introduce APIs on CGBuilderTy to work with Address
values. Change core APIs on CGF/CGM to traffic in Address where
appropriate. Require alignments to be non-zero. Update a ton
of code to compute and propagate alignment information.
As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment
helper function to CGF and made use of it in a number of places in
the expression emitter.
The end result is that we should now be significantly more correct
when performing operations on objects that are locally known to
be under-aligned. Since alignment is not reliably tracked in the
type system, there are inherent limits to this, but at least we
are no longer confused by standard operations like derived-to-base
conversions and array-to-pointer decay. I've also fixed a large
number of bugs where we were applying the complete-object alignment
to a pointer instead of the non-virtual alignment, although most of
these were hidden by the very conservative approach we took with
member alignment.
Also, because IRGen now reliably asserts on zero alignments, we
should no longer be subject to an absurd but frustrating recurring
bug where an incomplete type would report a zero alignment and then
we'd naively do a alignmentAtOffset on it and emit code using an
alignment equal to the largest power-of-two factor of the offset.
We should also now be emitting much more aggressive alignment
attributes in the presence of over-alignment. In particular,
field access now uses alignmentAtOffset instead of min.
Several times in this patch, I had to change the existing
code-generation pattern in order to more effectively use
the Address APIs. For the most part, this seems to be a strict
improvement, like doing pointer arithmetic with GEPs instead of
ptrtoint. That said, I've tried very hard to not change semantics,
but it is likely that I've failed in a few places, for which I
apologize.
ABIArgInfo now always carries the assumed alignment of indirect and
indirect byval arguments. In order to cut down on what was already
a dauntingly large patch, I changed the code to never set align
attributes in the IR on non-byval indirect arguments. That is,
we still generate code which assumes that indirect arguments have
the given alignment, but we don't express this information to the
backend except where it's semantically required (i.e. on byvals).
This is likely a minor regression for those targets that did provide
this information, but it'll be trivial to add it back in a later
patch.
I partially punted on applying this work to CGBuiltin. Please
do not add more uses of the CreateDefaultAligned{Load,Store}
APIs; they will be going away eventually.
llvm-svn: 246985
2015-09-08 16:05:57 +08:00
|
|
|
return EmitLoadOfLValue(CGF.MakeAddrLValue(ArgPtr, E->getType()),
|
2013-10-02 10:29:49 +08:00
|
|
|
E->getExprLoc());
|
2009-02-10 11:03:30 +08:00
|
|
|
}
|
|
|
|
|
2007-08-21 13:54:00 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Entry Point into this File
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// EmitComplexExpr - Emit the computation of the specified expression of
|
|
|
|
/// complex type, ignoring the result.
|
2009-05-29 23:46:01 +08:00
|
|
|
ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal,
|
2010-11-16 18:08:07 +08:00
|
|
|
bool IgnoreImag) {
|
2013-03-08 05:37:08 +08:00
|
|
|
assert(E && getComplexType(E->getType()) &&
|
2007-08-21 13:54:00 +08:00
|
|
|
"Invalid complex expression to emit");
|
2009-09-09 21:00:44 +08:00
|
|
|
|
2015-02-10 03:13:51 +08:00
|
|
|
return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag)
|
|
|
|
.Visit(const_cast<Expr *>(E));
|
2007-08-21 13:54:00 +08:00
|
|
|
}
|
|
|
|
|
2013-03-08 05:37:08 +08:00
|
|
|
void CodeGenFunction::EmitComplexExprIntoLValue(const Expr *E, LValue dest,
|
2015-01-14 15:38:27 +08:00
|
|
|
bool isInit) {
|
2013-03-08 05:37:08 +08:00
|
|
|
assert(E && getComplexType(E->getType()) &&
|
2007-08-24 07:43:33 +08:00
|
|
|
"Invalid complex expression to emit");
|
|
|
|
ComplexExprEmitter Emitter(*this);
|
|
|
|
ComplexPairTy Val = Emitter.Visit(const_cast<Expr*>(E));
|
2015-01-14 15:38:27 +08:00
|
|
|
Emitter.EmitStoreOfComplex(Val, dest, isInit);
|
2007-08-24 07:43:33 +08:00
|
|
|
}
|
2007-09-01 06:49:20 +08:00
|
|
|
|
2013-03-08 05:37:08 +08:00
|
|
|
/// EmitStoreOfComplex - Store a complex number into the specified l-value.
|
|
|
|
void CodeGenFunction::EmitStoreOfComplex(ComplexPairTy V, LValue dest,
|
2015-01-14 15:38:27 +08:00
|
|
|
bool isInit) {
|
|
|
|
ComplexExprEmitter(*this).EmitStoreOfComplex(V, dest, isInit);
|
2008-08-30 13:35:15 +08:00
|
|
|
}
|
|
|
|
|
2013-03-08 05:37:08 +08:00
|
|
|
/// EmitLoadOfComplex - Load a complex number from the specified address.
|
2013-10-02 10:29:49 +08:00
|
|
|
ComplexPairTy CodeGenFunction::EmitLoadOfComplex(LValue src,
|
|
|
|
SourceLocation loc) {
|
|
|
|
return ComplexExprEmitter(*this).EmitLoadOfLValue(src, loc);
|
2007-09-01 06:49:20 +08:00
|
|
|
}
|
2010-11-17 07:07:28 +08:00
|
|
|
|
|
|
|
LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) {
|
2010-12-05 10:00:02 +08:00
|
|
|
assert(E->getOpcode() == BO_Assign);
|
2010-11-17 07:07:28 +08:00
|
|
|
ComplexPairTy Val; // ignored
|
2019-12-27 22:44:43 +08:00
|
|
|
LValue LVal = ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val);
|
|
|
|
if (getLangOpts().OpenMP)
|
|
|
|
CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(*this,
|
|
|
|
E->getLHS());
|
|
|
|
return LVal;
|
2010-12-05 10:00:02 +08:00
|
|
|
}
|
2010-11-17 07:07:28 +08:00
|
|
|
|
2013-06-12 09:40:06 +08:00
|
|
|
typedef ComplexPairTy (ComplexExprEmitter::*CompoundFunc)(
|
|
|
|
const ComplexExprEmitter::BinOpInfo &);
|
2010-11-17 07:07:28 +08:00
|
|
|
|
2013-06-12 09:40:06 +08:00
|
|
|
static CompoundFunc getComplexOp(BinaryOperatorKind Op) {
|
|
|
|
switch (Op) {
|
|
|
|
case BO_MulAssign: return &ComplexExprEmitter::EmitBinMul;
|
|
|
|
case BO_DivAssign: return &ComplexExprEmitter::EmitBinDiv;
|
|
|
|
case BO_SubAssign: return &ComplexExprEmitter::EmitBinSub;
|
|
|
|
case BO_AddAssign: return &ComplexExprEmitter::EmitBinAdd;
|
2010-11-17 07:07:28 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected complex compound assignment");
|
|
|
|
}
|
2013-06-12 09:40:06 +08:00
|
|
|
}
|
2010-11-17 07:07:28 +08:00
|
|
|
|
2013-06-12 09:40:06 +08:00
|
|
|
LValue CodeGenFunction::
|
|
|
|
EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
|
|
|
|
CompoundFunc Op = getComplexOp(E->getOpcode());
|
|
|
|
RValue Val;
|
2010-12-05 10:00:02 +08:00
|
|
|
return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
|
2010-11-17 07:07:28 +08:00
|
|
|
}
|
2013-06-12 09:40:06 +08:00
|
|
|
|
|
|
|
LValue CodeGenFunction::
|
2015-02-13 05:23:20 +08:00
|
|
|
EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E,
|
|
|
|
llvm::Value *&Result) {
|
2013-06-12 09:40:06 +08:00
|
|
|
CompoundFunc Op = getComplexOp(E->getOpcode());
|
|
|
|
RValue Val;
|
|
|
|
LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
|
|
|
|
Result = Val.getScalarVal();
|
|
|
|
return Ret;
|
|
|
|
}
|