From 17dcb742c6eabb5f700199c3b795b660e232dc75 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 11 Sep 2021 00:44:35 +0200 Subject: [PATCH] Fixed codegen for subarray global initializers. Adding fasta example. --- resources/examples/fasta.c3 | 74 ++-- src/compiler/llvm_codegen.c | 42 ++- src/compiler/llvm_codegen_expr.c | 2 +- src/compiler/llvm_codegen_internal.h | 1 + test/test_suite/initializer_lists/fasta.c3t | 384 ++++++++++++++++++++ 5 files changed, 464 insertions(+), 39 deletions(-) create mode 100644 test/test_suite/initializer_lists/fasta.c3t diff --git a/resources/examples/fasta.c3 b/resources/examples/fasta.c3 index b71c47f0b..08c65672e 100644 --- a/resources/examples/fasta.c3 +++ b/resources/examples/fasta.c3 @@ -9,8 +9,8 @@ uint seed = SEED; func float fasta_rand(float max) { - seed = (seed * IA + IC) % IM; - return max * seed / IM; + seed = (seed * IA + IC) % IM; + return max * seed / IM; } private char[] alu = @@ -27,7 +27,7 @@ extern func int printf(char *s, ...); extern func void putchar(int c); char[] iub = "acgtBDHKMNRSVWY"; -double[*] iub_p = { +double[] iub_p = { 0.27, 0.12, 0.12, @@ -45,7 +45,7 @@ double[*] iub_p = { 0.02 }; char[] homosapiens = "acgt"; -double[*] homosapiens_p = { +double[] homosapiens_p = { 0.3029549426680, 0.1979883004921, 0.1975473066391, @@ -57,49 +57,49 @@ const LINELEN = 60; // slowest character-at-a-time output func void repeat_fasta(char[] seq, int n) { - usize len = seq.len; - int i = void; - for (i = 0; i < n; i++) - { - putchar(seq[i % len]); - if (i % LINELEN == LINELEN - 1) putchar('\n'); - } - if (i % LINELEN != 0) putchar('\n'); + usize len = seq.len; + int i = void; + for (i = 0; i < n; i++) + { + putchar(seq[i % len]); + if (i % LINELEN == LINELEN - 1) putchar('\n'); + } + if (i % LINELEN != 0) putchar('\n'); } func void random_fasta(char[] symb, double[] probability, int n) { - assert(symb.len == probability.len); - int len = probability.len; - int i = void; - for (i = 0; i < n; i++) - { - double v = fasta_rand(1.0); - /* slowest idiomatic linear lookup. Fast if len is short though. */ - int j = void; - for (j = 0; j < len - 1; j++) - { - v -= probability[j]; - if (v < 0) break; - } - putchar(symb[j]); - if (i % LINELEN == LINELEN - 1) putchar('\n'); - } - if (i % LINELEN != 0) putchar('\n'); + assert(symb.len == probability.len); + int len = probability.len; + int i = void; + for (i = 0; i < n; i++) + { + double v = fasta_rand(1.0); + /* slowest idiomatic linear lookup. Fast if len is short though. */ + int j = void; + for (j = 0; j < len - 1; j++) + { + v -= probability[j]; + if (v < 0) break; + } + putchar(symb[j]); + if (i % LINELEN == LINELEN - 1) putchar('\n'); + } + if (i % LINELEN != 0) putchar('\n'); } func void main(int argc, char **argv) { - int n=1000; - if (argc > 1) n = atoi(argv[1]); + int n = 1000; + if (argc > 1) n = atoi(argv[1]); - printf(">ONE Homo sapiens alu\n"); - repeat_fasta(alu, n * 2); + printf(">ONE Homo sapiens alu\n"); + repeat_fasta(alu, n * 2); - printf(">TWO IUB ambiguity codes\n"); - random_fasta(iub, &iub_p, n * 3); + printf(">TWO IUB ambiguity codes\n"); + random_fasta(iub, iub_p, n * 3); - printf(">THREE Homo sapiens frequency\n"); - random_fasta(homosapiens, &homosapiens_p, n * 5); + printf(">THREE Homo sapiens frequency\n"); + random_fasta(homosapiens, homosapiens_p, n * 5); } diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 30fabbe9e..4b87ee675 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -344,7 +344,47 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) { if (init_expr->expr_kind == EXPR_CONST && init_expr->const_expr.const_kind == CONST_LIST) { - init_value = llvm_emit_const_initializer(c, init_expr->const_expr.list, &modified); + ConstInitializer *list = init_expr->const_expr.list; + init_value = llvm_emit_const_initializer(c, list, &modified); + Type *type = type_lowering(init_expr->type); + if (type->type_kind == TYPE_SUBARRAY) + { + LLVMTypeRef const_type = LLVMTypeOf(init_value); + LLVMValueRef global_copy = LLVMAddGlobal(c->module, const_type, ".__const"); + LLVMSetLinkage(global_copy, LLVMPrivateLinkage); + + // Set a nice alignment + Type *ptr = type_get_ptr(type); + llvm_set_alignment(global_copy, type_alloca_alignment(ptr)); + + // Set the value and make it constant + LLVMSetInitializer(global_copy, init_value); + LLVMSetGlobalConstant(global_copy, true); + + LLVMValueRef value = LLVMConstBitCast(global_copy, llvm_get_type(c, ptr)); + ByteSize size; + switch (list->kind) + { + case CONST_INIT_ZERO: + size = 0; + break; + case CONST_INIT_ARRAY: + size = VECLAST(list->init_array.elements)->init_array_value.index + 1; + break; + case CONST_INIT_ARRAY_FULL: + size = vec_size(list->init_array_full); + break; + default: + UNREACHABLE + } + LLVMTypeRef subarray_type = llvm_get_type(c, type); + LLVMValueRef result = LLVMGetUndef(subarray_type); + LLVMValueRef len = llvm_const_int(c, type_usize, size); + unsigned id = 0; + result = LLVMConstInsertValue(result, value, &id, 1); + id = 1; + init_value = LLVMConstInsertValue(result, len, &id, 1); + } } else { diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 438f11cb3..ef23236e5 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -782,7 +782,7 @@ static LLVMValueRef llvm_recursive_set_const_value(GenContext *context, Designat } -static inline void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, Expr *expr) +void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, Expr *expr) { bool modified = false; // First create the constant value. diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 954095de3..97166eb23 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -240,6 +240,7 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr); void llvm_emit_typeid(GenContext *c, BEValue *be_value, Type *type); void llvm_emit_global_variable_init(GenContext *c, Decl *decl); +void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, Expr *expr); void llvm_emit_int_comp_zero(GenContext *c, BEValue *result, BEValue *lhs, BinaryOp binary_op); void llvm_emit_int_comparison(GenContext *c, BEValue *result, BEValue *lhs, BEValue *rhs, BinaryOp binary_op); void llvm_emit_int_comp(GenContext *c, BEValue *result, Type *lhs_type, Type *rhs_type, LLVMValueRef lhs_value, LLVMValueRef rhs_value, BinaryOp binary_op); diff --git a/test/test_suite/initializer_lists/fasta.c3t b/test/test_suite/initializer_lists/fasta.c3t new file mode 100644 index 000000000..5a72fff83 --- /dev/null +++ b/test/test_suite/initializer_lists/fasta.c3t @@ -0,0 +1,384 @@ +module fasta; + +const IM = 139968; +const IA = 3877; +const IC = 29573; +const SEED = 42; + +uint seed = SEED; + +func float fasta_rand(float max) +{ + seed = (seed * IA + IC) % IM; + return max * seed / IM; +} + +private char[] alu = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + +extern func int atoi(char *s); +extern func int printf(char *s, ...); +extern func void putchar(int c); + +char[] iub = "acgtBDHKMNRSVWY"; +double[] iub_p = { + 0.27, + 0.12, + 0.12, + 0.27, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02, + 0.02 }; + +char[] homosapiens = "acgt"; +double[] homosapiens_p = { + 0.3029549426680, + 0.1979883004921, + 0.1975473066391, + 0.3015094502008 +}; + +const LINELEN = 60; + +// slowest character-at-a-time output +func void repeat_fasta(char[] seq, int n) +{ + usize len = seq.len; + int i = void; + for (i = 0; i < n; i++) + { + putchar(seq[i % len]); + if (i % LINELEN == LINELEN - 1) putchar('\n'); + } + if (i % LINELEN != 0) putchar('\n'); +} + +func void random_fasta(char[] symb, double[] probability, int n) +{ + assert(symb.len == probability.len); + int len = probability.len; + int i = void; + for (i = 0; i < n; i++) + { + double v = fasta_rand(1.0); + /* slowest idiomatic linear lookup. Fast if len is short though. */ + int j = void; + for (j = 0; j < len - 1; j++) + { + v -= probability[j]; + if (v < 0) break; + } + putchar(symb[j]); + if (i % LINELEN == LINELEN - 1) putchar('\n'); + } + if (i % LINELEN != 0) putchar('\n'); +} + +func void main(int argc, char **argv) +{ + int n = 1000; + if (argc > 1) n = atoi(argv[1]); + + printf(">ONE Homo sapiens alu\n"); + repeat_fasta(alu, n * 2); + + printf(">TWO IUB ambiguity codes\n"); + random_fasta(iub, iub_p, n * 3); + + printf(">THREE Homo sapiens frequency\n"); + random_fasta(homosapiens, homosapiens_p, n * 5); + +} + +// #expect: fasta.ll + +@fasta.IM = constant i32 139968, align 1 +@fasta.IA = constant i32 3877, align 1 +@fasta.IC = constant i32 29573, align 1 +@fasta.SEED = constant i32 42, align 1 +@fasta.seed = global i32 42, align 4 +@.str = private constant [288 x i8] c"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA\00", align 1 +@fasta.alu = protected global %"char[]" { i8* getelementptr inbounds ([288 x i8], [288 x i8]* @.str, i32 0, i32 0), i64 287 }, align 8 +@.str.11 = private constant [16 x i8] c"acgtBDHKMNRSVWY\00", align 1 +@fasta.iub = global %"char[]" { i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.11, i32 0, i32 0), i64 15 }, align 8 +@.__const = private constant [15 x double] [double 2.700000e-01, double 1.200000e-01, double 1.200000e-01, double 2.700000e-01, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02], align 8 +@fasta.iub_p = global %"double[]" { %"double[]"* bitcast ([15 x double]* @.__const to %"double[]"*), i64 15 }, align 8 +@.str.12 = private constant [5 x i8] c"acgt\00", align 1 +@fasta.homosapiens = global %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.12, i32 0, i32 0), i64 4 }, align 8 +@.__const.13 = private constant [4 x double] [double 0x3FD3639D20BAEB5B, double 0x3FC957AE3DCD561B, double 0x3FC9493AEAB6C2BF, double 0x3FD34BEE4B030838], align 8 +@fasta.homosapiens_p = global %"double[]" { %"double[]"* bitcast ([4 x double]* @.__const.13 to %"double[]"*), i64 4 }, align 8 +@fasta.LINELEN = constant i32 60, align 1 +@.str.14 = private constant [23 x i8] c">ONE Homo sapiens alu\0A\00", align 1 +@.str.15 = private constant [26 x i8] c">TWO IUB ambiguity codes\0A\00", align 1 +@.str.16 = private constant [31 x i8] c">THREE Homo sapiens frequency\0A\00", align 1 + +; Function Attrs: nounwind +define float @fasta.fasta_rand(float %0) #0 { +entry: + %max = alloca float, align 4 + store float %0, float* %max, align 4 + %1 = load i32, i32* @fasta.seed, align 4 + %mul = mul i32 %1, 3877 + %add = add i32 %mul, 29573 + %umod = urem i32 %add, 139968 + store i32 %umod, i32* @fasta.seed, align 4 + %2 = load float, float* %max, align 4 + %3 = load i32, i32* @fasta.seed, align 4 + %uifp = uitofp i32 %3 to float + %fmul = fmul float %2, %uifp + %fdiv = fdiv float %fmul, 1.399680e+05 + ret float %fdiv +} + +; Function Attrs: nounwind +declare i32 @atoi(i8*) #0 + +; Function Attrs: nounwind +declare i32 @printf(i8*, ...) #0 + +; Function Attrs: nounwind +declare void @putchar(i32) #0 + +; Function Attrs: nounwind +define void @fasta.repeat_fasta(i8* %0, i64 %1, i32 %2) #0 { +entry: + %seq = alloca %"char[]", align 8 + %n = alloca i32, align 4 + %len = alloca i64, align 8 + %i = alloca i32, align 4 + %pair = bitcast %"char[]"* %seq to { i8*, i64 }* + %lo = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0 + store i8* %0, i8** %lo, align 8 + %hi = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1 + store i64 %1, i64* %hi, align 8 + store i32 %2, i32* %n, align 4 + %len1 = getelementptr inbounds %"char[]", %"char[]"* %seq, i32 0, i32 1 + %3 = load i64, i64* %len1, align 8 + store i64 %3, i64* %len, align 8 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %4 = load i32, i32* %i, align 4 + %5 = load i32, i32* %n, align 4 + %lt = icmp slt i32 %4, %5 + br i1 %lt, label %for.body, label %for.exit + +for.body: ; preds = %for.cond + %subarrayptr = getelementptr inbounds %"char[]", %"char[]"* %seq, i32 0, i32 0 + %saptr = load i8*, i8** %subarrayptr, align 8 + %6 = load i32, i32* %i, align 4 + %sisiext = sext i32 %6 to i64 + %7 = load i64, i64* %len, align 8 + %smod = srem i64 %sisiext, %7 + %sarridx = getelementptr inbounds i8, i8* %saptr, i64 %smod + %8 = load i8, i8* %sarridx, align 1 + %uisiext = zext i8 %8 to i32 + call void @putchar(i32 %uisiext) + %9 = load i32, i32* %i, align 4 + %smod2 = srem i32 %9, 60 + %eq = icmp eq i32 %smod2, 59 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %for.body + call void @putchar(i32 10) + br label %if.exit + +if.exit: ; preds = %if.then, %for.body + br label %for.inc + +for.inc: ; preds = %if.exit + %10 = load i32, i32* %i, align 4 + %add = add i32 %10, 1 + store i32 %add, i32* %i, align 4 + br label %for.cond + +for.exit: ; preds = %for.cond + %11 = load i32, i32* %i, align 4 + %smod3 = srem i32 %11, 60 + %neq = icmp ne i32 %smod3, 0 + br i1 %neq, label %if.then4, label %if.exit5 + +if.then4: ; preds = %for.exit + call void @putchar(i32 10) + br label %if.exit5 + +if.exit5: ; preds = %if.then4, %for.exit + ret void +} + +; Function Attrs: nounwind +define void @fasta.random_fasta(i8* %0, i64 %1, i8* %2, i64 %3, i32 %4) #0 { +entry: + %symb = alloca %"char[]", align 8 + %probability = alloca %"double[]", align 8 + %n = alloca i32, align 4 + %len = alloca i32, align 4 + %i = alloca i32, align 4 + %v = alloca double, align 8 + %j = alloca i32, align 4 + %pair = bitcast %"char[]"* %symb to { i8*, i64 }* + %lo = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0 + store i8* %0, i8** %lo, align 8 + %hi = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1 + store i64 %1, i64* %hi, align 8 + %pair1 = bitcast %"double[]"* %probability to { i8*, i64 }* + %lo2 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair1, i32 0, i32 0 + store i8* %2, i8** %lo2, align 8 + %hi3 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair1, i32 0, i32 1 + store i64 %3, i64* %hi3, align 8 + store i32 %4, i32* %n, align 4 + %len4 = getelementptr inbounds %"double[]", %"double[]"* %probability, i32 0, i32 1 + %5 = load i64, i64* %len4, align 8 + %uisitrunc = trunc i64 %5 to i32 + store i32 %uisitrunc, i32* %len, align 4 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc15, %entry + %6 = load i32, i32* %i, align 4 + %7 = load i32, i32* %n, align 4 + %lt = icmp slt i32 %6, %7 + br i1 %lt, label %for.body, label %for.exit17 + +for.body: ; preds = %for.cond + %8 = call float @fasta.fasta_rand(float 1.000000e+00) + %fpfpext = fpext float %8 to double + store double %fpfpext, double* %v, align 8 + store i32 0, i32* %j, align 4 + br label %for.cond5 + +for.cond5: ; preds = %for.inc, %for.body + %9 = load i32, i32* %j, align 4 + %10 = load i32, i32* %len, align 4 + %sub = sub i32 %10, 1 + %lt6 = icmp slt i32 %9, %sub + br i1 %lt6, label %for.body7, label %for.exit + +for.body7: ; preds = %for.cond5 + %11 = load double, double* %v, align 8 + %subarrayptr = getelementptr inbounds %"double[]", %"double[]"* %probability, i32 0, i32 0 + %saptr = load double*, double** %subarrayptr, align 8 + %12 = load i32, i32* %j, align 4 + %sisiext = sext i32 %12 to i64 + %sarridx = getelementptr inbounds double, double* %saptr, i64 %sisiext + %13 = load double, double* %sarridx, align 8 + %fsub = fsub double %11, %13 + store double %fsub, double* %v, align 8 + %14 = load double, double* %v, align 8 + %lt8 = fcmp olt double %14, 0.000000e+00 + br i1 %lt8, label %if.then, label %if.exit + +if.then: ; preds = %for.body7 + br label %for.exit + +if.exit: ; preds = %for.body7 + br label %for.inc + +for.inc: ; preds = %if.exit + %15 = load i32, i32* %j, align 4 + %add = add i32 %15, 1 + store i32 %add, i32* %j, align 4 + br label %for.cond5 + +for.exit: ; preds = %if.then, %for.cond5 + %subarrayptr9 = getelementptr inbounds %"char[]", %"char[]"* %symb, i32 0, i32 0 + %saptr10 = load i8*, i8** %subarrayptr9, align 8 + %16 = load i32, i32* %j, align 4 + %sisiext11 = sext i32 %16 to i64 + %sarridx12 = getelementptr inbounds i8, i8* %saptr10, i64 %sisiext11 + %17 = load i8, i8* %sarridx12, align 1 + %uisiext = zext i8 %17 to i32 + call void @putchar(i32 %uisiext) + %18 = load i32, i32* %i, align 4 + %smod = srem i32 %18, 60 + %eq = icmp eq i32 %smod, 59 + br i1 %eq, label %if.then13, label %if.exit14 + +if.then13: ; preds = %for.exit + call void @putchar(i32 10) + br label %if.exit14 + +if.exit14: ; preds = %if.then13, %for.exit + br label %for.inc15 + +for.inc15: ; preds = %if.exit14 + %19 = load i32, i32* %i, align 4 + %add16 = add i32 %19, 1 + store i32 %add16, i32* %i, align 4 + br label %for.cond + +for.exit17: ; preds = %for.cond + %20 = load i32, i32* %i, align 4 + %smod18 = srem i32 %20, 60 + %neq = icmp ne i32 %smod18, 0 + br i1 %neq, label %if.then19, label %if.exit20 + +if.then19: ; preds = %for.exit17 + call void @putchar(i32 10) + br label %if.exit20 + +if.exit20: ; preds = %if.then19, %for.exit17 + ret void +} + +; Function Attrs: nounwind +define void @main(i32 %0, i8** %1) #0 { +entry: + %argc = alloca i32, align 4 + %argv = alloca i8**, align 8 + %n = alloca i32, align 4 + store i32 %0, i32* %argc, align 4 + store i8** %1, i8*** %argv, align 8 + store i32 1000, i32* %n, align 4 + %2 = load i32, i32* %argc, align 4 + %gt = icmp sgt i32 %2, 1 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %3 = load i8**, i8*** %argv, align 8 + %ptridx = getelementptr inbounds i8*, i8** %3, i64 1 + %4 = load i8*, i8** %ptridx, align 8 + %5 = call i32 @atoi(i8* %4) + store i32 %5, i32* %n, align 4 + br label %if.exit + +if.exit: ; preds = %if.then, %entry + %6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.14, i32 0, i32 0)) + %lo = load i8*, i8** getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"char[]"* @fasta.alu to { i8*, i64 }*), i32 0, i32 0), align 8 + %hi = load i64, i64* getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"char[]"* @fasta.alu to { i8*, i64 }*), i32 0, i32 1), align 8 + %7 = load i32, i32* %n, align 4 + %mul = mul i32 %7, 2 + call void @fasta.repeat_fasta(i8* %lo, i64 %hi, i32 %mul) + %8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str.15, i32 0, i32 0)) + %lo1 = load i8*, i8** getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"char[]"* @fasta.iub to { i8*, i64 }*), i32 0, i32 0), align 8 + %hi2 = load i64, i64* getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"char[]"* @fasta.iub to { i8*, i64 }*), i32 0, i32 1), align 8 + %lo3 = load i8*, i8** getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"double[]"* @fasta.iub_p to { i8*, i64 }*), i32 0, i32 0), align 8 + %hi4 = load i64, i64* getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"double[]"* @fasta.iub_p to { i8*, i64 }*), i32 0, i32 1), align 8 + %9 = load i32, i32* %n, align 4 + %mul5 = mul i32 %9, 3 + call void @fasta.random_fasta(i8* %lo1, i64 %hi2, i8* %lo3, i64 %hi4, i32 %mul5) + %10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.16, i32 0, i32 0)) + %lo6 = load i8*, i8** getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"char[]"* @fasta.homosapiens to { i8*, i64 }*), i32 0, i32 0), align 8 + %hi7 = load i64, i64* getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"char[]"* @fasta.homosapiens to { i8*, i64 }*), i32 0, i32 1), align 8 + %lo8 = load i8*, i8** getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"double[]"* @fasta.homosapiens_p to { i8*, i64 }*), i32 0, i32 0), align 8 + %hi9 = load i64, i64* getelementptr inbounds ({ i8*, i64 }, { i8*, i64 }* bitcast (%"double[]"* @fasta.homosapiens_p to { i8*, i64 }*), i32 0, i32 1), align 8 + %11 = load i32, i32* %n, align 4 + %mul10 = mul i32 %11, 5 + call void @fasta.random_fasta(i8* %lo6, i64 %hi7, i8* %lo8, i64 %hi9, i32 %mul10) + ret void +} \ No newline at end of file