; ModuleID = 'LFortran'
source_filename = "LFortran"
target datalayout = "..."

%string_descriptor = type <{ i8*, i64 }>
%"~unlimited_polymorphic_type" = type <{ i32 (...)**, i8* }>

@_Type_Info_integer_8 = linkonce_odr unnamed_addr constant { i8*, i8*, i8* } { i8* inttoptr (i32 8 to i8*), i8* inttoptr (i64 8 to i8*), i8* null }, align 8
@_VTable_integer_8 = linkonce_odr unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_Type_Info_integer_8 to i8*), i8* bitcast (void (i8*, i8*)* @_copy_integer_8 to i8*), i8* bitcast (void (i8**)* @_allocate_integer_8 to i8*), i8* bitcast (void (i8*)* @finalize_i64_for_UPoly to i8*)] }, align 8
@0 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
@string_const_data = private constant [10 x i8] c"integer(8)"
@string_const = private global %string_descriptor <{ i8* getelementptr inbounds ([10 x i8], [10 x i8]* @string_const_data, i32 0, i32 0), i64 10 }>
@1 = private unnamed_addr constant [5 x i8] c"%s%s\00", align 1
@_Type_Info_integer_4 = linkonce_odr unnamed_addr constant { i8*, i8*, i8* } { i8* inttoptr (i32 4 to i8*), i8* inttoptr (i64 4 to i8*), i8* null }, align 8
@2 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
@string_const_data.1 = private constant [10 x i8] c"integer(4)"
@string_const.2 = private global %string_descriptor <{ i8* getelementptr inbounds ([10 x i8], [10 x i8]* @string_const_data.1, i32 0, i32 0), i64 10 }>
@3 = private unnamed_addr constant [5 x i8] c"%s%s\00", align 1
@_Type_Info_real_4 = linkonce_odr unnamed_addr constant { i8*, i8*, i8* } { i8* inttoptr (i32 6 to i8*), i8* inttoptr (i64 4 to i8*), i8* null }, align 8
@4 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
@string_const_data.3 = private constant [4 x i8] c"real"
@string_const.4 = private global %string_descriptor <{ i8* getelementptr inbounds ([4 x i8], [4 x i8]* @string_const_data.3, i32 0, i32 0), i64 4 }>
@5 = private unnamed_addr constant [5 x i8] c"%s%s\00", align 1
@6 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
@string_const_data.5 = private constant [7 x i8] c"default"
@string_const.6 = private global %string_descriptor <{ i8* getelementptr inbounds ([7 x i8], [7 x i8]* @string_const_data.5, i32 0, i32 0), i64 7 }>
@7 = private unnamed_addr constant [5 x i8] c"%s%s\00", align 1

define i32 @main(i32 %0, i8** %1) {
.entry:
  call void @_lpython_call_initial_functions(i32 %0, i8** %1)
  %var = alloca %"~unlimited_polymorphic_type"*, align 8
  store %"~unlimited_polymorphic_type"* null, %"~unlimited_polymorphic_type"** %var, align 8
  %x = alloca i64, align 8
  store i64 10, i64* %x, align 8
  %2 = call i8* @_lfortran_get_default_allocator()
  %3 = call i8* @_lfortran_malloc_alloc(i8* %2, i64 8)
  call void @llvm.memset.p0i8.i32(i8* %3, i8 0, i32 8, i1 false)
  %4 = call i8* @_lfortran_get_default_allocator()
  %5 = call i8* @_lfortran_malloc_alloc(i8* %4, i64 16)
  call void @llvm.memset.p0i8.i32(i8* %5, i8 0, i32 16, i1 false)
  %6 = bitcast i8* %5 to %"~unlimited_polymorphic_type"*
  store %"~unlimited_polymorphic_type"* %6, %"~unlimited_polymorphic_type"** %var, align 8
  %7 = load %"~unlimited_polymorphic_type"*, %"~unlimited_polymorphic_type"** %var, align 8
  %8 = getelementptr %"~unlimited_polymorphic_type", %"~unlimited_polymorphic_type"* %7, i32 0, i32 1
  store i8* %3, i8** %8, align 8
  %9 = load i8*, i8** %8, align 8
  %10 = bitcast i8* %9 to i64*
  %11 = bitcast %"~unlimited_polymorphic_type"* %6 to i32 (...)***
  store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_VTable_integer_8, i32 0, i32 0, i32 2) to i32 (...)**), i32 (...)*** %11, align 8
  %12 = load i64, i64* %x, align 8
  store i64 %12, i64* %10, align 8
  %13 = alloca i1, align 1
  %14 = load %"~unlimited_polymorphic_type"*, %"~unlimited_polymorphic_type"** %var, align 8
  %15 = bitcast %"~unlimited_polymorphic_type"* %14 to i8*
  %16 = call i8* @__lfortran_dynamic_cast(i8* %15, i8* bitcast ({ i8*, i8*, i8* }* @_Type_Info_integer_8 to i8*), i1 true)
  %17 = icmp ne i8* %16, null
  store i1 %17, i1* %13, align 1
  %18 = load i1, i1* %13, align 1
  br i1 %18, label %then, label %else

