diff options
author | arphaman <arphaman@gmail.com> | 2013-09-13 12:42:19 +0100 |
---|---|---|
committer | arphaman <arphaman@gmail.com> | 2013-09-13 12:42:19 +0100 |
commit | 43e78c02ca0fbe7219efb962b2fd8dd03dda318e (patch) | |
tree | 41176bac483fd7630e41da65155b8e899712170e | |
parent | 715ff12488de990af7f5ed3929110d0a610666da (diff) | |
download | flang-43e78c02ca0fbe7219efb962b2fd8dd03dda318e.tar.gz |
updated codegen for DATA stmt, added codegen for charater initialization
-rw-r--r-- | include/flang/AST/Stmt.h | 17 | ||||
-rw-r--r-- | lib/AST/ASTDumper.cpp | 4 | ||||
-rw-r--r-- | lib/AST/Stmt.cpp | 18 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 162 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 35 | ||||
-rw-r--r-- | lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 104 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 7 | ||||
-rw-r--r-- | lib/Sema/SemaDataStmt.cpp | 20 | ||||
-rw-r--r-- | test/CodeGen/data.f95 | 4 | ||||
-rw-r--r-- | test/CodeGenInAction/arrayOperations.f95 | 3 | ||||
-rw-r--r-- | test/CodeGenInAction/data.f95 | 21 |
13 files changed, 221 insertions, 182 deletions
diff --git a/include/flang/AST/Stmt.h b/include/flang/AST/Stmt.h index 175ac07245..fd415c54ef 100644 --- a/include/flang/AST/Stmt.h +++ b/include/flang/AST/Stmt.h @@ -606,26 +606,19 @@ class DataStmt : public Stmt { Stmt *Body; DataStmt(ASTContext &C, SourceLocation Loc, - ArrayRef<Expr*> Names, - ArrayRef<Expr*> Values, - Stmt *BodyStmt, - Expr *StmtLabel); + ArrayRef<Expr*> Objects, + ArrayRef<Expr*> Values, Expr *StmtLabel); public: static DataStmt *Create(ASTContext &C, SourceLocation Loc, - ArrayRef<Expr*> Names, - ArrayRef<Expr*> Values, - Stmt *Body, - Expr *StmtLabel); + ArrayRef<Expr*> Objects, + ArrayRef<Expr*> Values, Expr *StmtLabel); - ArrayRef<Expr*> getNames() const { + ArrayRef<Expr*> getObjects() const { return ArrayRef<Expr*>(NameList, NumNames); } ArrayRef<Expr*> getValues() const { return ArrayRef<Expr*>(ValueList, NumValues); } - const Stmt *getBody() const { - return Body; - } static bool classof(const DataStmt*) { return true; } static bool classof(const Stmt *S) { diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 078ca238f6..5131200018 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -461,12 +461,10 @@ void ASTDumper::VisitEquivalenceStmt(const EquivalenceStmt *S) { void ASTDumper::VisitDataStmt(const DataStmt *S) { OS << "data "; - dumpExprList(S->getNames()); + dumpExprList(S->getObjects()); OS << " / "; dumpExprList(S->getValues()); OS << " / \n"; - if(S->getBody()) - dumpSubStmt(S->getBody()); } void ASTDumper::VisitBlockStmt(const BlockStmt *S) { diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 1a57341091..e00ff31803 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -302,15 +302,14 @@ EquivalenceSet *EquivalenceSet::Create(ASTContext &C, ArrayRef<Object> Objects) //===----------------------------------------------------------------------===// DataStmt::DataStmt(ASTContext &C, SourceLocation Loc, - ArrayRef<Expr*> Names, + ArrayRef<Expr*> Objects, ArrayRef<Expr*> Values, - Stmt *BodyStmt, Expr *StmtLabel) - : Stmt(DataStmtClass, Loc, StmtLabel), Body(BodyStmt) { - NumNames = Names.size(); + : Stmt(DataStmtClass, Loc, StmtLabel) { + NumNames = Objects.size(); NameList = new (C) Expr* [NumNames]; - for(size_t I = 0; I < Names.size(); ++I) - NameList[I] = Names[I]; + for(size_t I = 0; I < Objects.size(); ++I) + NameList[I] = Objects[I]; NumValues = Values.size(); ValueList = new (C) Expr* [NumValues]; @@ -319,10 +318,9 @@ DataStmt::DataStmt(ASTContext &C, SourceLocation Loc, } DataStmt *DataStmt::Create(ASTContext &C, SourceLocation Loc, - ArrayRef<Expr*> Names, - ArrayRef<Expr*> Values, Stmt *Body, - Expr *StmtLabel) { - return new(C) DataStmt(C, Loc, Names, Values, Body, StmtLabel); + ArrayRef<Expr*> Objects, + ArrayRef<Expr*> Values, Expr *StmtLabel) { + return new(C) DataStmt(C, Loc, Objects, Values, StmtLabel); } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp new file mode 100644 index 0000000000..e00566b3ea --- /dev/null +++ b/lib/CodeGen/CGDecl.cpp @@ -0,0 +1,162 @@ +//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Decl nodes as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "flang/AST/Decl.h" +#include "flang/AST/DeclVisitor.h" +#include "flang/AST/Expr.h" +#include "flang/AST/EquivalenceSet.h" + +namespace flang { +namespace CodeGen { + +class FuncDeclEmitter : public ConstDeclVisitor<FuncDeclEmitter> { + CodeGenFunction &CGF; +public: + FuncDeclEmitter(CodeGenFunction &cgf) : CGF(cgf) {} + + void VisitVarDecl(const VarDecl *D) { + CGF.EmitVarDecl(D); + } +}; + +void CodeGenFunction::EmitFunctionDecls(const DeclContext *DC) { + FuncDeclEmitter DV(*this); + DV.Visit(DC); +} + +void CodeGenFunction::EmitVarDecl(const VarDecl *D) { + if(D->isParameter() || + D->isArgument() || + D->isFunctionResult()) return; + + if(D->hasEquivalenceSet()) { + auto Set = EmitEquivalenceSet(D->getEquivalenceSet()); + auto Ptr = EmitEquivalenceSetObject(Set, D); + LocalVariables.insert(std::make_pair(D, Ptr)); + return; + } + + llvm::Value *Ptr; + auto Type = D->getType(); + auto Quals = Type.getExtQualsPtrOrNull(); + if(Quals && Quals->getQualifiers().hasAttributeSpec(Qualifiers::AS_save) && + !IsMainProgram) { + Ptr = CGM.EmitGlobalVariable(CurFn->getName(), D); + HasSavedVariables = true; + } else { + if(Type->isArrayType()) + Ptr = CreateArrayAlloca(Type, D->getName()); + else Ptr = Builder.CreateAlloca(ConvertTypeForMem(Type), + nullptr, D->getName()); + } + LocalVariables.insert(std::make_pair(D, Ptr)); +} + +class VarInitEmitter : public ConstDeclVisitor<VarInitEmitter> { + CodeGenFunction &CGF; + bool VisitSaveQualified; +public: + VarInitEmitter(CodeGenFunction &cgf, bool VisitSave = false) + : CGF(cgf), VisitSaveQualified(VisitSave) {} + + void VisitVarDecl(const VarDecl *D) { + if(D->isParameter() || D->isArgument() || + D->isFunctionResult()) + return; + auto Ext = D->getType().getExtQualsPtrOrNull(); + bool HasSave = Ext && Ext->getQualifiers().hasAttributeSpec(Qualifiers::AS_save); + if(HasSave != VisitSaveQualified) + return; + if(D->hasInit()) + CGF.EmitVarInitializer(D); + } +}; + +void CodeGenFunction::EmitVarInitializers(const DeclContext *DC) { + VarInitEmitter DV(*this, false); + DV.Visit(DC); +} + +void CodeGenFunction::EmitSavedVarInitializers(const DeclContext *DC) { + VarInitEmitter DV(*this, true); + DV.Visit(DC); +} + +void CodeGenFunction::EmitVarInitializer(const VarDecl *D) { + assert(D->hasInit()); + + auto T = D->getType(); + if(T->isArrayType()) { + auto Dest = Builder.CreateConstInBoundsGEP2_32(GetVarPtr(D), 0, 0); + auto Init = cast<ArrayConstructorExpr>(D->getInit())->getItems(); + for(size_t I = 0; I < Init.size(); ++I) { + auto Val = EmitRValue(Init[I]); + EmitStoreCharSameLength(Val, Builder.CreateConstInBoundsGEP1_64(Dest, I), T.getSelfOrArrayElementType()); + } + return; + } + auto Val = EmitRValue(D->getInit()); + EmitStoreCharSameLength(Val, GetVarPtr(D), D->getType()); +} + +// FIXME: support substrings. +std::pair<int64_t, int64_t> CodeGenFunction::GetObjectBounds(const VarDecl *Var, const Expr *E) { + auto Size = CGM.getDataLayout().getTypeStoreSize(ConvertTypeForMem(Var->getType())); + uint64_t Offset = 0; + if(auto Arr = dyn_cast<ArrayElementExpr>(E)) { + Arr->EvaluateOffset(getContext(), Offset); + Offset = Offset * CGM.getDataLayout().getTypeStoreSize(ConvertTypeForMem(E->getType())); + } else + Offset = 0; + + return std::make_pair(-int64_t(Offset), -int64_t(Offset) + int64_t(Size)); +} + +CodeGenFunction::EquivSet CodeGenFunction::EmitEquivalenceSet(const EquivalenceSet *S) { + auto Result = EquivSets.find(S); + if(Result != EquivSets.end()) + return Result->second; + + // Find the bounds of the set + int64_t LowestBound = 0; + int64_t HighestBound = 0; + for(auto I : S->getObjects()) { + auto Bounds = GetObjectBounds(I.Var, I.E); + LowestBound = std::min(Bounds.first, LowestBound); + HighestBound = std::max(Bounds.second, HighestBound); + LocalVariablesInEquivSets.insert(std::make_pair(I.Var, Bounds.first)); + } + EquivSet Set; + // FIXME: more accurate alignment? + Set.Ptr= Builder.Insert(new llvm::AllocaInst(CGM.Int8Ty, + llvm::ConstantInt::get(CGM.SizeTy, HighestBound - LowestBound), + CGM.getDataLayout().getTypeStoreSize(CGM.DoubleTy)), + "equivalence-set"); + Set.LowestBound = LowestBound; + EquivSets.insert(std::make_pair(S, Set)); + return Set; +} + +llvm::Value *CodeGenFunction::EmitEquivalenceSetObject(EquivSet Set, const VarDecl *Var) { + // Compute the pointer to the object. + auto ObjLowBound = LocalVariablesInEquivSets.find(Var)->second; + auto Ptr = Builder.CreateConstInBoundsGEP1_64(Set.Ptr, + uint64_t(ObjLowBound - Set.LowestBound)); + auto T = Var->getType(); + return Builder.CreatePointerCast(Ptr, llvm::PointerType::get(ConvertTypeForMem(T), 0)); +} + +} +} diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 6e4b6f2468..a16e63e17f 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -69,6 +69,13 @@ void CodeGenFunction::EmitStore(RValueTy Val, LValueTy Dest, QualType T) { } } +void CodeGenFunction::EmitStoreCharSameLength(RValueTy Val, LValueTy Dest, QualType T) { + if(!Val.isCharacter()) + return EmitStore(Val, Dest, T); + auto CharVal = Val.asCharacter(); + Builder.CreateMemCpy(Dest.getPointer(), CharVal.Ptr, CharVal.Len, 1, Dest.isVolatileQualifier()); +} + RValueTy CodeGenFunction::EmitBinaryExpr(BinaryExpr::Operator Op, RValueTy LHS, RValueTy RHS) { if(LHS.isScalar()) return EmitScalarBinaryExpr(Op, LHS.asScalar(), RHS.asScalar()); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 0989777ce2..9d0b3e4db8 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -24,41 +24,6 @@ namespace flang { namespace CodeGen { -class DataStmtEmmitter : public ConstStmtVisitor<DataStmtEmmitter> { - bool InData, Saved; - CodeGenFunction &CGF; -public: - DataStmtEmmitter(CodeGenFunction &cgf, bool SavedOnly) - : CGF(cgf), InData(false), Saved(SavedOnly) {} - - void VisitCompoundStmt(const CompoundStmt *S) { - for(auto I : S->getBody()) - Visit(I); - } - void VisitDataStmt(const DataStmt *S) { - assert(!InData); - InData = true; - Visit(S->getBody()); - InData = false; - } - void VisitBlockStmt(const BlockStmt *S) { - for(auto I : S->getStatements()) - Visit(I); - } - void VisitAssignmentStmt(const AssignmentStmt *S) { - if(!InData || CGF.IsAssignmentStmtAssignmentToSaved(S) != Saved) - return; - CGF.EmitAssignmentStmt(S); - } -}; - -void CodeGenFunction::EmitDataStmts(const Stmt *S, bool Saved) { - DataStmtEmmitter SV(*this, Saved); - if(S->getStmtLabel()) - EmitStmtLabel(S); - SV.Visit(S); -} - class StmtEmmitter : public ConstStmtVisitor<StmtEmmitter> { CodeGenFunction &CGF; public: diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index 4a0c6b4457..ed8e5d045a 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -6,6 +6,7 @@ add_flang_library(flangCodeGen CodeGenAction.cpp BackendUtil.cpp CGABI.cpp + CGDecl.cpp CGStmt.cpp CGExpr.cpp CGExprScalar.cpp diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index b8b9c10054..961dd1e540 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -16,10 +16,8 @@ #include "CGSystemRuntime.h" #include "flang/AST/ASTContext.h" #include "flang/AST/Decl.h" -#include "flang/AST/DeclVisitor.h" #include "flang/AST/Stmt.h" #include "flang/AST/Expr.h" -#include "flang/AST/EquivalenceSet.h" #include "flang/Frontend/CodeGenOptions.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" @@ -42,21 +40,6 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, llvm::Function *Fn) CodeGenFunction::~CodeGenFunction() { } -void CodeGenFunction::EmitFunctionDecls(const DeclContext *DC) { - class Visitor : public ConstDeclVisitor<Visitor> { - public: - CodeGenFunction *CG; - - Visitor(CodeGenFunction *P) : CG(P) {} - - void VisitVarDecl(const VarDecl *D) { - CG->EmitVarDecl(D); - } - }; - Visitor DV(this); - DV.Visit(DC); -} - void CodeGenFunction::EmitMainProgramBody(const DeclContext *DC, const Stmt *S) { EmitBlock(createBasicBlock("program_entry")); CGM.getSystemRuntime().EmitInit(*this); @@ -143,14 +126,14 @@ void CodeGenFunction::EmitFunctionBody(const DeclContext *DC, const Stmt *S) { AllocaInsertPt = Builder.CreateBr(BodyBB); EmitBlock(BodyBB); if(HasSavedVariables) - EmitFirstInvocationBlock(S); - if(S) { - EmitDataStmts(S); + EmitFirstInvocationBlock(DC, S); + EmitVarInitializers(DC); + if(S) EmitStmt(S); - } } -void CodeGenFunction::EmitFirstInvocationBlock(const Stmt *S) { +void CodeGenFunction::EmitFirstInvocationBlock(const DeclContext *DC, + const Stmt *S) { auto GlobalFirstInvocationFlag = CGM.EmitGlobalVariable(CurFn->getName(), "FIRST_INVOCATION", CGM.Int1Ty, Builder.getTrue()); auto FirstInvocationBB = createBasicBlock("first-invocation"); @@ -158,7 +141,7 @@ void CodeGenFunction::EmitFirstInvocationBlock(const Stmt *S) { Builder.CreateCondBr(Builder.CreateLoad(GlobalFirstInvocationFlag), FirstInvocationBB, EndBB); EmitBlock(FirstInvocationBB); - if(S) EmitDataStmts(S, true); + EmitSavedVarInitializers(DC); Builder.CreateStore(Builder.getFalse(), GlobalFirstInvocationFlag); EmitBlock(EndBB); } @@ -194,81 +177,6 @@ void CodeGenFunction::EmitFunctionEpilogue(const FunctionDecl *Func, EmitAssignedGotoDispatcher(); } -void CodeGenFunction::EmitVarDecl(const VarDecl *D) { - if(D->isParameter() || - D->isArgument() || - D->isFunctionResult()) return; - - if(D->hasEquivalenceSet()) { - auto Set = EmitEquivalenceSet(D->getEquivalenceSet()); - auto Ptr = EmitEquivalenceSetObject(Set, D); - LocalVariables.insert(std::make_pair(D, Ptr)); - return; - } - - llvm::Value *Ptr; - auto Type = D->getType(); - auto Quals = Type.getExtQualsPtrOrNull(); - if(Quals && Quals->getQualifiers().hasAttributeSpec(Qualifiers::AS_save) && - !IsMainProgram) { - Ptr = CGM.EmitGlobalVariable(CurFn->getName(), D); - HasSavedVariables = true; - } else { - if(Type->isArrayType()) - Ptr = CreateArrayAlloca(Type, D->getName()); - else Ptr = Builder.CreateAlloca(ConvertTypeForMem(Type), - nullptr, D->getName()); - } - LocalVariables.insert(std::make_pair(D, Ptr)); -} - -// FIXME: support substrings. -std::pair<int64_t, int64_t> CodeGenFunction::GetObjectBounds(const VarDecl *Var, const Expr *E) { - auto Size = CGM.getDataLayout().getTypeStoreSize(ConvertTypeForMem(Var->getType())); - uint64_t Offset = 0; - if(auto Arr = dyn_cast<ArrayElementExpr>(E)) { - Arr->EvaluateOffset(getContext(), Offset); - Offset = Offset * CGM.getDataLayout().getTypeStoreSize(ConvertTypeForMem(E->getType())); - } else - Offset = 0; - - return std::make_pair(-int64_t(Offset), -int64_t(Offset) + int64_t(Size)); -} - -CodeGenFunction::EquivSet CodeGenFunction::EmitEquivalenceSet(const EquivalenceSet *S) { - auto Result = EquivSets.find(S); - if(Result != EquivSets.end()) - return Result->second; - - // Find the bounds of the set - int64_t LowestBound = 0; - int64_t HighestBound = 0; - for(auto I : S->getObjects()) { - auto Bounds = GetObjectBounds(I.Var, I.E); - LowestBound = std::min(Bounds.first, LowestBound); - HighestBound = std::max(Bounds.second, HighestBound); - LocalVariablesInEquivSets.insert(std::make_pair(I.Var, Bounds.first)); - } - EquivSet Set; - // FIXME: more accurate alignment? - Set.Ptr= Builder.Insert(new llvm::AllocaInst(CGM.Int8Ty, - llvm::ConstantInt::get(CGM.SizeTy, HighestBound - LowestBound), - CGM.getDataLayout().getTypeStoreSize(CGM.DoubleTy)), - "equivalence-set"); - Set.LowestBound = LowestBound; - EquivSets.insert(std::make_pair(S, Set)); - return Set; -} - -llvm::Value *CodeGenFunction::EmitEquivalenceSetObject(EquivSet Set, const VarDecl *Var) { - // Compute the pointer to the object. - auto ObjLowBound = LocalVariablesInEquivSets.find(Var)->second; - auto Ptr = Builder.CreateConstInBoundsGEP1_64(Set.Ptr, - uint64_t(ObjLowBound - Set.LowestBound)); - auto T = Var->getType(); - return Builder.CreatePointerCast(Ptr, llvm::PointerType::get(ConvertTypeForMem(T), 0)); -} - llvm::Value *CodeGenFunction::GetVarPtr(const VarDecl *D) { if(D->isFunctionResult()) return ReturnValuePtr; diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 3177444153..0c795dff3a 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -203,8 +203,10 @@ public: void EmitCleanup(); void EmitVarDecl(const VarDecl *D); - void EmitDataStmts(const Stmt *S, bool Saved = false); - void EmitFirstInvocationBlock(const Stmt *S); + void EmitVarInitializers(const DeclContext *DC); + void EmitSavedVarInitializers(const DeclContext *DC); + void EmitVarInitializer(const VarDecl *D); + void EmitFirstInvocationBlock(const DeclContext *DC, const Stmt *S); std::pair<int64_t, int64_t> GetObjectBounds(const VarDecl *Var, const Expr *E); EquivSet EmitEquivalenceSet(const EquivalenceSet *S); @@ -268,6 +270,7 @@ public: /// Generic value operations for scalar/complex/character values. RValueTy EmitLoad (llvm::Value *Ptr, QualType T, bool IsVolatile = false); void EmitStore(RValueTy Val, LValueTy Dest, QualType T); + void EmitStoreCharSameLength(RValueTy Val, LValueTy Dest, QualType T); RValueTy EmitBinaryExpr(BinaryExpr::Operator Op, RValueTy LHS, RValueTy RHS); RValueTy EmitUnaryExpr(UnaryExpr::Operator Op, RValueTy Val); RValueTy EmitImplicitConversion(RValueTy Val, QualType T); diff --git a/lib/Sema/SemaDataStmt.cpp b/lib/Sema/SemaDataStmt.cpp index b3c1e52c36..88d4693c26 100644 --- a/lib/Sema/SemaDataStmt.cpp +++ b/lib/Sema/SemaDataStmt.cpp @@ -93,7 +93,6 @@ class DataStmtEngine : public ExprVisitor<DataStmtEngine> { SourceLocation DataStmtLoc; ExprEvalScope ImpliedDoEvaluator; - SmallVector<Stmt*, 16> ResultingAST; bool Done; @@ -124,18 +123,9 @@ public: void VisitMemberExpr(MemberExpr *E); void VisitImpliedDoExpr(ImpliedDoExpr *E); - void Emit(Stmt *S); - ArrayRef<Stmt*> getEmittedStmtList() const { - return ResultingAST; - } - bool CheckVar(VarExpr *E); }; -void DataStmtEngine::Emit(Stmt *S) { - ResultingAST.push_back(S); -} - bool DataStmtEngine::HasValues(const Expr *Where) { if(Values.isEmpty()) { // more items than values. @@ -401,16 +391,8 @@ StmtResult Sema::ActOnDATA(ASTContext &C, SourceLocation Loc, << SourceRange(FirstVal->getLocStart(), LastVal->getLocEnd()); } - Stmt *ResultStmt; - auto ResultStmts = LHSVisitor.getEmittedStmtList(); - if(ResultStmts.size() > 1) - ResultStmt = BlockStmt::Create(Context, Loc, ResultStmts); - else if(ResultStmts.size() == 1) - ResultStmt = ResultStmts[0]; - else ResultStmt = nullptr; - auto Result = DataStmt::Create(C, Loc, Objects, Values, - ResultStmt, StmtLabel); + StmtLabel); if(StmtLabel) DeclareStatementLabel(StmtLabel, Result); return Result; } diff --git a/test/CodeGen/data.f95 b/test/CodeGen/data.f95 index 1239d3c39d..890aa09379 100644 --- a/test/CodeGen/data.f95 +++ b/test/CodeGen/data.f95 @@ -4,14 +4,18 @@ PROGRAM datatest REAL X INTEGER I_ARR(10) LOGICAL L_ARR(4) + character(len=5) str1 DATA (I_ARR(I), I = 1,10) / 2*0, 5*2, 3*-1 / DATA L_ARR / .false., .true., .false., .true. / + data str1 / 'Hello' / + DATA I / 1 / J, X / 2*0 / ! CHECK: store i32 1 CONTINUE ! CHECK-NEXT: store i32 0 CONTINUE ! CHECK-NEXT: store float 0 + continue ! CHECK: call void @llvm.memcpy.p0i8.p0i8 END PROGRAM diff --git a/test/CodeGenInAction/arrayOperations.f95 b/test/CodeGenInAction/arrayOperations.f95 index 89ed41772e..a3069cfdff 100644 --- a/test/CodeGenInAction/arrayOperations.f95 +++ b/test/CodeGenInAction/arrayOperations.f95 @@ -9,7 +9,6 @@ program arrayops ! assignment using data statement data i_arr / 1, 2*0, -69 / data i_mat / 1, 0, 0, 0, 1, 0, 0, 0, 1 / - ! FIXME: data char_arr / 'Hello', 'World' / print *, i_arr(1), ', ', i_arr(2), ', ', i_arr(3), ', ', i_arr(4) continue ! CHECK: 1, 0, 0, -69 @@ -19,8 +18,6 @@ program arrayops i_mat(1,3), ', ', i_mat(2,3), ', ', i_mat(3,3) continue ! CHECK-NEXT: 1, 0, 0, 0, 1, 0, 0, 0, 1 - ! FIXME: print *, char_arr(1), char_arr(2) ! CECK-NEXT: HelloWorld - i_mat2 = 1 i_mat = i_mat + i_mat2 * 2 diff --git a/test/CodeGenInAction/data.f95 b/test/CodeGenInAction/data.f95 index 49af67b680..67e59ff72b 100644 --- a/test/CodeGenInAction/data.f95 +++ b/test/CodeGenInAction/data.f95 @@ -11,6 +11,18 @@ program datatest / 3*42, 3*11, 3*-88 / + character(len=5) str1, str2, str3 + character(len=5) strArr(2), strArr2(3) + + data str1 / 'Hello' / str2(:) / 'World' / + data str3(2:4) / 'Flang' / + + data strArr / 'Hello', 'World' / + data strArr2(1) / 'Hello' / + data strArr2(2)(2:4) / '+' / + data (strArr2(i), i = 3,3) / 'funke' / + + print *, 'START' ! CHECK: START print *, i ! CHECK-NEXT: 1 print *, j ! CHECK-NEXT: 0 @@ -24,4 +36,13 @@ program datatest i_mat(1,3), ', ', i_mat(2,3), ', ', i_mat(3,3) continue ! CHECK-NEXT: 42, 42, 42, 11, 11, 11, -88, -88, -88 + print *, str1 ! CHECK-NEXT: Hello + print *, str2 ! CHECK-NEXT: World + print *, str3 ! CHECK-NEXT: Fla + print *, strArr(1) ! CHECK-NEXT: Hello + print *, strArr(2) ! CHECK-NEXT: World + print *, strArr2(1) ! CHECK-NEXT: Hello + print *, strArr2(2) ! CHECK-NEXT: + + print *, strArr2(3) ! CHECK-NEXT: funke + end program |