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