then:                                             ; preds = %.entry
  br label %"~select_type_block_.start"

"~select_type_block_.start":                      ; preds = %then
  %19 = call i8* @llvm.stacksave()
  %20 = load i8*, i8** getelementptr inbounds (%string_descriptor, %string_descriptor* @string_const, i32 0, i32 0), align 8
  call void @_lfortran_printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @1, i32 0, i32 0), i8* %20, i32 10, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @0, i32 0, i32 0), i32 1)
  br label %"~select_type_block_.end"

"~select_type_block_.end":                        ; preds = %"~select_type_block_.start"
  br label %"FINALIZE_SYMTABLE_~select_type_block_"

"FINALIZE_SYMTABLE_~select_type_block_":          ; preds = %"~select_type_block_.end"
  call void @llvm.stackrestore(i8* %19)
  br label %ifcont

else:                                             ; preds = %.entry
  %21 = alloca i1, align 1
  %22 = load %"~unlimited_polymorphic_type"*, %"~unlimited_polymorphic_type"** %var, align 8
  %23 = bitcast %"~unlimited_polymorphic_type"* %22 to i8*
  %24 = call i8* @__lfortran_dynamic_cast(i8* %23, i8* bitcast ({ i8*, i8*, i8* }* @_Type_Info_integer_4 to i8*), i1 true)
  %25 = icmp ne i8* %24, null
  store i1 %25, i1* %21, align 1
  %26 = load i1, i1* %21, align 1
  br i1 %26, label %then1, label %else2

then1:                                            ; preds = %else
  br label %"~select_type_block_1.start"

"~select_type_block_1.start":                     ; preds = %then1
  %27 = call i8* @llvm.stacksave()
  %28 = load i8*, i8** getelementptr inbounds (%string_descriptor, %string_descriptor* @string_const.2, i32 0, i32 0), align 8
  call void @_lfortran_printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @3, i32 0, i32 0), i8* %28, i32 10, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @2, i32 0, i32 0), i32 1)
  br label %"~select_type_block_1.end"

"~select_type_block_1.end":                       ; preds = %"~select_type_block_1.start"
  br label %"FINALIZE_SYMTABLE_~select_type_block_1"

"FINALIZE_SYMTABLE_~select_type_block_1":         ; preds = %"~select_type_block_1.end"
  call void @llvm.stackrestore(i8* %27)
  br label %ifcont

else2:                                            ; preds = %else
  %29 = alloca i1, align 1
  %30 = load %"~unlimited_polymorphic_type"*, %"~unlimited_polymorphic_type"** %var, align 8
  %31 = bitcast %"~unlimited_polymorphic_type"* %30 to i8*
  %32 = call i8* @__lfortran_dynamic_cast(i8* %31, i8* bitcast ({ i8*, i8*, i8* }* @_Type_Info_real_4 to i8*), i1 true)
  %33 = icmp ne i8* %32, null
  store i1 %33, i1* %29, align 1
  %34 = load i1, i1* %29, align 1
  br i1 %34, label %then3, label %else4

