Skip to content

Commit

Permalink
Emit heap allocations
Browse files Browse the repository at this point in the history
Produce a call to malloc with the right size, store ptr to allocated memory in
the variable.

Bitcast malloc's return value to the right pointer size, store to the target
symbol.

Add all of that to the test.

For llvm-fortran#22
  • Loading branch information
ppenzin committed Mar 21, 2019
1 parent c34839b commit f963347
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 9 deletions.
28 changes: 25 additions & 3 deletions lib/CodeGen/CGArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "CGArray.h"
#include "CGSystemRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "fort/AST/ASTContext.h"
Expand Down Expand Up @@ -41,9 +42,9 @@ llvm::ArrayType *CodeGenTypes::ConvertArrayTypeForMem(const ArrayType *T) {
return nullptr;
}

llvm::Value *CodeGenFunction::CreateArrayAlloca(QualType T,
const llvm::Twine &Name,
bool IsTemp) {
llvm::Value *CodeGenFunction::CreateArrayTypeAlloca(QualType T,
const llvm::Twine &Name,
bool IsTemp) {
auto ATy = cast<ArrayType>(T.getTypePtr());
auto ElementType = ATy->getElementType();
uint64_t ArraySize;
Expand Down Expand Up @@ -80,6 +81,22 @@ CodeGenFunction::CreateTempHeapArrayAlloca(QualType T,
return CreateTempHeapArrayAlloca(T, EmitArraySize(Value));
}

llvm::Value *CodeGenFunction::CreateHeapArrayAlloca(AllocExpr *Alloc) {
auto Shape = Alloc->getShape();
assert(Shape && "Expecting array allocation expression");
SmallVector<ArrayDimensionValueTy, 8> Dims;
GetArrayDimensionsInfo(Shape, Dims);
auto ElType = getTypes().ConvertTypeForMem(Shape->getElementType());
llvm::Value *Sz = llvm::ConstantInt::get(
CGM.SizeTy, CGM.getDataLayout().getTypeStoreSize(ElType));
for (auto D : Dims) {
Sz = Builder.CreateMul(Sz, EmitDimSize(D));
}
auto Call = CGM.getSystemRuntime().EmitMalloc(*this, Sz);
auto RHS = Builder.CreateBitCast(Call, llvm::PointerType::get(ElType, 0));
return RHS;
}

ArrayDimensionValueTy CodeGenFunction::GetVectorDimensionInfo(QualType T) {
auto ATy = cast<ArrayType>(T.getTypePtr());
auto Dimension = ATy->getDimensions().front();
Expand All @@ -93,6 +110,11 @@ ArrayDimensionValueTy CodeGenFunction::GetVectorDimensionInfo(QualType T) {
void CodeGenFunction::GetArrayDimensionsInfo(
QualType T, SmallVectorImpl<ArrayDimensionValueTy> &Dims) {
auto ATy = cast<ArrayType>(T.getTypePtr());
GetArrayDimensionsInfo(ATy, Dims);
}

void CodeGenFunction::GetArrayDimensionsInfo(
const ArrayType *ATy, SmallVectorImpl<ArrayDimensionValueTy> &Dims) {
auto Dimensions = ATy->getDimensions();
llvm::Value *Stride = llvm::ConstantInt::get(CGM.SizeTy, 1);

Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void CodeGenFunction::EmitVarDecl(const VarDecl *D) {
HasSavedVariables = true;
} else {
if (Type->isArrayType())
Ptr = CreateArrayAlloca(Type, D->getName());
Ptr = CreateArrayTypeAlloca(Type, D->getName());
else
Ptr =
Builder.CreateAlloca(ConvertTypeForMem(Type), nullptr, D->getName());
Expand Down
12 changes: 12 additions & 0 deletions lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class StmtEmmitter : public ConstStmtVisitor<StmtEmmitter> {
void VisitComputedGotoStmt(const ComputedGotoStmt *S) {
CGF.EmitComputedGotoStmt(S);
}
void VisitAllocateStmt(const AllocateStmt *S) { CGF.EmitAllocateStmt(S); }
void VisitDeallocateStmt(const DeallocateStmt *S) {
CGF.EmitDeallocateStmt(S);
}
Expand Down Expand Up @@ -196,6 +197,17 @@ void CodeGenFunction::EmitComputedGotoStmt(const ComputedGotoStmt *S) {
EmitBlock(DefaultCase);
}

void CodeGenFunction::EmitAllocateStmt(const AllocateStmt *S) {
for (auto Arg : S->getArguments()) {
auto Alloc = dyn_cast<AllocExpr>(Arg);
assert(Alloc && "Expecting allocate expression");
auto Ptr = CreateHeapArrayAlloca(Alloc);
auto Target = Alloc->getTarget();
auto Loc = EmitLValue(Target);
EmitStore(Ptr, Loc, Target->getType());
}
}

void CodeGenFunction::EmitDeallocateStmt(const DeallocateStmt *S) {
for (auto Arg : S->getArguments()) {
auto A = EmitScalarExpr(Arg);
Expand Down
10 changes: 8 additions & 2 deletions lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ class CodeGenFunction {

void EmitCommonBlock(const CommonBlockSet *S);

llvm::Value *CreateArrayAlloca(QualType T, const llvm::Twine &Name = "",
bool IsTemp = false);
llvm::Value *CreateArrayTypeAlloca(QualType T, const llvm::Twine &Name = "",
bool IsTemp = false);

/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block. The caller is responsible for setting an appropriate alignment on
Expand All @@ -223,6 +223,9 @@ class CodeGenFunction {
llvm::Value *CreateTempHeapArrayAlloca(QualType T,
const ArrayValueRef &Value);

/// CreateHeapArrayAlloca - This allocates an array on the heap
llvm::Value *CreateHeapArrayAlloca(AllocExpr *Alloc);

void EmitBlock(llvm::BasicBlock *BB);
void EmitBranch(llvm::BasicBlock *Target);
void EmitBranchOnLogicalExpr(const Expr *Condition, llvm::BasicBlock *ThenBB,
Expand All @@ -237,6 +240,7 @@ class CodeGenFunction {
void EmitAssignedGotoStmt(const AssignedGotoStmt *S);
void EmitAssignedGotoDispatcher();
void EmitComputedGotoStmt(const ComputedGotoStmt *S);
void EmitAllocateStmt(const AllocateStmt *S);
void EmitDeallocateStmt(const DeallocateStmt *S);
void EmitIfStmt(const IfStmt *S);
void EmitDoStmt(const DoStmt *S);
Expand Down Expand Up @@ -483,6 +487,8 @@ class CodeGenFunction {

void GetArrayDimensionsInfo(QualType T,
SmallVectorImpl<ArrayDimensionValueTy> &Dims);
void GetArrayDimensionsInfo(const ArrayType *ATy,
SmallVectorImpl<ArrayDimensionValueTy> &Dims);

llvm::Value *EmitArrayArgumentPointerValueABI(const Expr *E);
llvm::Constant *EmitConstantArrayExpr(const ArrayConstructorExpr *E);
Expand Down
1 change: 1 addition & 0 deletions lib/Parse/ParseExec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ Parser::StmtResult Parser::ParseALLOCATEStmt() {
return StmtError();

// TODO [ type-spec :: ]
// TODO (Language standard specific)

// allocation-list
SmallVector<ExprResult, 4> Alloc;
Expand Down
12 changes: 9 additions & 3 deletions test/CodeGen/memory.f95
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
! RUN: %fort %s -S -emit-llvm -o - | %file_check %s
! RUN: %fort %s -O0 -S -emit-llvm -o - | %file_check %s
program p
integer, allocatable :: a(10), b(5) ! CHECK: %a = alloca i32*
continue ! CHECK: %b = alloca i32*
integer(kind=4), allocatable :: a(10), b(5) ! CHECK: %a = alloca i32*
continue ! CHECK: %b = alloca i32*
allocate(a(10), b(5)) ! CHECK: @libfort_malloc({{.*}}40)
continue ! CHECK-NEXT: bitcast i8* {{.*}} to i32*
continue ! CHECK-NEXT: store i32* {{.*}}, i32** %a
continue ! CHECK: @libfort_malloc({{.*}}20)
continue ! CHECK-NEXT: bitcast i8* {{.*}} to i32*
continue ! CHECK-NEXT: store i32* {{.*}}, i32** %b
deallocate(a,b) ! CHECK: load {{.*}} %a
continue ! CHECK: call void @libfort_free
continue ! CHECK: load {{.*}} %b
Expand Down

0 comments on commit f963347

Please sign in to comment.