gollvm: fix an unary minus operations effect on expressions of complex types
The current implementation translates '-EXPR' into
'ZERO_EXPR - EXPR'. It handles EXPR of floating-point types as a
special case for which ZERO_EXPR is -0.0. This change applies the
same approach to EXPR of complex types so that '-CMPLX_EXPR'
translates into '(-0.0-0.0i) - CMPLX_EXPR' instead of
'(0.0+0.0i) - CMPLX_EXPR'.
Updates golang/go#51648
Change-Id: I66bcfaa9864a83d108c2719fe6dce59975e1c205
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/393595
Reviewed-by: Than McIntosh <thanm@google.com>
Trust: Bryan Mills <bcmills@google.com>
diff --git a/bridge/go-llvm.cpp b/bridge/go-llvm.cpp
index 301a062..312b38b 100644
--- a/bridge/go-llvm.cpp
+++ b/bridge/go-llvm.cpp
@@ -1531,10 +1531,21 @@
Btype *bt = expr->btype();
+ // Special handling for unary minus applied to fp or complex type.
if (op == OPERATOR_MINUS) {
- // Special handling for unary minus applied to fp type.
- BFloatType *ft = bt->castToBFloatType();
- Bexpression *zerexp = (ft ? minusZeroExpr(ft) : zero_expression(bt));
+ Bexpression *zerexp;
+
+ switch (bt->flavor()) {
+ case Btype::FloatT:
+ zerexp = minusZeroExpr(bt->castToBFloatType());
+ break;
+ case Btype::ComplexT:
+ zerexp = minusZeroExpr(bt->castToBComplexType());
+ break;
+ default:
+ zerexp = zero_expression(bt);
+ }
+
return binary_expression(OPERATOR_MINUS, zerexp, expr, location);
}
@@ -1542,6 +1553,21 @@
return rval;
}
+Bexpression *Llvm_backend::minusZeroExpr(BComplexType *typ)
+{
+ assert(typ);
+ assert(typ->type()->getTypeID() == llvm::Type::StructTyID);
+
+ llvm::StructType *styp = llvm::cast<llvm::StructType>(typ->type());
+ llvm::Constant *nzrealcon = llvm::ConstantFP::getNegativeZero(styp->getElementType(0));
+ llvm::Constant *nzimagcon = llvm::ConstantFP::getNegativeZero(styp->getElementType(1));
+ std::vector<llvm::Constant*> structVals {nzrealcon, nzimagcon};
+ llvm::Constant *nzcmplxcon = llvm::ConstantStruct::get(styp, structVals);
+ Bexpression *bconst = nbuilder_.mkConst(typ, nzcmplxcon);
+
+ return makeGlobalExpression(bconst, nzcmplxcon, typ, Location());
+}
+
Bexpression *Llvm_backend::minusZeroExpr(BFloatType *typ)
{
assert(typ);
diff --git a/bridge/go-llvm.h b/bridge/go-llvm.h
index db1e941..880ae39 100644
--- a/bridge/go-llvm.h
+++ b/bridge/go-llvm.h
@@ -687,6 +687,9 @@
// hence no delayed value creation).
Bexpression *lateConvert(Btype *type, Bexpression *expr, Location);
+ // Manufacture a complex constant corresponding to -0.0-0.0i
+ Bexpression *minusZeroExpr(BComplexType *typ);
+
// Manufacture a floating point constant corresponding to -0.0
Bexpression *minusZeroExpr(BFloatType *typ);