then3:                                            ; preds = %else2
  br label %"~select_type_block_2.start"

"~select_type_block_2.start":                     ; preds = %then3
  %35 = call i8* @llvm.stacksave()
  %36 = load i8*, i8** getelementptr inbounds (%string_descriptor, %string_descriptor* @string_const.4, i32 0, i32 0), align 8
  call void @_lfortran_printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @5, i32 0, i32 0), i8* %36, i32 4, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @4, i32 0, i32 0), i32 1)
  br label %"~select_type_block_2.end"

"~select_type_block_2.end":                       ; preds = %"~select_type_block_2.start"
  br label %"FINALIZE_SYMTABLE_~select_type_block_2"

"FINALIZE_SYMTABLE_~select_type_block_2":         ; preds = %"~select_type_block_2.end"
  call void @llvm.stackrestore(i8* %35)
  br label %ifcont

else4:                                            ; preds = %else2
  br label %"~select_type_block_3.start"

"~select_type_block_3.start":                     ; preds = %else4
  %37 = call i8* @llvm.stacksave()
  %38 = load i8*, i8** getelementptr inbounds (%string_descriptor, %string_descriptor* @string_const.6, i32 0, i32 0), align 8
  call void @_lfortran_printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @7, i32 0, i32 0), i8* %38, i32 7, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @6, i32 0, i32 0), i32 1)
  br label %"~select_type_block_3.end"

"~select_type_block_3.end":                       ; preds = %"~select_type_block_3.start"
  br label %"FINALIZE_SYMTABLE_~select_type_block_3"

"FINALIZE_SYMTABLE_~select_type_block_3":         ; preds = %"~select_type_block_3.end"
  call void @llvm.stackrestore(i8* %37)
  br label %ifcont

ifcont:                                           ; preds = %"FINALIZE_SYMTABLE_~select_type_block_3", %"FINALIZE_SYMTABLE_~select_type_block_2", %"FINALIZE_SYMTABLE_~select_type_block_1", %"FINALIZE_SYMTABLE_~select_type_block_"
  br label %return

return:                                           ; preds = %ifcont
  br label %FINALIZE_SYMTABLE_unlimited_polymorphic_intrinsic_type_allocate

FINALIZE_SYMTABLE_unlimited_polymorphic_intrinsic_type_allocate: ; preds = %return
  br label %Finalize_Variable_var

Finalize_Variable_var:                            ; preds = %FINALIZE_SYMTABLE_unlimited_polymorphic_intrinsic_type_allocate
  %39 = load %"~unlimited_polymorphic_type"*, %"~unlimited_polymorphic_type"** %var, align 8
  call void @"finalize_allocatable__StructType_Class__~unlimited_polymorphic_type_3"(%"~unlimited_polymorphic_type"* %39)
  call void @_lfortran_internal_alloc_finalize()
  ret i32 0
}

declare void @_lpython_call_initial_functions(i32, i8**)

declare i8* @_lfortran_malloc_alloc(i8*, i64)

declare i8* @_lfortran_get_default_allocator()

; Function Attrs: argmemonly nounwind willreturn writeonly
declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1 immarg) #0

define linkonce_odr void @_copy_integer_8(i8* %0, i8* %1) {
entry:
  %2 = bitcast i8* %0 to i64*
  %3 = bitcast i8* %1 to i64*
  %4 = load i64, i64* %2, align 8
  store i64 %4, i64* %3, align 8
  ret void
}

