summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarphaman <arphaman@gmail.com>2013-09-20 17:11:37 +0100
committerarphaman <arphaman@gmail.com>2013-09-20 17:11:37 +0100
commit94075050b2849974ba0f6327cfbef72ead76bd75 (patch)
tree17c1241f7b6f2843b0974dba365d83d36ab9ee85
parent6ba4866e1096d45a83a5d92ecac7e902b897f3e9 (diff)
downloadflang-94075050b2849974ba0f6327cfbef72ead76bd75.tar.gz
added codegen for COMMON
-rw-r--r--lib/CodeGen/CGDecl.cpp29
-rw-r--r--lib/CodeGen/CodeGenFunction.h3
-rw-r--r--lib/CodeGen/CodeGenModule.cpp24
-rw-r--r--lib/CodeGen/CodeGenModule.h4
-rw-r--r--test/CodeGen/common.f9533
-rw-r--r--test/CodeGenInAction/common.f9547
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
+
+