Forward declared type
This commit is contained in:
		
							parent
							
								
									5de4ba76f5
								
							
						
					
					
						commit
						e95eea0504
					
				
							
								
								
									
										347
									
								
								src/compiler.bbb
									
									
									
									
									
								
							
							
						
						
									
										347
									
								
								src/compiler.bbb
									
									
									
									
									
								
							| @ -625,16 +625,108 @@ Value = struct | |||||||
| i128_offset: u64 = 64 * 2; | i128_offset: u64 = 64 * 2; | ||||||
| void_offset: u64 = i128_offset + 2; | void_offset: u64 = i128_offset + 2; | ||||||
| 
 | 
 | ||||||
|  | ScopeKind = enum | ||||||
|  | { | ||||||
|  |     global, | ||||||
|  |     function, | ||||||
|  |     local, | ||||||
|  |     for_each, | ||||||
|  |     macro_declaration, | ||||||
|  |     macro_instantiation, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Scope = struct | ||||||
|  | { | ||||||
|  |     parent: &Scope, | ||||||
|  |     line: u32, | ||||||
|  |     column: u32, | ||||||
|  |     kind: ScopeKind, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Variable = struct | ||||||
|  | { | ||||||
|  |     storage: &Value, | ||||||
|  |     type: &Type, | ||||||
|  |     scope: &Scope, | ||||||
|  |     name: []u8, | ||||||
|  |     line: u32, | ||||||
|  |     column: u32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Linkage = enum | ||||||
|  | { | ||||||
|  |     internal, | ||||||
|  |     external, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Global = struct | ||||||
|  | { | ||||||
|  |     variable: Variable, | ||||||
|  |     initial_value: &Value, | ||||||
|  |     next: &Global, | ||||||
|  |     linkage: Linkage, | ||||||
|  |     emitted: u1, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Local = struct | ||||||
|  | { | ||||||
|  |     variable: Variable, | ||||||
|  |     initial_value: &Value, | ||||||
|  |     next: &Local, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Argument = struct | ||||||
|  | { | ||||||
|  |     variable: Variable, | ||||||
|  |     index: u32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MacroDeclaration = struct | ||||||
|  | { | ||||||
|  |     foo: u32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MacroInstantiation = struct | ||||||
|  | { | ||||||
|  |     foo: u32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | LLVMContext = struct; | ||||||
|  | LLVMModule = struct; | ||||||
|  | LLVMBuilder = struct; | ||||||
|  | LLVMDIBuilder = struct; | ||||||
|  | LLVMValue = struct; | ||||||
|  | LLVMType = struct; | ||||||
|  | LLVMMetadata = struct; | ||||||
|  | LLVMBasicBlock = struct; | ||||||
|  | LLVMIntrinsicId = typealias u32; | ||||||
|  | 
 | ||||||
| Module = struct | Module = struct | ||||||
| { | { | ||||||
|     arena: &Arena, |     arena: &Arena, | ||||||
|     base_type_allocation: &Type, |  | ||||||
|     void_value: &Value, |  | ||||||
|     // Parser data |  | ||||||
|     content: []u8, |     content: []u8, | ||||||
|     offset: u64, |     offset: u64, | ||||||
|     line_offset: u64, |     line_offset: u64, | ||||||
|     line_character_offset: u64, |     line_character_offset: u64, | ||||||
|  | 
 | ||||||
|  |     first_pointer_type: &Type, | ||||||
|  |     first_slice_type: &Type, | ||||||
|  |     first_pair_struct_type: &Type, | ||||||
|  |     first_array_type: &Type, | ||||||
|  | 
 | ||||||
|  |     first_type: &Type, | ||||||
|  |     last_type: &Type, | ||||||
|  |     va_list_type: &Type, | ||||||
|  | 
 | ||||||
|  |     void_value: &Value, | ||||||
|  |     first_global: &Global, | ||||||
|  |     last_global: &Global, | ||||||
|  |     first_macro_declaration: &MacroDeclaration, | ||||||
|  |     last_macro_declaration: &MacroDeclaration, | ||||||
|  | 
 | ||||||
|  |     current_function: &Global, | ||||||
|  |     current_macro_declaration: &MacroDeclaration, | ||||||
|  |     current_macro_instantiation: &MacroInstantiation, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module_integer_type = fn (module: &Module, integer: TypeInteger) &Type | module_integer_type = fn (module: &Module, integer: TypeInteger) &Type | ||||||
| @ -724,6 +816,29 @@ get_column = fn (module: &Module) u32 | |||||||
|     return #truncate(column); |     return #truncate(column); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Checkpoint = struct | ||||||
|  | { | ||||||
|  |     offset: u64, | ||||||
|  |     line_offset: u64, | ||||||
|  |     line_character_offset: u64, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | get_checkpoint = fn (module: &Module) Checkpoint | ||||||
|  | { | ||||||
|  |     return { | ||||||
|  |         .offset = module.offset, | ||||||
|  |         .line_offset = module.line_offset, | ||||||
|  |         .line_character_offset = module.line_character_offset, | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | set_checkpoint = fn (module: &Module, checkpoint: Checkpoint) void | ||||||
|  | { | ||||||
|  |     module.offset = checkpoint.offset; | ||||||
|  |     module.line_offset = checkpoint.line_offset; | ||||||
|  |     module.line_character_offset = checkpoint.line_character_offset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| skip_space = fn (module: &Module) void | skip_space = fn (module: &Module) void | ||||||
| { | { | ||||||
|     while (1) |     while (1) | ||||||
| @ -817,8 +932,231 @@ parse_identifier = fn (module: &Module) []u8 | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | GlobalAttributeKeyword = enum | ||||||
|  | { | ||||||
|  |     export, | ||||||
|  |     extern, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GlobalKeyword = enum | ||||||
|  | { | ||||||
|  |     bits, | ||||||
|  |     enum, | ||||||
|  |     fn, | ||||||
|  |     macro, | ||||||
|  |     struct, | ||||||
|  |     typealias, | ||||||
|  |     union, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | left_bracket: u8 = '['; | ||||||
|  | right_bracket: u8 = ']'; | ||||||
|  | left_parenthesis: u8 = '('; | ||||||
|  | right_parenthesis: u8 = ')'; | ||||||
|  | left_brace: u8 = '{'; | ||||||
|  | right_brace: u8 = '}'; | ||||||
|  | 
 | ||||||
|  | parse_type = fn (module: &Module, scope: &Scope) &Type | ||||||
|  | { | ||||||
|  |     >start_character = module.content[module.offset]; | ||||||
|  | 
 | ||||||
|  |     if (is_identifier_start(start_character)) | ||||||
|  |     { | ||||||
|  |         #trap(); | ||||||
|  |     } | ||||||
|  |     else if (start_character == '&') | ||||||
|  |     { | ||||||
|  |         #trap(); | ||||||
|  |     } | ||||||
|  |     else if (start_character == left_bracket) | ||||||
|  |     { | ||||||
|  |         #trap(); | ||||||
|  |     } | ||||||
|  |     else if (start_character == '#') | ||||||
|  |     { | ||||||
|  |         #trap(); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         report_error(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| parse = fn (module: &Module) void | parse = fn (module: &Module) void | ||||||
| { | { | ||||||
|  |     >scope = &module.scope; | ||||||
|  | 
 | ||||||
|  |     while (1) | ||||||
|  |     { | ||||||
|  |         skip_space(module); | ||||||
|  | 
 | ||||||
|  |         if (module.offset == module.content.length) | ||||||
|  |         { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         >is_export: u1 = 0; | ||||||
|  |         >is_extern: u1 = 0; | ||||||
|  | 
 | ||||||
|  |         >global_line = get_line(module); | ||||||
|  |         >global_column = get_line(module); | ||||||
|  | 
 | ||||||
|  |         if (consume_character_if_match(module, left_bracket)) | ||||||
|  |         { | ||||||
|  |             while (module.offset < module.content.length) | ||||||
|  |             { | ||||||
|  |                 >global_attribute_keyword_string = parse_identifier(module); | ||||||
|  |                 >global_attribute_keyword_s2e = #string_to_enum(GlobalAttributeKeyword, global_attribute_keyword_string); | ||||||
|  |                 if (!global_attribute_keyword_s2e.is_valid) | ||||||
|  |                 { | ||||||
|  |                     report_error(); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 >global_attribute_keyword = global_attribute_keyword_s2e.enum_value; | ||||||
|  |                 switch (global_attribute_keyword) | ||||||
|  |                 { | ||||||
|  |                     .export => | ||||||
|  |                     { | ||||||
|  |                         is_export = 1; | ||||||
|  |                     }, | ||||||
|  |                     .extern => | ||||||
|  |                     { | ||||||
|  |                         is_extern = 1; | ||||||
|  |                     }, | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if (consume_character_if_match(module, right_bracket)) | ||||||
|  |                 { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     report_error(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             skip_space(module); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         >global_name = parse_identifier(module); | ||||||
|  | 
 | ||||||
|  |         >last_global = module.first_global; | ||||||
|  | 
 | ||||||
|  |         while (last_global) | ||||||
|  |         { | ||||||
|  |             if (string_equal(global_name, last_global.variable.name)) | ||||||
|  |             { | ||||||
|  |                 report_error(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (!last_global.next) | ||||||
|  |             { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             last_global = last_global.next; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         >type_it = module.first_type; | ||||||
|  |         >forward_declaration: &Type = 0; | ||||||
|  | 
 | ||||||
|  |         while (type_it) | ||||||
|  |         { | ||||||
|  |             if (string_equal(global_name, type_it.name)) | ||||||
|  |             { | ||||||
|  |                 if (type_it.id == .forward_declaration) | ||||||
|  |                 { | ||||||
|  |                     forward_declaration = type_it; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     report_error(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (!type_it.next) | ||||||
|  |             { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             type_it = type_it.next; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         >global_type: &Type = 0; | ||||||
|  | 
 | ||||||
|  |         if (consume_character_if_match(module, ':')) | ||||||
|  |         { | ||||||
|  |             skip_space(module); | ||||||
|  | 
 | ||||||
|  |             global_type = parse_type(module, scope); | ||||||
|  | 
 | ||||||
|  |             skip_space(module); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         expect_character(module, '='); | ||||||
|  | 
 | ||||||
|  |         skip_space(module); | ||||||
|  | 
 | ||||||
|  |         >is_global_keyword: u1 = 0; | ||||||
|  | 
 | ||||||
|  |         if (is_identifier_start(module.content[module.offset])) | ||||||
|  |         { | ||||||
|  |             >checkpoint = get_checkpoint(module); | ||||||
|  |             >global_keyword_string = parse_identifier(module); | ||||||
|  |             skip_space(module); | ||||||
|  | 
 | ||||||
|  |             >global_keyword_s2e = #string_to_enum(GlobalKeyword, global_keyword_string); | ||||||
|  | 
 | ||||||
|  |             is_global_keyword = global_keyword_s2e.is_valid; | ||||||
|  | 
 | ||||||
|  |             if (is_global_keyword) | ||||||
|  |             { | ||||||
|  |                 >global_keyword = global_keyword_s2e.enum_value; | ||||||
|  | 
 | ||||||
|  |                 switch (global_keyword) | ||||||
|  |                 { | ||||||
|  |                     .bits => | ||||||
|  |                     { | ||||||
|  |                         #trap(); | ||||||
|  |                     }, | ||||||
|  |                     .enum => | ||||||
|  |                     { | ||||||
|  |                         #trap(); | ||||||
|  |                     }, | ||||||
|  |                     .fn => | ||||||
|  |                     { | ||||||
|  |                         #trap(); | ||||||
|  |                     }, | ||||||
|  |                     .macro => | ||||||
|  |                     { | ||||||
|  |                         #trap(); | ||||||
|  |                     }, | ||||||
|  |                     .struct => | ||||||
|  |                     { | ||||||
|  |                         #trap(); | ||||||
|  |                     }, | ||||||
|  |                     .typealias => | ||||||
|  |                     { | ||||||
|  |                         #trap(); | ||||||
|  |                     }, | ||||||
|  |                     .union => | ||||||
|  |                     { | ||||||
|  |                         #trap(); | ||||||
|  |                     }, | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 set_checkpoint(module, checkpoint); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!is_global_keyword) | ||||||
|  |         { | ||||||
|  |             #trap(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| emit = fn (module: &Module) void | emit = fn (module: &Module) void | ||||||
| @ -908,6 +1246,9 @@ compile = fn (arena: &Arena, options: CompileOptions) void | |||||||
|         .offset = 0, |         .offset = 0, | ||||||
|         .line_offset = 0, |         .line_offset = 0, | ||||||
|         .line_character_offset = 0, |         .line_character_offset = 0, | ||||||
|  |         .scope = { | ||||||
|  |             zero, | ||||||
|  |         }, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     parse(&module); |     parse(&module); | ||||||
|  | |||||||
| @ -307,7 +307,7 @@ global_variable String names[] = | |||||||
|     string_literal("generic_pointer_array"), |     string_literal("generic_pointer_array"), | ||||||
|      |      | ||||||
|     string_literal("self_referential_struct"), // TODO
 |     string_literal("self_referential_struct"), // TODO
 | ||||||
|     // string_literal("forward_declared_type"),
 |     string_literal("forward_declared_type"), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void entry_point(Slice<const char*> arguments, Slice<char* const> environment) | void entry_point(Slice<const char*> arguments, Slice<char* const> environment) | ||||||
|  | |||||||
| @ -17,6 +17,8 @@ fn void analyze_block(Module* module, Block* block); | |||||||
| fn void emit_local_storage(Module* module, Variable* variable); | fn void emit_local_storage(Module* module, Variable* variable); | ||||||
| fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type, Value* right); | fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type, Value* right); | ||||||
| fn void emit_macro_instantiation(Module* module, Value* value); | fn void emit_macro_instantiation(Module* module, Value* value); | ||||||
|  | fn void emit_value(Module* module, Value* value, TypeKind type_kind); | ||||||
|  | fn void analyze_value(Module* module, Value* value, Type* expected_type, TypeKind type_kind); | ||||||
| 
 | 
 | ||||||
| fn void emit_block(Module* module, LLVMBasicBlockRef basic_block) | fn void emit_block(Module* module, LLVMBasicBlockRef basic_block) | ||||||
| { | { | ||||||
| @ -42,6 +44,24 @@ fn void emit_block(Module* module, LLVMBasicBlockRef basic_block) | |||||||
|     LLVMPositionBuilderAtEnd(module->llvm.builder, basic_block); |     LLVMPositionBuilderAtEnd(module->llvm.builder, basic_block); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn LLVMValueRef emit_condition(Module* module, Value* condition_value) | ||||||
|  | { | ||||||
|  |     auto condition_llvm_value = condition_value->llvm; | ||||||
|  |     auto condition_type = condition_value->type; | ||||||
|  |     assert(condition_type); | ||||||
|  |     assert(condition_llvm_value); | ||||||
|  | 
 | ||||||
|  |     assert(condition_type->id == TypeId::integer || condition_type->id == TypeId::pointer); | ||||||
|  |     if (!(condition_type->id == TypeId::integer && condition_type->integer.bit_count == 1)) | ||||||
|  |     { | ||||||
|  |         condition_llvm_value = LLVMBuildICmp(module->llvm.builder, LLVMIntNE, condition_llvm_value, LLVMConstNull(condition_type->llvm.abi), ""); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     assert(condition_llvm_value); | ||||||
|  | 
 | ||||||
|  |     return condition_llvm_value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn LLVMValueRef emit_intrinsic_call(Module* module, IntrinsicIndex index, Slice<LLVMTypeRef> argument_types, Slice<LLVMValueRef> argument_values) | fn LLVMValueRef emit_intrinsic_call(Module* module, IntrinsicIndex index, Slice<LLVMTypeRef> argument_types, Slice<LLVMValueRef> argument_values) | ||||||
| { | { | ||||||
|     auto intrinsic_id = module->llvm.intrinsic_table[(backing_type(IntrinsicIndex))index]; |     auto intrinsic_id = module->llvm.intrinsic_table[(backing_type(IntrinsicIndex))index]; | ||||||
| @ -216,8 +236,6 @@ fn void dump_module(Module* module) | |||||||
|     print(llvm_module_to_string(module->llvm.module)); |     print(llvm_module_to_string(module->llvm.module)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn void emit_value(Module* module, Value* value, TypeKind type_kind); |  | ||||||
| 
 |  | ||||||
| fn LLVMCallConv llvm_calling_convention(CallingConvention calling_convention) | fn LLVMCallConv llvm_calling_convention(CallingConvention calling_convention) | ||||||
| { | { | ||||||
|     LLVMCallConv cc; |     LLVMCallConv cc; | ||||||
| @ -918,11 +936,8 @@ fn void resolve_type_in_place_debug(Module* module, Type* type) | |||||||
|                 case TypeId::pointer: |                 case TypeId::pointer: | ||||||
|                     { |                     { | ||||||
|                         resolve_type_in_place_debug(module, type->pointer.element_type); |                         resolve_type_in_place_debug(module, type->pointer.element_type); | ||||||
|                         if (type->llvm.debug) |                         result = type->llvm.debug; | ||||||
|                         { |                         if (!result) | ||||||
|                             trap(); |  | ||||||
|                         } |  | ||||||
|                         else |  | ||||||
|                         { |                         { | ||||||
|                             result = LLVMDIBuilderCreatePointerType(module->llvm.di_builder, type->pointer.element_type->llvm.debug, 64, 64, 0, (char*)type->name.pointer, type->name.length); |                             result = LLVMDIBuilderCreatePointerType(module->llvm.di_builder, type->pointer.element_type->llvm.debug, 64, 64, 0, (char*)type->name.pointer, type->name.length); | ||||||
|                         } |                         } | ||||||
| @ -3118,6 +3133,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type) | |||||||
| 
 | 
 | ||||||
|                             if (!result_field) |                             if (!result_field) | ||||||
|                             { |                             { | ||||||
|  |                                 // Field not found
 | ||||||
|                                 report_error(); |                                 report_error(); | ||||||
|                             } |                             } | ||||||
| 
 | 
 | ||||||
| @ -6286,41 +6302,10 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind) | |||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     auto* left = value->binary.left; |                     auto* left = value->binary.left; | ||||||
|                     if (left->llvm) |  | ||||||
|                     { |  | ||||||
|                         assert(false); // TODO: check if this if is really necessary
 |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         emit_value(module, left, TypeKind::abi); |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     auto left_llvm = left->llvm; |  | ||||||
| 
 |  | ||||||
|                     LLVMValueRef left_condition = 0; |  | ||||||
| 
 |  | ||||||
|                     switch (left->type->id) |  | ||||||
|                     { |  | ||||||
|                         case TypeId::integer: |  | ||||||
|                             { |  | ||||||
|                                 switch (left->type->integer.bit_count) |  | ||||||
|                                 { |  | ||||||
|                                     case 1: |  | ||||||
|                                         left_condition = left_llvm; |  | ||||||
|                                         break; |  | ||||||
|                                     default: trap(); |  | ||||||
|                                 } |  | ||||||
|                             } break; |  | ||||||
|                         default: trap(); |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     assert(left_condition); |  | ||||||
| 
 | 
 | ||||||
|                     auto llvm_function = module->current_function->variable.storage->llvm; |                     auto llvm_function = module->current_function->variable.storage->llvm; | ||||||
|                     assert(llvm_function); |                     assert(llvm_function); | ||||||
| 
 | 
 | ||||||
|                     auto current_basic_block = LLVMGetInsertBlock(module->llvm.builder); |  | ||||||
|                      |  | ||||||
|                     auto* right_block = llvm_context_create_basic_block(module->llvm.context, string_literal("shortcircuit.right"), llvm_function); |                     auto* right_block = llvm_context_create_basic_block(module->llvm.context, string_literal("shortcircuit.right"), llvm_function); | ||||||
|                     auto* end_block = llvm_context_create_basic_block(module->llvm.context, string_literal("shortcircuit.end"), llvm_function); |                     auto* end_block = llvm_context_create_basic_block(module->llvm.context, string_literal("shortcircuit.end"), llvm_function); | ||||||
| 
 | 
 | ||||||
| @ -6339,7 +6324,11 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind) | |||||||
|                             break; |                             break; | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     LLVMBuildCondBr(module->llvm.builder, left_condition, true_block, false_block); |                     emit_value(module, left, TypeKind::abi); | ||||||
|  |                     auto llvm_condition = emit_condition(module, left); | ||||||
|  |                     auto current_basic_block = LLVMGetInsertBlock(module->llvm.builder); | ||||||
|  | 
 | ||||||
|  |                     LLVMBuildCondBr(module->llvm.builder, llvm_condition, true_block, false_block); | ||||||
| 
 | 
 | ||||||
|                     LLVMPositionBuilderAtEnd(module->llvm.builder, right_block); |                     LLVMPositionBuilderAtEnd(module->llvm.builder, right_block); | ||||||
| 
 | 
 | ||||||
| @ -7104,19 +7093,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3 | |||||||
| 
 | 
 | ||||||
|                 auto condition = statement->if_st.condition; |                 auto condition = statement->if_st.condition; | ||||||
|                 analyze_value(module, condition, 0, TypeKind::abi); |                 analyze_value(module, condition, 0, TypeKind::abi); | ||||||
|                 auto condition_type = condition->type; |                 auto llvm_condition = emit_condition(module, statement->if_st.condition); | ||||||
| 
 |  | ||||||
|                 LLVMValueRef llvm_condition = 0; |  | ||||||
|                 assert(condition_type->id == TypeId::integer || condition_type->id == TypeId::pointer); |  | ||||||
| 
 |  | ||||||
|                 llvm_condition = condition->llvm; |  | ||||||
| 
 |  | ||||||
|                 if (!(condition_type->id == TypeId::integer && condition_type->integer.bit_count == 1)) |  | ||||||
|                 { |  | ||||||
|                     llvm_condition = LLVMBuildICmp(module->llvm.builder, LLVMIntNE, llvm_condition, LLVMConstNull(condition_type->llvm.abi), ""); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 assert(llvm_condition); |  | ||||||
| 
 | 
 | ||||||
|                 LLVMBuildCondBr(module->llvm.builder, llvm_condition, taken_block, not_taken_block); |                 LLVMBuildCondBr(module->llvm.builder, llvm_condition, taken_block, not_taken_block); | ||||||
|                 LLVMPositionBuilderAtEnd(module->llvm.builder, taken_block); |                 LLVMPositionBuilderAtEnd(module->llvm.builder, taken_block); | ||||||
| @ -7187,22 +7164,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3 | |||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     analyze_value(module, condition, 0, TypeKind::abi); |                     analyze_value(module, condition, 0, TypeKind::abi); | ||||||
| 
 |                     auto llvm_condition = emit_condition(module, condition); | ||||||
|                     auto boolean = uint1(module); |  | ||||||
| 
 |  | ||||||
|                     LLVMValueRef llvm_condition = condition->llvm; |  | ||||||
|                     auto condition_type = condition->type; |  | ||||||
|                     if (condition_type != boolean) |  | ||||||
|                     { |  | ||||||
|                         switch (condition_type->id) |  | ||||||
|                         { |  | ||||||
|                             case TypeId::integer: |  | ||||||
|                                 { |  | ||||||
|                                     llvm_condition = LLVMBuildICmp(module->llvm.builder, LLVMIntNE, llvm_condition, LLVMConstNull(condition_type->llvm.abi), ""); |  | ||||||
|                                 } break; |  | ||||||
|                             default: unreachable(); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
| 
 | 
 | ||||||
|                     LLVMBuildCondBr(module->llvm.builder, llvm_condition, body_block, exit_block); |                     LLVMBuildCondBr(module->llvm.builder, llvm_condition, body_block, exit_block); | ||||||
|                 } |                 } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user