Skip to content

Commit

Permalink
Update subroutine methods to match functions
Browse files Browse the repository at this point in the history
  • Loading branch information
dpoerio committed May 29, 2021
1 parent e0e12b8 commit aad9410
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 11 deletions.
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,4 @@ RUN(NAME recursion_01 LABELS gfortran llvm)

RUN(NAME return_01 LABELS gfortran llvm)
RUN(NAME return_02 LABELS gfortran llvm)
RUN(NAME return_03 LABELS gfortran llvm)
17 changes: 17 additions & 0 deletions integration_tests/return_03.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
program main
integer :: main_out = 999
call main1(main_out)
print *, "main1 called"
contains
subroutine main1(out_var)
integer :: out_var
integer :: i = 10
if (i .GT. 5) then
out_var = i
print *, "early return"
return
end if
print *, "normal return"
out_var = i
end subroutine main1
end program
41 changes: 30 additions & 11 deletions src/lfortran/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1318,27 +1318,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>


void generate_subroutine(const ASR::Subroutine_t &x){
uint32_t h = get_hash((ASR::asr_t*)&x);
bool interactive = (x.m_abi == ASR::abiType::Interactive);
if (x.m_deftype == ASR::deftypeType::Implementation) {

if (interactive) return;

if (!prototype_only) {
llvm::Function* F = llvm_symtab_fn[h];
llvm::BasicBlock *BB = llvm::BasicBlock::Create(context,
".entry", F);
builder->SetInsertPoint(BB);

declare_args(x, *F);

declare_local_vars(x);
define_subroutine_entry(x);

for (size_t i=0; i<x.n_body; i++) {
this->visit_stmt(*x.m_body[i]);
}

builder->CreateRetVoid();
define_subroutine_exit(x);
}
}
}
Expand Down Expand Up @@ -1414,7 +1406,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
declare_local_vars(x);
}

inline void define_function_exit(const ASR::Function_t& x) {

inline void define_subroutine_entry(const ASR::Subroutine_t& x) {
uint32_t h = get_hash((ASR::asr_t*)&x);
llvm::Function* F = llvm_symtab_fn[h];
llvm::BasicBlock *BB = llvm::BasicBlock::Create(context,
".entry", F);
builder->SetInsertPoint(BB);

declare_args(x, *F);

declare_local_vars(x);
}

inline void define_function_exit(const ASR::Function_t& x) {
if (early_return) {
builder->CreateBr(if_return);
}
Expand All @@ -1433,6 +1438,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
builder->CreateRet(ret_val2);
}


inline void define_subroutine_exit(const ASR::Subroutine_t& /*x*/) {
if (early_return) {
builder->CreateBr(if_return);
}

if (early_return) {
builder->SetInsertPoint(if_return);
early_return = false;
}

builder->CreateRetVoid();
}

void generate_function(const ASR::Function_t &x){
bool interactive = (x.m_abi == ASR::abiType::Interactive);
if (x.m_deftype == ASR::deftypeType::Implementation ) {
Expand Down
13 changes: 13 additions & 0 deletions tests/reference/llvm-return_03-fd5ee01.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"basename": "llvm-return_03-fd5ee01",
"cmd": "lfortran --show-llvm {infile} -o {outfile}",
"infile": "tests/../integration_tests/return_03.f90",
"infile_hash": "7d4898b23c807b105723b597c037469040fba56ee6c9891c93947d14",
"outfile": null,
"outfile_hash": null,
"stdout": "llvm-return_03-fd5ee01.stdout",
"stdout_hash": "f5de0548d6690b15f07d47f1b94e6af28ecf80b55404c37a4ea9f4e5",
"stderr": null,
"stderr_hash": null,
"returncode": 0
}
48 changes: 48 additions & 0 deletions tests/reference/llvm-return_03-fd5ee01.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
; ModuleID = 'LFortran'
source_filename = "LFortran"

@0 = private unnamed_addr constant [13 x i8] c"early return\00", align 1
@1 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
@2 = private unnamed_addr constant [14 x i8] c"normal return\00", align 1
@3 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
@4 = private unnamed_addr constant [13 x i8] c"main1 called\00", align 1
@5 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1

define void @main1(i32* %out_var) {
.entry:
%i = alloca i32, align 4
store i32 10, i32* %i, align 4
%0 = load i32, i32* %i, align 4
%1 = icmp sgt i32 %0, 5
br i1 %1, label %then, label %else

then: ; preds = %.entry
%2 = load i32, i32* %i, align 4
store i32 %2, i32* %out_var, align 4
call void (i8*, ...) @_lfortran_printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @1, i32 0, i32 0), i8* getelementptr inbounds ([13 x i8], [13 x i8]* @0, i32 0, i32 0))
br label %return

return: ; preds = %ifcont, %then
ret void

else: ; preds = %.entry
br label %ifcont

ifcont: ; preds = %else
call void (i8*, ...) @_lfortran_printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @3, i32 0, i32 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @2, i32 0, i32 0))
%3 = load i32, i32* %i, align 4
store i32 %3, i32* %out_var, align 4
br label %return
}

declare void @_lfortran_printf(i8*, ...)

define i32 @main() {
.entry:
%main_out = alloca i32, align 4
store i32 999, i32* %main_out, align 4
call void @main1(i32* %main_out)
call void (i8*, ...) @_lfortran_printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @5, i32 0, i32 0), i8* getelementptr inbounds ([13 x i8], [13 x i8]* @4, i32 0, i32 0))
ret i32 0
}

4 changes: 4 additions & 0 deletions tests/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,10 @@ llvm = true
filename = "../integration_tests/return_02.f90"
llvm = true

[[test]]
filename = "../integration_tests/return_03.f90"
llvm = true

[[test]]
filename = "../integration_tests/modules_13.f90"
llvm = true

0 comments on commit aad9410

Please sign in to comment.