define linkonce_odr void @_allocate_integer_8(i8** %0) {
entry:
  %1 = call i8* @_lfortran_get_default_allocator()
  %2 = call i8* @_lfortran_malloc_alloc(i8* %1, i64 16)
  call void @llvm.memset.p0i8.i32(i8* %2, i8 0, i32 16, i1 false)
  store i8* %2, i8** %0, align 8
  %3 = bitcast i8* %2 to <{ i32 (...)**, i8* }>*
  %4 = bitcast <{ i32 (...)**, i8* }>* %3 to i32 (...)***
  store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_VTable_integer_8, i32 0, i32 0, i32 2) to i32 (...)**), i32 (...)*** %4, align 8
  %5 = call i8* @_lfortran_get_default_allocator()
  %6 = call i8* @_lfortran_malloc_alloc(i8* %5, i64 8)
  call void @llvm.memset.p0i8.i32(i8* %6, i8 0, i32 8, i1 false)
  %7 = getelementptr <{ i32 (...)**, i8* }>, <{ i32 (...)**, i8* }>* %3, i32 0, i32 1
  store i8* %6, i8** %7, align 8
  ret void
}

define internal void @finalize_i64_for_UPoly(i8* %0) {
entry:
  %1 = bitcast i8* %0 to i64*
  ret void
}

declare i8* @__lfortran_dynamic_cast(i8*, i8*, i1)

; Function Attrs: nounwind
declare i8* @llvm.stacksave() #1

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

; Function Attrs: nounwind
declare void @llvm.stackrestore(i8*) #1

define internal void @"finalize_allocatable__StructType_Class__~unlimited_polymorphic_type_3"(%"~unlimited_polymorphic_type"* %0) {
entry:
  %1 = call i8* @_lfortran_get_default_allocator()
  %2 = icmp ne %"~unlimited_polymorphic_type"* %0, null
  br i1 %2, label %is_allocated.then, label %is_allocated.else

is_allocated.then:                                ; preds = %entry
  call void @"finalize_StructType_Class__~unlimited_polymorphic_type_3"(%"~unlimited_polymorphic_type"* %0)
  %3 = bitcast %"~unlimited_polymorphic_type"* %0 to i8*
  call void @_lfortran_free_alloc(i8* %1, i8* %3)
  br label %is_allocated.ifcont

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

is_allocated.ifcont:                              ; preds = %is_allocated.else, %is_allocated.then
  ret void
}

define internal void @"finalize_StructType_Class__~unlimited_polymorphic_type_3"(%"~unlimited_polymorphic_type"* %0) {
entry:
  %1 = call i8* @_lfortran_get_default_allocator()
  %2 = getelementptr %"~unlimited_polymorphic_type", %"~unlimited_polymorphic_type"* %0, i32 0, i32 0
  %3 = load i32 (...)**, i32 (...)*** %2, align 8
  %4 = icmp ne i32 (...)** %3, null
  br i1 %4, label %is_allocated.then, label %is_allocated.else

is_allocated.then:                                ; preds = %entry
  %5 = getelementptr inbounds i32 (...)*, i32 (...)** %3, i32 2
  %6 = load i8*, i32 (...)** %5, align 8
  %7 = bitcast i8* %6 to void (i8*)*
  %8 = getelementptr %"~unlimited_polymorphic_type", %"~unlimited_polymorphic_type"* %0, i32 0, i32 1
  %9 = load i8*, i8** %8, align 8
  call void %7(i8* %9)
  br label %is_allocated.ifcont

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

is_allocated.ifcont:                              ; preds = %is_allocated.else, %is_allocated.then
  %10 = getelementptr %"~unlimited_polymorphic_type", %"~unlimited_polymorphic_type"* %0, i32 0, i32 1
  %11 = load i8*, i8** %10, align 8
  call void @_lfortran_free_alloc(i8* %1, i8* %11)
  ret void
}

declare void @_lfortran_free_alloc(i8*, i8*)

declare void @_lfortran_internal_alloc_finalize()

attributes #0 = { argmemonly nounwind willreturn writeonly }
attributes #1 = { nounwind }
