summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarphaman <arphaman@gmail.com>2013-09-18 15:04:06 +0100
committerarphaman <arphaman@gmail.com>2013-09-18 15:04:06 +0100
commit30af97c28d5bed8a4e8ba2ef90f6cde1390606ce (patch)
tree5f42d944f75e30538d67e536ee5918e501bb1053
parent6074e7c2442679d7b6b0ba5d7ef288566be90f9e (diff)
downloadflang-30af97c28d5bed8a4e8ba2ef90f6cde1390606ce.tar.gz
added codegen for int, real and cmplx array operation intrinsics
-rw-r--r--lib/CodeGen/CGArray.cpp38
-rw-r--r--lib/CodeGen/CGArray.h1
-rw-r--r--test/CodeGen/arrayOperations.f955
-rw-r--r--test/CodeGenInAction/arrayOperations.f957
4 files changed, 51 insertions, 0 deletions
diff --git a/lib/CodeGen/CGArray.cpp b/lib/CodeGen/CGArray.cpp
index cbe4fdb6f3..6871ec9bc6 100644
--- a/lib/CodeGen/CGArray.cpp
+++ b/lib/CodeGen/CGArray.cpp
@@ -396,6 +396,7 @@ public:
void VisitBinaryExpr(const BinaryExpr *E);
void VisitArrayConstructorExpr(const ArrayConstructorExpr *E);
void VisitArraySectionExpr(const ArraySectionExpr *E);
+ void VisitIntrinsicCallExpr(const IntrinsicCallExpr *E);
const Expr *getLastEmmittedArray() const {
return LastArrayEmmitted;
@@ -437,6 +438,11 @@ void ScalarEmitterAndSectionGatherer::VisitArraySectionExpr(const ArraySectionEx
LastArrayEmmitted = E;
}
+void ScalarEmitterAndSectionGatherer::VisitIntrinsicCallExpr(const IntrinsicCallExpr *E) {
+ for(auto I : E->getArguments())
+ Emit(I);
+}
+
void ArrayOperation::EmitAllScalarValuesAndArraySections(CodeGenFunction &CGF, const Expr *E) {
ScalarEmitterAndSectionGatherer EV(CGF, *this);
EV.Emit(E);
@@ -561,6 +567,38 @@ RValueTy ArrayOperationEmitter::VisitArraySectionExpr(const ArraySectionExpr *E)
return CGF.EmitLoad(Looper.EmitElementPointer(Operation.getArrayValue(E)), ElementType(E));
}
+RValueTy ArrayOperationEmitter::VisitIntrinsicCallExpr(const IntrinsicCallExpr *E) {
+ using namespace intrinsic;
+ auto Func = getGenericFunctionKind(E->getIntrinsicFunction());
+ auto Group = getFunctionGroup(Func);
+ auto Args = E->getArguments();
+
+ switch(Group) {
+ case GROUP_CONVERSION: {
+ auto FirstVal = Emit(Args[0]);
+
+ if(Func == INT || Func == REAL)
+ return CGF.EmitImplicitConversion(FirstVal, E->getType());
+ else if(Func == CMPLX) {
+ if(FirstVal.isComplex())
+ return CGF.EmitComplexToComplexConversion(FirstVal.asComplex(),
+ E->getType());
+ if(Args.size() >= 2) {
+ auto ElementType = CGF.getContext().getComplexTypeElementType(E->getType());
+ return ComplexValueTy(CGF.EmitScalarToScalarConversion(FirstVal.asScalar(), ElementType),
+ CGF.EmitScalarToScalarConversion(Emit(Args[1]).asScalar(), ElementType));
+ }
+ else return CGF.EmitScalarToComplexConversion(FirstVal.asScalar(),
+ E->getType());
+ }
+ break;
+ }
+ default:
+ llvm_unreachable("invalid intrinsic group");
+ }
+ return RValueTy();
+}
+
LValueTy ArrayOperationEmitter::EmitLValue(const Expr *E) {
return Looper.EmitElementPointer(Operation.getArrayValue(E));
}
diff --git a/lib/CodeGen/CGArray.h b/lib/CodeGen/CGArray.h
index faefc41fe9..50e2c2e3f4 100644
--- a/lib/CodeGen/CGArray.h
+++ b/lib/CodeGen/CGArray.h
@@ -193,6 +193,7 @@ public:
RValueTy VisitBinaryExpr(const BinaryExpr *E);
RValueTy VisitArrayConstructorExpr(const ArrayConstructorExpr *E);
RValueTy VisitArraySectionExpr(const ArraySectionExpr *E);
+ RValueTy VisitIntrinsicCallExpr(const IntrinsicCallExpr *E);
static QualType ElementType(const Expr *E) {
return cast<ArrayType>(E->getType().getTypePtr())->getElementType();
diff --git a/test/CodeGen/arrayOperations.f95 b/test/CodeGen/arrayOperations.f95
index 7f0fe77cc9..c44ce73c0d 100644
--- a/test/CodeGen/arrayOperations.f95
+++ b/test/CodeGen/arrayOperations.f95
@@ -25,4 +25,9 @@ PROGRAM test
l_mat = i_mat <= i_mat2
+ i_mat = int(r_mat)
+ r_mat = real(i_mat)
+ c_mat = cmplx(c_mat2)
+ c_mat = cmplx(i_mat,r_mat)
+
END
diff --git a/test/CodeGenInAction/arrayOperations.f95 b/test/CodeGenInAction/arrayOperations.f95
index a3069cfdff..439b90ed6d 100644
--- a/test/CodeGenInAction/arrayOperations.f95
+++ b/test/CodeGenInAction/arrayOperations.f95
@@ -47,4 +47,11 @@ program arrayops
i_mat(1,3), ', ', i_mat(2,3), ', ', i_mat(3,3)
continue ! CHECK-NEXT: 2, 2, 2, 2, 2, 2, 2, 2, 1
+ r_mat = 5.5
+ i_mat = int(r_mat)
+ print *, i_mat(1,1), ', ', i_mat(2,1), ', ', i_mat(3,1), ', ', &
+ i_mat(1,2), ', ', i_mat(2,2), ', ', i_mat(3,2), ', ', &
+ i_mat(1,3), ', ', i_mat(2,3), ', ', i_mat(3,3)
+ continue ! CHECK-NEXT: 5, 5, 5, 5, 5, 5, 5, 5, 5
+
end