89 lines
3 KiB
LLVM
89 lines
3 KiB
LLVM
|
|
; fdustin, geneliu
|
||
|
|
; generates a geometric series of 10 numbers given a base and a factor
|
||
|
|
%array = type [10 x i64]
|
||
|
|
|
||
|
|
@base = global i64 2
|
||
|
|
@factor = global i64 2
|
||
|
|
@answer = global %array [ i64 2, i64 4, i64 8, i64 16, i64 32, i64 64, i64 128, i64 256, i64 512, i64 1024 ]
|
||
|
|
@temp= global %array [ i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0 ]
|
||
|
|
|
||
|
|
define i64 @check_answer(%array* %expected, %array* %actual) {
|
||
|
|
%curr_idx = alloca i64
|
||
|
|
store i64 0, i64* %curr_idx
|
||
|
|
br label %loop_check_cond
|
||
|
|
|
||
|
|
loop_check_cond:
|
||
|
|
%idx = load i64, i64* %curr_idx
|
||
|
|
%cond_keep = icmp slt i64 %idx, 10
|
||
|
|
br i1 %cond_keep, label %loop_check_body, label %loop_check_exit
|
||
|
|
|
||
|
|
loop_check_body:
|
||
|
|
%exp_ptr = getelementptr %array, %array* %expected, i32 0, i64 %idx
|
||
|
|
%act_ptr = getelementptr %array, %array* %actual, i32 0, i64 %idx
|
||
|
|
%exp_val = load i64, i64* %exp_ptr
|
||
|
|
%act_val = load i64, i64* %act_ptr
|
||
|
|
|
||
|
|
%cmp = icmp eq i64 %exp_val, %act_val
|
||
|
|
|
||
|
|
%new_idx = add i64 %idx, 1
|
||
|
|
store i64 %new_idx, i64* %curr_idx
|
||
|
|
br i1 %cmp, label %loop_check_cond, label %loop_check_bad
|
||
|
|
|
||
|
|
loop_check_bad:
|
||
|
|
ret i64 0
|
||
|
|
|
||
|
|
loop_check_exit:
|
||
|
|
ret i64 1
|
||
|
|
}
|
||
|
|
|
||
|
|
define void @geometric_series(i64 %base, i64 %factor, %array* %arr) {
|
||
|
|
%curr_idx = alloca i64
|
||
|
|
store i64 0, i64* %curr_idx
|
||
|
|
br label %loop_geo_cond
|
||
|
|
|
||
|
|
loop_geo_cond:
|
||
|
|
%idx = load i64, i64* %curr_idx
|
||
|
|
%cond = icmp slt i64 %idx, 10
|
||
|
|
br i1 %cond, label %loop_geo_body, label %loop_geo_exit
|
||
|
|
|
||
|
|
loop_geo_body:
|
||
|
|
%should_use_base_value = icmp eq i64 %idx, 0
|
||
|
|
br i1 %should_use_base_value, label %use_base_value, label %use_array_value
|
||
|
|
use_base_value:
|
||
|
|
; load the base value into the 1st element of the array
|
||
|
|
%arr_index_zero = getelementptr %array, %array* %arr, i32 0, i64 0
|
||
|
|
store i64 %base, i64* %arr_index_zero
|
||
|
|
; increment the counter
|
||
|
|
%new_idx_of_base = add i64 %idx, 1
|
||
|
|
store i64 %new_idx_of_base, i64* %curr_idx
|
||
|
|
br label %loop_geo_cond
|
||
|
|
|
||
|
|
use_array_value:
|
||
|
|
; use the previous value to calculate the next value
|
||
|
|
%prev_idx = sub i64 %idx, 1
|
||
|
|
%prev_value_ptr = getelementptr %array, %array* %arr, i32 0, i64 %prev_idx
|
||
|
|
%prev_value = load i64, i64* %prev_value_ptr
|
||
|
|
%new_value = mul i64 %prev_value, %factor
|
||
|
|
|
||
|
|
; store the new value into the array
|
||
|
|
%new_value_ptr = getelementptr %array, %array* %arr, i32 0, i64 %idx
|
||
|
|
store i64 %new_value, i64* %new_value_ptr
|
||
|
|
|
||
|
|
; increment the counter
|
||
|
|
%new_idx_of_non_base = add i64 %idx, 1
|
||
|
|
store i64 %new_idx_of_non_base, i64* %curr_idx
|
||
|
|
br label %loop_geo_cond
|
||
|
|
|
||
|
|
loop_geo_exit:
|
||
|
|
ret void
|
||
|
|
}
|
||
|
|
|
||
|
|
define i64 @main() {
|
||
|
|
%base_local = load i64, i64* @base
|
||
|
|
%factor_local = load i64, i64* @factor
|
||
|
|
call void @geometric_series(i64 %base_local, i64 %factor_local, %array* @temp)
|
||
|
|
%res = call i64 @check_answer(%array* @answer, %array* @temp)
|
||
|
|
|
||
|
|
ret i64 %res
|
||
|
|
}
|