diff options
author | arphaman <arphaman@gmail.com> | 2013-09-20 17:11:37 +0100 |
---|---|---|
committer | arphaman <arphaman@gmail.com> | 2013-09-20 17:11:37 +0100 |
commit | 94075050b2849974ba0f6327cfbef72ead76bd75 (patch) | |
tree | 17c1241f7b6f2843b0974dba365d83d36ab9ee85 | |
parent | 6ba4866e1096d45a83a5d92ecac7e902b897f3e9 (diff) | |
download | flang-94075050b2849974ba0f6327cfbef72ead76bd75.tar.gz |
added codegen for COMMON
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 29 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 3 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 24 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 4 | ||||
-rw-r--r-- | test/CodeGen/common.f95 | 33 | ||||
-rw-r--r-- | test/CodeGenInAction/common.f95 | 47 |
6 files changed, 137 insertions, 3 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 1a1976c4a3..5a060f6569 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -46,9 +46,9 @@ void CodeGenFunction::EmitVarDecl(const VarDecl *D) { auto Set = EmitEquivalenceSet(E); auto Ptr = EmitEquivalenceSetObject(Set, D); LocalVariables.insert(std::make_pair(D, Ptr)); - } else if(auto C = dyn_cast<CommonBlockSet>(D->getStorageSet())) { - // FIXME - } else + } else if(auto CB = dyn_cast<CommonBlockSet>(D->getStorageSet())) + EmitCommonBlock(CB); + else llvm_unreachable("invalid storage set"); return; } @@ -160,5 +160,28 @@ llvm::Value *CodeGenFunction::EmitEquivalenceSetObject(EquivSet Set, const VarDe return Builder.CreatePointerCast(Ptr, llvm::PointerType::get(ConvertTypeForMem(T), 0)); } +void CodeGenFunction::EmitCommonBlock(const CommonBlockSet *S) { + auto Result = CommonBlocks.find(S); + if(Result != CommonBlocks.end()) + return; + + SmallVector<llvm::Type*, 32> Items; + for(auto Obj : S->getObjects()) { + if(Obj.Var) + Items.push_back(ConvertTypeForMem(Obj.Var->getType())); + } + auto CBType = llvm::StructType::get(CGM.getLLVMContext(), Items); + auto Ptr = Builder.CreateBitCast(CGM.EmitCommonBlock(S->getDecl(), CBType), + llvm::PointerType::get(CBType, 0)); + unsigned Idx = 0; + for(auto Obj : S->getObjects()) { + if(Obj.Var) { + LocalVariables.insert(std::make_pair(Obj.Var, + Builder.CreateStructGEP(Ptr, Idx))); + } + ++Idx; + } +} + } } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 141e8f97e9..867a314aa9 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -97,6 +97,7 @@ class CodeGenFunction { }; llvm::SmallDenseMap<const EquivalenceSet*, EquivSet, 4> EquivSets; llvm::SmallDenseMap<const VarDecl*, int64_t, 16> LocalVariablesInEquivSets; + llvm::SmallDenseMap<const CommonBlockSet*, llvm::Value*, 4> CommonBlocks; llvm::Value *ReturnValuePtr; llvm::Instruction *AllocaInsertPt; @@ -213,6 +214,8 @@ public: EquivSet EmitEquivalenceSet(const EquivalenceSet *S); llvm::Value *EmitEquivalenceSetObject(EquivSet Set, const VarDecl *Var); + void EmitCommonBlock(const CommonBlockSet *S); + llvm::Value *CreateArrayAlloca(QualType T, const llvm::Twine &Name = "", diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index a498282d01..74536bbd05 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -196,5 +196,29 @@ llvm::Value *CodeGenModule::EmitConstantArray(llvm::Constant *Array) { true, llvm::GlobalValue::PrivateLinkage, Array); } +llvm::Value *CodeGenModule::EmitCommonBlock(const CommonBlockDecl *CB, + llvm::Type *Type, + llvm::Constant *Initializer) { + llvm::SmallString<32> Name; + StringRef NameRef; + if(CB->getIdentifier()) { + Name.append(CB->getName()); + Name.push_back('_'); + NameRef = Name; + } else + NameRef = "__BLNK__"; // FIXME? + + auto Var = TheModule.getGlobalVariable(NameRef); + if(Var) + return Var; + if(!Initializer) + Initializer = llvm::Constant::getNullValue(Type); + auto CBVar = new llvm::GlobalVariable(TheModule, Type, + false, llvm::GlobalValue::CommonLinkage, + Initializer, NameRef); + CBVar->setAlignment(16); // FIXME: proper target dependent alignment value + return CBVar; +} + } } // end namespace flang diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 8aebab83c0..dfa1a31080 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -193,6 +193,10 @@ public: llvm::Value *EmitConstantArray(llvm::Constant *Array); + llvm::Value *EmitCommonBlock(const CommonBlockDecl *CB, + llvm::Type *Type, + llvm::Constant *Initializer = nullptr); + llvm::Value *GetCFunction(StringRef Name, ArrayRef<llvm::Type*> ArgTypes, llvm::Type *ReturnType = nullptr); diff --git a/test/CodeGen/common.f95 b/test/CodeGen/common.f95 new file mode 100644 index 0000000000..8b1a404e88 --- /dev/null +++ b/test/CodeGen/common.f95 @@ -0,0 +1,33 @@ +! RUN: %flang -emit-llvm -o - %s | %file_check %s + +program com ! CHECK: @__BLNK__ = common global { i32, i32, float, { float, float } } zeroinitializer, align 16 + integer i,j ! CHECK: @dir_ = common global { [20 x i8], i32 } zeroinitializer, align 16 + real r + complex c + common i,j,r,c + + integer str_len + character(20) str + common /dir/ str + common /dir/ str_len + save /dir/ + + i = 0 ! CHECK: store i32 0, i32* getelementptr inbounds ({ i32, i32, float, { float, float } }* @__BLNK__, i32 0, i32 0) + r = 1.0 + str_len = j ! CHECK: load i32* getelementptr inbounds ({ i32, i32, float, { float, float } }* @__BLNK__, i32 0, i32 1) + continue ! CHECK-NEXT: i32* getelementptr inbounds ({ [20 x i8], i32 }* @dir_, i32 0, i32 1) + + str = 'Hello' + +end + +subroutine sub1 + integer j + real r + common j, r + character(10) str + common /dir/ str + j = 1 ! CHECK: store i32 1, i32* getelementptr inbounds ({ i32, float }* bitcast ({ i32, i32, float, { float, float } }* @__BLNK__ to { i32, float }*), i32 0, i32 0) + r = 1.0 + str = 'Foo' +end diff --git a/test/CodeGenInAction/common.f95 b/test/CodeGenInAction/common.f95 new file mode 100644 index 0000000000..5e34cf6ffd --- /dev/null +++ b/test/CodeGenInAction/common.f95 @@ -0,0 +1,47 @@ +! RUN: %flang -interpret %s | %file_check %s + +subroutine sub1 + integer i, i_mat(3,3) + common i, i_mat + + character(10) str + common /data/ str + + print *,i + 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) + print *,str + + i = 42 + str = 'WorldHello' + i_mat(1,:) = -1 +end + +program com + integer i, i_mat(3,3) + common i, i_mat + + character(10) str + common /data/ str + + i = 2 + i_mat = 1 + str = 'HelloWorld' + + print *, str ! CHECK: HelloWorld + + call sub1 ! CHECK-NEXT: 2 + continue ! CHECK-NEXT: 1, 1, 1, 1, 1, 1, 1, 1, 1 + continue ! CHECK-NEXT: HelloWorld + + print *,i ! CHECK-NEXT: 42 + 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: -1, 1, 1, -1, 1, 1, -1, 1, 1 + print *,str ! CHECK-NEXT: WorldHello + +end + + |