Compile the compiler
All checks were successful
CI / ci (RelWithDebInfo, ubuntu-latest) (pull_request) Successful in 5m18s
CI / ci (MinSizeRel, ubuntu-latest) (pull_request) Successful in 5m21s
CI / ci (Release, ubuntu-latest) (pull_request) Successful in 5m4s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 18m44s
All checks were successful
CI / ci (RelWithDebInfo, ubuntu-latest) (pull_request) Successful in 5m18s
CI / ci (MinSizeRel, ubuntu-latest) (pull_request) Successful in 5m21s
CI / ci (Release, ubuntu-latest) (pull_request) Successful in 5m4s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 18m44s
This commit is contained in:
parent
14f856b550
commit
74b9a2b0ff
605
src/compiler.bbb
605
src/compiler.bbb
@ -101,6 +101,29 @@ assert = macro (ok: u1) void
|
||||
}
|
||||
}
|
||||
|
||||
ArgumentBuilder = struct
|
||||
{
|
||||
buffer: [128]&u8,
|
||||
count: u64,
|
||||
}
|
||||
|
||||
add_argument = fn (builder: &ArgumentBuilder, argument: []u8) void
|
||||
{
|
||||
assert(argument.pointer[argument.length] == 0);
|
||||
>index = builder.count;
|
||||
assert(index < builder.buffer.length);
|
||||
builder.buffer[index] = argument.pointer;
|
||||
builder.count = index + 1;
|
||||
}
|
||||
|
||||
flush_arguments = fn (builder: &ArgumentBuilder) []&u8
|
||||
{
|
||||
>argument_count = builder.count;
|
||||
assert(argument_count < builder.buffer.length);
|
||||
builder.buffer[argument_count] = zero;
|
||||
return builder.buffer[..argument_count];
|
||||
}
|
||||
|
||||
align_forward = fn (value: u64, alignment: u64) u64
|
||||
{
|
||||
assert(alignment != 0);
|
||||
@ -154,6 +177,22 @@ string_equal = fn(a: []u8, b: []u8) u1
|
||||
return result;
|
||||
}
|
||||
|
||||
string_first_character = fn (string: []u8, character: u8) u64
|
||||
{
|
||||
>result = string_no_match;
|
||||
|
||||
for (i: 0..string.length)
|
||||
{
|
||||
if (character == string[i])
|
||||
{
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string_last_character = fn(string: []u8, character: u8) u64
|
||||
{
|
||||
>i = string.length;
|
||||
@ -1533,6 +1572,10 @@ receives_type = fn (value: &Value) u1
|
||||
|
||||
return receives_type(left) and receives_type(right);
|
||||
},
|
||||
.unary_type =>
|
||||
{
|
||||
return 1; // TODO: base on unary_type_id
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -1727,6 +1770,11 @@ get_byte_size = fn (type: &Type) u64
|
||||
>result = element_size * element_count;
|
||||
return result;
|
||||
},
|
||||
.alias =>
|
||||
{
|
||||
>result = get_byte_size(type.content.alias.type);
|
||||
return result;
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -1820,6 +1868,15 @@ get_bit_size = fn (type: &Type) u64
|
||||
>result = type.content.union.byte_size * 8;
|
||||
return result;
|
||||
},
|
||||
.enum_array =>
|
||||
{
|
||||
>enum_type = type.content.enum_array.enum_type;
|
||||
>element_type = type.content.enum_array.element_type;
|
||||
>element_bit_size = get_byte_size(element_type) * 8;
|
||||
assert(enum_type.id == .enum);
|
||||
>element_count = enum_type.content.enum.fields.length;
|
||||
return element_bit_size * element_count;
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -1876,6 +1933,10 @@ is_promotable_integer_type_for_abi = fn (type: &Type) u1
|
||||
>backing_type = type.content.enum.backing_type;
|
||||
return is_promotable_integer_type_for_abi(backing_type);
|
||||
},
|
||||
.pointer =>
|
||||
{
|
||||
return 0;
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -1927,6 +1988,7 @@ ValueId = enum
|
||||
string_to_enum,
|
||||
macro_instantiation,
|
||||
field_parent_pointer,
|
||||
build_mode,
|
||||
}
|
||||
|
||||
ValueConstantInteger = struct
|
||||
@ -1998,6 +2060,7 @@ UnaryTypeId = enum
|
||||
{
|
||||
align_of,
|
||||
byte_size,
|
||||
enum_names,
|
||||
enum_values,
|
||||
integer_max,
|
||||
}
|
||||
@ -2295,6 +2358,22 @@ value_is_constant = fn (value: &Value) u1
|
||||
{
|
||||
return 1;
|
||||
},
|
||||
.unary_type =>
|
||||
{
|
||||
>unary_type_id = value.content.unary_type.id;
|
||||
switch (unary_type_id)
|
||||
{
|
||||
.align_of,
|
||||
.byte_size,
|
||||
.integer_max,
|
||||
=> { return 1; },
|
||||
else => { unreachable; },
|
||||
}
|
||||
},
|
||||
.build_mode =>
|
||||
{
|
||||
return 1;
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -2781,6 +2860,7 @@ llvm_create_global_variable = fn (module: &LLVMModule, type: &LLVMType, is_const
|
||||
[extern] LLVMConstNamedStruct = fn [cc(c)] (type: &LLVMType, constant_pointer: &&LLVMValue, constant_count: u32) &LLVMValue;
|
||||
[extern] LLVMConstStructInContext = fn [cc(c)] (context: &LLVMContext, constant_pointer: &&LLVMValue, constant_count: u32, packed: s32) &LLVMValue;
|
||||
|
||||
[extern] LLVMGetInstructionParent = fn [cc(c)] (value: &LLVMValue) &LLVMBasicBlock;
|
||||
[extern] LLVMInstructionEraseFromParent = fn [cc(c)] (value: &LLVMValue) void;
|
||||
[extern] LLVMGetOperand = fn [cc(c)] (value: &LLVMValue, index: u32) &LLVMValue;
|
||||
[extern] LLVMGetFirstUse = fn [cc(c)] (value: &LLVMValue) &LLVMUse;
|
||||
@ -2882,6 +2962,7 @@ Module = struct
|
||||
first_function_type: &Type,
|
||||
|
||||
va_list_type: &Type,
|
||||
build_mode_enum: &Type,
|
||||
|
||||
void_value: &Value,
|
||||
first_global: &Global,
|
||||
@ -3761,6 +3842,7 @@ TypeKeyword = enum
|
||||
void,
|
||||
noreturn,
|
||||
enum_array,
|
||||
fn,
|
||||
}
|
||||
|
||||
type_is_slice = fn (type: &Type) u1
|
||||
@ -4027,6 +4109,7 @@ ValueIntrinsic = enum
|
||||
byte_size,
|
||||
enum_from_int,
|
||||
enum_name,
|
||||
enum_names,
|
||||
enum_values,
|
||||
extend,
|
||||
field_parent_pointer,
|
||||
@ -4545,6 +4628,15 @@ parse_type = fn (module: &Module, scope: &Scope) &Type
|
||||
>enum_array_type = get_enum_array_type(module, enum_type, element_type);
|
||||
return enum_array_type;
|
||||
},
|
||||
.fn =>
|
||||
{
|
||||
skip_space(module);
|
||||
>mandate_argument_names: u1 = 0;
|
||||
>function_header = parse_function_header(module, scope, mandate_argument_names);
|
||||
>result = function_header.type;
|
||||
return result;
|
||||
},
|
||||
else => { unreachable; },
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -5556,6 +5648,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
|
||||
},
|
||||
.align_of,
|
||||
.byte_size,
|
||||
.enum_names,
|
||||
.enum_values,
|
||||
.integer_max,
|
||||
=>
|
||||
@ -5573,6 +5666,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
|
||||
{
|
||||
.align_of => { id = .align_of; },
|
||||
.byte_size => { id = .byte_size; },
|
||||
.enum_names => { id = .enum_names; },
|
||||
.enum_values => { id = .enum_values; },
|
||||
.integer_max => { id = .integer_max; },
|
||||
else => { unreachable; },
|
||||
@ -5751,7 +5845,10 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
|
||||
},
|
||||
.build_mode =>
|
||||
{
|
||||
#trap();
|
||||
result.& = {
|
||||
.id = .build_mode,
|
||||
zero,
|
||||
};
|
||||
},
|
||||
.field_parent_pointer =>
|
||||
{
|
||||
@ -5785,7 +5882,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
|
||||
.left_bracket =>
|
||||
{
|
||||
>element_count: u64 = 0;
|
||||
>value_buffer: [64]&Value = undefined;
|
||||
>value_buffer: [128]&Value = undefined;
|
||||
|
||||
skip_space(module);
|
||||
|
||||
@ -5826,6 +5923,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
|
||||
}
|
||||
|
||||
>value = parse_value(module, scope, zero);
|
||||
assert(element_count < value_buffer.length);
|
||||
value_buffer[element_count] = value;
|
||||
element_count += 1;
|
||||
|
||||
@ -5851,7 +5949,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
|
||||
},
|
||||
.dot =>
|
||||
{
|
||||
>identifier = parse_identifier(module);
|
||||
>identifier = parse_name(module);
|
||||
result = new_value(module);
|
||||
result.& = {
|
||||
.content = {
|
||||
@ -6565,7 +6663,12 @@ parse_statement = fn (module: &Module, scope: &Scope) &Statement
|
||||
},
|
||||
.return =>
|
||||
{
|
||||
>return_value = parse_value(module, scope, zero);
|
||||
>return_value: &Value = zero;
|
||||
// TODO: make this better
|
||||
if (module.content[module.offset] != ';')
|
||||
{
|
||||
return_value = parse_value(module, scope, zero);
|
||||
}
|
||||
statement.content.return = return_value;
|
||||
statement.id = .return;
|
||||
},
|
||||
@ -8690,19 +8793,16 @@ get_member_at_offset = fn (struct_type: &Type, offset: u64) &Field
|
||||
>byte_size = get_byte_size(struct_type);
|
||||
if (byte_size > offset)
|
||||
{
|
||||
>offset_it: u64 = 0;
|
||||
>fields = struct_type.content.struct.fields;
|
||||
|
||||
for (&field: fields)
|
||||
{
|
||||
if (offset_it > offset)
|
||||
if (field.offset > offset)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = field;
|
||||
assert(offset_it == field.offset);
|
||||
offset_it = align_forward(offset_it + get_byte_size(field.type), #extend(get_byte_alignment(field.type)));
|
||||
}
|
||||
|
||||
assert(result != zero);
|
||||
@ -8922,7 +9022,11 @@ abi_system_v_get_indirect_result = fn (module: &Module, type: &Type, free_gpr: u
|
||||
{
|
||||
if (is_promotable_integer_type_for_abi(type))
|
||||
{
|
||||
#trap();
|
||||
return abi_system_v_get_extend({
|
||||
.semantic_type = type,
|
||||
.sign = type_is_signed(type),
|
||||
zero,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -9919,6 +10023,7 @@ resolve_type = fn (module: &Module, type: &Type) &Type
|
||||
.void,
|
||||
.noreturn,
|
||||
.integer,
|
||||
.enum,
|
||||
=>
|
||||
{
|
||||
result = type;
|
||||
@ -10039,6 +10144,29 @@ clone_value = fn (module: &Module, scope: &Scope, old_value: &Value) &Value
|
||||
},
|
||||
};
|
||||
},
|
||||
.call =>
|
||||
{
|
||||
>callable = clone_value(module, scope, old_value.content.call.callable);
|
||||
>old_arguments = old_value.content.call.arguments;
|
||||
>arguments = arena_allocate_slice[&Value](module.arena, old_arguments.length);
|
||||
|
||||
for (i: 0..arguments.length)
|
||||
{
|
||||
arguments[i] = clone_value(module, scope, old_arguments[i]);
|
||||
}
|
||||
|
||||
result.content = {
|
||||
.call = {
|
||||
.callable = callable,
|
||||
.arguments = arguments,
|
||||
.function_type = old_value.content.call.function_type,
|
||||
},
|
||||
};
|
||||
},
|
||||
.unary_type =>
|
||||
{
|
||||
result.content = old_value.content;
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -10185,6 +10313,47 @@ copy_block = fn (module: &Module, parent_scope: &Scope, copy: BlockCopy) void
|
||||
}
|
||||
}
|
||||
|
||||
get_build_mode_enum = fn (module: &Module) &Type
|
||||
{
|
||||
>result = module.build_mode_enum;
|
||||
|
||||
if (!result)
|
||||
{
|
||||
>enum_names = #enum_names(BuildMode);
|
||||
>enum_fields = arena_allocate_slice[EnumField](module.arena, enum_names.length);
|
||||
|
||||
>field_value: u64 = 0;
|
||||
for (enum_name: enum_names)
|
||||
{
|
||||
enum_fields[field_value] = {
|
||||
.name = enum_name,
|
||||
.value = field_value,
|
||||
};
|
||||
|
||||
field_value += 1;
|
||||
}
|
||||
|
||||
>backing_type = integer_type(module, { .bit_count = enum_names.length, .signed = 0 });
|
||||
|
||||
result = new_type(module, {
|
||||
.content = {
|
||||
.enum = {
|
||||
.fields = enum_fields,
|
||||
.backing_type = backing_type,
|
||||
zero,
|
||||
},
|
||||
},
|
||||
.id = .enum,
|
||||
.name = "BuildMode",
|
||||
.scope = &module.scope,
|
||||
zero,
|
||||
});
|
||||
}
|
||||
|
||||
assert(result != zero);
|
||||
return result;
|
||||
}
|
||||
|
||||
analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysis: TypeAnalysis) void
|
||||
{
|
||||
assert(!value.type);
|
||||
@ -10629,7 +10798,30 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi
|
||||
},
|
||||
.enum_from_int =>
|
||||
{
|
||||
#trap();
|
||||
if (!expected_type)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
if (expected_type.id != .enum)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
analyze_type(module, unary_value, expected_type.content.enum.backing_type, { .must_be_constant = analysis.must_be_constant, zero });
|
||||
|
||||
>unary_value_type = unary_value.type;
|
||||
if (unary_value_type.id != .integer)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
if (get_bit_size(unary_value_type) != get_bit_size(expected_type))
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
value_type = expected_type;
|
||||
},
|
||||
// Generic case
|
||||
.minus,
|
||||
@ -10695,12 +10887,49 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi
|
||||
.unary_type =>
|
||||
{
|
||||
>unary_type_id = value.content.unary_type.id;
|
||||
>unary_type = value.content.unary_type.type; // TODO: call resolve_type
|
||||
>unary_type = resolve_type(module, value.content.unary_type.type);
|
||||
value.content.unary_type.type = unary_type;
|
||||
|
||||
if (unary_type_id == .enum_values)
|
||||
{
|
||||
#trap();
|
||||
>element_type = unary_type;
|
||||
|
||||
if (element_type.id != .enum)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
>fields = element_type.content.enum.fields;
|
||||
|
||||
>element_count = fields.length;
|
||||
|
||||
if (element_count == 0)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
>array_type = get_array_type(module, element_type, element_count);
|
||||
|
||||
switch (value.kind)
|
||||
{
|
||||
.right =>
|
||||
{
|
||||
value_type = array_type;
|
||||
},
|
||||
.left =>
|
||||
{
|
||||
value_type = get_pointer_type(module, array_type);
|
||||
},
|
||||
}
|
||||
}
|
||||
else if (unary_type_id == .enum_names)
|
||||
{
|
||||
if (unary_type.id != .enum)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
value_type = get_slice_type(module, get_slice_type(module, uint8(module)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -10736,7 +10965,7 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi
|
||||
|
||||
value = integer_max_value(unary_type.content.integer.bit_count, unary_type.content.integer.signed);
|
||||
},
|
||||
.enum_values => { unreachable; },
|
||||
else => { unreachable; },
|
||||
}
|
||||
|
||||
if (value > max_value)
|
||||
@ -11694,13 +11923,13 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi
|
||||
|
||||
>return_value_alloca = create_alloca(module, {
|
||||
.type = enum_type,
|
||||
.name = "retval",
|
||||
.name = "return_value",
|
||||
zero,
|
||||
});
|
||||
|
||||
>return_boolean_alloca = create_alloca(module, {
|
||||
.type = u8_type,
|
||||
.name = "retbool",
|
||||
.name = "return_bool",
|
||||
zero,
|
||||
});
|
||||
|
||||
@ -12163,6 +12392,16 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi
|
||||
>pointer_to_field = get_pointer_type(module, field_type);
|
||||
analyze_type(module, field_pointer, pointer_to_field, zero);
|
||||
},
|
||||
.build_mode =>
|
||||
{
|
||||
value_type = get_build_mode_enum(module);
|
||||
typecheck(module, expected_type, value_type);
|
||||
},
|
||||
.has_debug_info =>
|
||||
{
|
||||
value_type = uint1(module);
|
||||
typecheck(module, expected_type, value_type);
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -12988,7 +13227,13 @@ emit_call = fn (module: &Module, value: &Value, left_llvm: &LLVMValue, left_type
|
||||
}
|
||||
.zero =>
|
||||
{
|
||||
#trap();
|
||||
for (i: 0..coerce_fields.length)
|
||||
{
|
||||
>field = &coerce_fields[i];
|
||||
>field_type = field.type;
|
||||
llvm_abi_argument_value_buffer[abi_argument_count] = LLVMConstNull(field_type.llvm.abi);
|
||||
abi_argument_count += 1;
|
||||
}
|
||||
},
|
||||
else =>
|
||||
{
|
||||
@ -13320,7 +13565,14 @@ emit_call = fn (module: &Module, value: &Value, left_llvm: &LLVMValue, left_type
|
||||
{
|
||||
switch (value.kind)
|
||||
{
|
||||
.right => { #trap(); },
|
||||
.right =>
|
||||
{
|
||||
return create_load(module, {
|
||||
.type = destination_type,
|
||||
.pointer = destination_pointer,
|
||||
zero,
|
||||
});
|
||||
},
|
||||
.left => { #trap(); },
|
||||
}
|
||||
}
|
||||
@ -13336,7 +13588,8 @@ emit_call = fn (module: &Module, value: &Value, left_llvm: &LLVMValue, left_type
|
||||
|
||||
emit_constant_array = fn (module: &Module, elements: []&Value, element_type: &Type) &LLVMValue
|
||||
{
|
||||
>value_buffer: [64]&LLVMValue = undefined;
|
||||
>value_buffer: [128]&LLVMValue = undefined;
|
||||
assert(elements.length <= value_buffer.length);
|
||||
|
||||
resolve_type_in_place(module, element_type);
|
||||
|
||||
@ -13455,7 +13708,14 @@ emit_field_access = fn (module: &Module, value: &Value, left_llvm: &LLVMValue, l
|
||||
|
||||
if (left_llvm)
|
||||
{
|
||||
#trap();
|
||||
assert(get_evaluation_kind(field_access.type) == .aggregate);
|
||||
>alignment = get_byte_alignment(field_access.type);
|
||||
|
||||
>u64_type = uint64(module);
|
||||
resolve_type_in_place(module, u64_type);
|
||||
|
||||
LLVMBuildMemCpy(module.llvm.builder, left_llvm, alignment, gep, alignment, LLVMConstInt(u64_type.llvm.abi, get_byte_size(field_access.type), 0));
|
||||
return gep;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -14019,7 +14279,7 @@ emit_string_literal = fn (module: &Module, value: &Value) [2]&LLVMValue
|
||||
>thread_local_mode: LLVMThreadLocalMode = .none;
|
||||
>externally_initialized: u1 = 0;
|
||||
>alignment: u32 = 1;
|
||||
>global = llvm_create_global_variable(module.llvm.module, string_type, is_constant, .internal, constant_string, "conststring", thread_local_mode, externally_initialized, alignment, .global);
|
||||
>global = llvm_create_global_variable(module.llvm.module, string_type, is_constant, .internal, constant_string, "const.string", thread_local_mode, externally_initialized, alignment, .global);
|
||||
return [ global, LLVMConstInt(uint64(module).llvm.abi, length, 0) ];
|
||||
}
|
||||
|
||||
@ -14369,7 +14629,7 @@ emit_value = fn (module: &Module, value: &Value, type_kind: TypeKind, expect_con
|
||||
|
||||
if (type_kind == .memory)
|
||||
{
|
||||
#trap();
|
||||
llvm_value = memory_to_abi(module, llvm_value, boolean_type);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -14545,6 +14805,10 @@ emit_value = fn (module: &Module, value: &Value, type_kind: TypeKind, expect_con
|
||||
>values: [_]&LLVMValue = [ llvm_unary_value, zero_is_poison ];
|
||||
llvm_value = emit_intrinsic_call(module, intrinsic_index, types[..], values[..]);
|
||||
},
|
||||
.enum_from_int =>
|
||||
{
|
||||
llvm_value = llvm_unary_value;
|
||||
},
|
||||
else => { #trap(); },
|
||||
}
|
||||
},
|
||||
@ -14636,8 +14900,41 @@ emit_value = fn (module: &Module, value: &Value, type_kind: TypeKind, expect_con
|
||||
},
|
||||
.enum_values =>
|
||||
{
|
||||
#trap();
|
||||
assert(type_kind == .memory);
|
||||
assert(unary_type.id == .enum);
|
||||
|
||||
>buffer: [64]&LLVMValue = undefined;
|
||||
>fields = unary_type.content.enum.fields;
|
||||
assert(fields.length <= buffer.length);
|
||||
|
||||
>llvm_enum_type = unary_type.llvm.memory;
|
||||
|
||||
for (i: 0..fields.length)
|
||||
{
|
||||
buffer[i] = LLVMConstInt(llvm_enum_type, fields[i].value, 0);
|
||||
}
|
||||
|
||||
>array_value = LLVMConstArray2(llvm_enum_type, &buffer[0], fields.length);
|
||||
|
||||
switch (value.kind)
|
||||
{
|
||||
.right =>
|
||||
{
|
||||
llvm_value = array_value;
|
||||
},
|
||||
.left =>
|
||||
{
|
||||
assert(resolved_value_type.id == .pointer);
|
||||
>array_type = resolved_value_type.content.pointer.element_type;
|
||||
assert(array_type.id == .array);
|
||||
resolve_type_in_place(module, array_type);
|
||||
>alignment = get_byte_alignment(resolved_value_type);
|
||||
>value_array_variable = llvm_create_global_variable(module.llvm.module, array_type.llvm.memory, 1, .internal, array_value, "enum.values", .none, 0, alignment, .global);
|
||||
llvm_value = value_array_variable;
|
||||
},
|
||||
}
|
||||
},
|
||||
else => { unreachable; },
|
||||
}
|
||||
},
|
||||
.call =>
|
||||
@ -14909,6 +15206,7 @@ emit_value = fn (module: &Module, value: &Value, type_kind: TypeKind, expect_con
|
||||
|
||||
>alloca = create_alloca(module, {
|
||||
.type = aggregate_type,
|
||||
.name = "",
|
||||
zero,
|
||||
});
|
||||
|
||||
@ -15047,7 +15345,33 @@ emit_value = fn (module: &Module, value: &Value, type_kind: TypeKind, expect_con
|
||||
}
|
||||
else
|
||||
{
|
||||
#trap();
|
||||
llvm_value = LLVMConstNull(abi_type);
|
||||
|
||||
for (&initialization_element: elements)
|
||||
{
|
||||
>value = initialization_element.value;
|
||||
>name = initialization_element.name;
|
||||
|
||||
>result_field: &Field = zero;
|
||||
|
||||
for (&field: fields)
|
||||
{
|
||||
if (string_equal(name, field.name))
|
||||
{
|
||||
result_field = field;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(result_field != zero);
|
||||
|
||||
emit_value(module, value, .memory, must_be_constant);
|
||||
|
||||
>extended = LLVMBuildZExt(module.llvm.builder, value.llvm, abi_type, "");
|
||||
>shl = LLVMBuildShl(module.llvm.builder, extended, LLVMConstInt(abi_type, result_field.offset, 0), "");
|
||||
>or_value = LLVMBuildOr(module.llvm.builder, llvm_value, shl, "");
|
||||
llvm_value = or_value;
|
||||
}
|
||||
}
|
||||
},
|
||||
.enum_array =>
|
||||
@ -15222,6 +15546,18 @@ emit_value = fn (module: &Module, value: &Value, type_kind: TypeKind, expect_con
|
||||
},
|
||||
}
|
||||
},
|
||||
.undefined =>
|
||||
{
|
||||
llvm_value = LLVMGetPoison(get_llvm_type(resolved_value_type, type_kind));
|
||||
},
|
||||
.build_mode =>
|
||||
{
|
||||
llvm_value = LLVMConstInt(get_llvm_type(resolved_value_type.content.enum.backing_type, type_kind), #extend(#int_from_enum(module.build_mode)), 0);
|
||||
},
|
||||
.has_debug_info =>
|
||||
{
|
||||
llvm_value = LLVMConstInt(get_llvm_type(resolved_value_type, type_kind), #extend(module.has_debug_info), 0);
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -15295,11 +15631,11 @@ emit_assignment = fn (module: &Module, left_llvm: &LLVMValue, left_type: &Type,
|
||||
>element_type = resolved_value_type.content.array.element_type;
|
||||
>element_count = resolved_value_type.content.array.element_count;
|
||||
|
||||
if (right.content.array_initialization.is_constant)
|
||||
>is_constant = right.content.array_initialization.is_constant;
|
||||
if (is_constant)
|
||||
{
|
||||
emit_value(module, right, .memory, 0);
|
||||
|
||||
>is_constant: u1 = 1;
|
||||
>linkage: LLVMLinkage = .internal;
|
||||
>initial_value = right.llvm;
|
||||
>thread_local_mode: LLVMThreadLocalMode = .none;
|
||||
@ -15314,7 +15650,20 @@ emit_assignment = fn (module: &Module, left_llvm: &LLVMValue, left_type: &Type,
|
||||
}
|
||||
else
|
||||
{
|
||||
#trap();
|
||||
>u64_zero = LLVMConstNull(u64_type.llvm.abi);
|
||||
>pointer_to_element_type = get_pointer_type(module, element_type);
|
||||
|
||||
for (i: 0..values.length)
|
||||
{
|
||||
>alloca_gep = create_gep(module, {
|
||||
.type = resolved_value_type.llvm.memory,
|
||||
.pointer = left_llvm,
|
||||
.indices = [ u64_zero, LLVMConstInt(u64_type.llvm.abi, i, 0) ][..],
|
||||
zero,
|
||||
});
|
||||
|
||||
emit_assignment(module, alloca_gep, pointer_to_element_type, values[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
.string_literal =>
|
||||
@ -15554,13 +15903,11 @@ emit_assignment = fn (module: &Module, left_llvm: &LLVMValue, left_type: &Type,
|
||||
{
|
||||
// TODO: something
|
||||
},
|
||||
.select =>
|
||||
.unary,
|
||||
.array_expression,
|
||||
.select,
|
||||
=>
|
||||
{
|
||||
if (!type_is_slice(resolved_value_type))
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
emit_value(module, right, .memory, 0);
|
||||
|
||||
create_store(module, {
|
||||
@ -15581,6 +15928,43 @@ emit_assignment = fn (module: &Module, left_llvm: &LLVMValue, left_type: &Type,
|
||||
|
||||
LLVMBuildMemCpy(module.llvm.builder, left_llvm, alignment, right.content.macro_instantiation.return_alloca, alignment, LLVMConstInt(u64_type.llvm.abi, size, 0));
|
||||
},
|
||||
.field_access =>
|
||||
{
|
||||
>value = emit_field_access(module, right, left_llvm, left_type, .memory);
|
||||
right.llvm = value;
|
||||
},
|
||||
.unary_type =>
|
||||
{
|
||||
>unary_type_id = right.content.unary_type.id;
|
||||
>unary_type = right.content.unary_type.type;
|
||||
|
||||
switch (unary_type_id)
|
||||
{
|
||||
.enum_names =>
|
||||
{
|
||||
assert(unary_type.id == .enum);
|
||||
|
||||
>global = get_enum_name_array_global(module, unary_type);
|
||||
|
||||
>u64_type = uint64(module);
|
||||
resolve_type_in_place(module, u64_type);
|
||||
|
||||
>slice_values: [_]&LLVMValue = [
|
||||
global.variable.storage.llvm,
|
||||
LLVMConstInt(u64_type.llvm.abi, unary_type.content.enum.fields.length, 0),
|
||||
];
|
||||
>slice = LLVMConstStructInContext(module.llvm.context, &slice_values[0], slice_values.length, 0);
|
||||
|
||||
create_store(module, {
|
||||
.source = slice,
|
||||
.destination = left_llvm,
|
||||
.type = resolved_value_type,
|
||||
zero,
|
||||
});
|
||||
},
|
||||
else => { unreachable; },
|
||||
}
|
||||
},
|
||||
else =>
|
||||
{
|
||||
#trap();
|
||||
@ -15939,7 +16323,7 @@ analyze_statement = fn (module: &Module, scope: &Scope, statement: &Statement) v
|
||||
.range =>
|
||||
{
|
||||
>start = value.content.range[0];
|
||||
>end = value.content.range[0];
|
||||
>end = value.content.range[1];
|
||||
|
||||
for (v: value.content.range)
|
||||
{
|
||||
@ -16627,29 +17011,6 @@ generate_object = fn (module: &LLVMModule, target_machine: &LLVMTargetMachine, o
|
||||
return result;
|
||||
}
|
||||
|
||||
ArgumentBuilder = struct
|
||||
{
|
||||
buffer: [128]&u8,
|
||||
count: u64,
|
||||
}
|
||||
|
||||
add_argument = fn (builder: &ArgumentBuilder, argument: []u8) void
|
||||
{
|
||||
assert(argument.pointer[argument.length] == 0);
|
||||
>index = builder.count;
|
||||
assert(index < builder.buffer.length);
|
||||
builder.buffer[index] = argument.pointer;
|
||||
builder.count = index + 1;
|
||||
}
|
||||
|
||||
flush_arguments = fn (builder: &ArgumentBuilder) []&u8
|
||||
{
|
||||
>argument_count = builder.count;
|
||||
assert(argument_count < builder.buffer.length);
|
||||
builder.buffer[argument_count] = zero;
|
||||
return builder.buffer[..argument_count];
|
||||
}
|
||||
|
||||
link = fn (module: &Module) void
|
||||
{
|
||||
>arena = module.arena;
|
||||
@ -17521,18 +17882,26 @@ emit = fn (module: &Module) void
|
||||
if (first_use)
|
||||
{
|
||||
>second_use = LLVMGetNextUse(first_use);
|
||||
>has_one_use = first_use != zero and first_use == zero;
|
||||
>has_one_use = first_use != zero and second_use == zero;
|
||||
|
||||
if (has_one_use)
|
||||
{
|
||||
user = LLVMGetUser(first_use);
|
||||
has_single_jump_to_return_block = LLVMIsABranchInst(user) != zero and? LLVMIsConditional(user) != 0 and? LLVMGetSuccessor(user, 0) == return_block;
|
||||
has_single_jump_to_return_block = LLVMIsABranchInst(user) != zero and? LLVMIsConditional(user) == 0 and? LLVMGetSuccessor(user, 0) == return_block;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_single_jump_to_return_block)
|
||||
{
|
||||
#trap();
|
||||
assert(LLVMGetBasicBlockParent(return_block) != zero);
|
||||
>new_return_block = LLVMGetInstructionParent(user);
|
||||
// Remove unconditional branch instruction to the return block
|
||||
LLVMInstructionEraseFromParent(user);
|
||||
assert(!LLVMGetFirstUse(#pointer_cast(return_block)));
|
||||
assert(!LLVMGetBasicBlockTerminator(return_block));
|
||||
assert(LLVMGetBasicBlockParent(return_block) != zero);
|
||||
LLVMPositionBuilderAtEnd(module.llvm.builder, new_return_block);
|
||||
LLVMDeleteBasicBlock(return_block);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -17550,7 +17919,7 @@ emit = fn (module: &Module) void
|
||||
>semantic_return_type = return_abi.semantic_type;
|
||||
if (semantic_return_type == noreturn_type(module) or function.content.function.attributes.naked)
|
||||
{
|
||||
#trap();
|
||||
LLVMBuildUnreachable(module.llvm.builder);
|
||||
}
|
||||
else if (semantic_return_type == void_type(module))
|
||||
{
|
||||
@ -17824,7 +18193,7 @@ compile = fn (arena: &Arena, options: CompileOptions) void
|
||||
emit(&module);
|
||||
}
|
||||
|
||||
compile_file = fn (arena: &Arena, compile_options: CompileFile) []u8
|
||||
compile_file = fn (arena: &Arena, compile_options: CompileFile, envp: &&u8) []u8
|
||||
{
|
||||
>relative_file_path = compile_options.relative_file_path;
|
||||
if (relative_file_path.length < 5)
|
||||
@ -17901,7 +18270,113 @@ compile_file = fn (arena: &Arena, compile_options: CompileFile) []u8
|
||||
|
||||
if (is_compiler)
|
||||
{
|
||||
#trap();
|
||||
>builder: ArgumentBuilder = zero;
|
||||
|
||||
add_argument(&builder, "/home/david/dev/llvm/install/llvm_20.1.3_x86_64-linux-Release/bin/llvm-config");
|
||||
add_argument(&builder, "--libdir");
|
||||
add_argument(&builder, "--libs");
|
||||
add_argument(&builder, "--system-libs");
|
||||
|
||||
>arguments = flush_arguments(&builder);
|
||||
|
||||
>llvm_config = os_execute(arena, arguments, envp, {
|
||||
.policies = [ .pipe, .ignore ],
|
||||
zero,
|
||||
});
|
||||
|
||||
>success = llvm_config.termination_kind == .exit and llvm_config.termination_code == 0;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
>stream = llvm_config.streams[0];
|
||||
|
||||
>line = string_first_character(stream, '\n');
|
||||
|
||||
if (line == string_no_match)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
library_directory = stream[..line];
|
||||
library_directories = { .pointer = &library_directory, .length = 1 };
|
||||
|
||||
stream = stream[line + 1..];
|
||||
|
||||
line = string_first_character(stream, '\n');
|
||||
if (line == string_no_match)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
>llvm_library_stream = stream[..line];
|
||||
|
||||
stream = stream[line + 1..];
|
||||
|
||||
>library_count: u64 = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
>space = string_first_character(llvm_library_stream, ' ');
|
||||
if (space == string_no_match)
|
||||
{
|
||||
>library_argument = llvm_library_stream;
|
||||
library_buffer[library_count] = library_argument[2..];
|
||||
library_count += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Omit the first two characters: "-l"
|
||||
>library_argument = llvm_library_stream[2..space];
|
||||
library_buffer[library_count] = library_argument;
|
||||
library_count += 1;
|
||||
llvm_library_stream = llvm_library_stream[space + 1..];
|
||||
}
|
||||
|
||||
line = string_first_character(stream, '\n');
|
||||
if (line == string_no_match)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
assert(line == stream.length - 1);
|
||||
|
||||
>system_library_stream = stream[..line];
|
||||
|
||||
while (1)
|
||||
{
|
||||
>space = string_first_character(system_library_stream, ' ');
|
||||
if (space == string_no_match)
|
||||
{
|
||||
>library_argument = system_library_stream;
|
||||
library_buffer[library_count] = library_argument[2..];
|
||||
library_count += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Omit the first two characters: "-l"
|
||||
>library_argument = system_library_stream[2..space];
|
||||
library_buffer[library_count] = library_argument;
|
||||
library_count += 1;
|
||||
system_library_stream = system_library_stream[space + 1..];
|
||||
}
|
||||
|
||||
library_buffer[library_count] = "gcc";
|
||||
library_count += 1;
|
||||
|
||||
library_buffer[library_count] = "gcc_s";
|
||||
library_count += 1;
|
||||
|
||||
library_buffer[library_count] = "lldCommon";
|
||||
library_count += 1;
|
||||
|
||||
library_buffer[library_count] = "lldELF";
|
||||
library_count += 1;
|
||||
|
||||
library_names = library_buffer[..library_count];
|
||||
library_paths = { .pointer = &llvm_bindings_library, .length = 1 };
|
||||
}
|
||||
else if (string_equal(base_name, "c_abi"))
|
||||
{
|
||||
@ -17915,7 +18390,7 @@ compile_file = fn (arena: &Arena, compile_options: CompileFile) []u8
|
||||
.library_names = library_names,
|
||||
.library_paths = library_paths,
|
||||
.link_libc = 1,
|
||||
.link_libcpp = 0,
|
||||
.link_libcpp = is_compiler,
|
||||
.name = base_name,
|
||||
.build_mode = compile_options.build_mode,
|
||||
.content = file_content,
|
||||
@ -18125,7 +18600,7 @@ names: [_][]u8 =
|
||||
.build_mode = build_mode,
|
||||
.has_debug_info = has_debug_info,
|
||||
.silent = 0,
|
||||
});
|
||||
}, envp);
|
||||
},
|
||||
.test =>
|
||||
{
|
||||
@ -18149,7 +18624,7 @@ names: [_][]u8 =
|
||||
.build_mode = build_mode,
|
||||
.has_debug_info = has_debug_info,
|
||||
.silent = 1,
|
||||
});
|
||||
}, envp);
|
||||
|
||||
>arguments: [_]&u8 = [
|
||||
executable_path.pointer,
|
||||
|
@ -898,6 +898,7 @@ enum class UnaryTypeId
|
||||
{
|
||||
align_of,
|
||||
byte_size,
|
||||
enum_names,
|
||||
enum_values,
|
||||
integer_max,
|
||||
};
|
||||
|
@ -686,20 +686,18 @@ fn Field* get_member_at_offset(Type* struct_type, u32 offset)
|
||||
|
||||
if (struct_type->structure.byte_size > offset)
|
||||
{
|
||||
u32 offset_it = 0;
|
||||
auto fields = struct_type->structure.fields;
|
||||
|
||||
for (u64 i = 0; i < fields.length; i += 1)
|
||||
{
|
||||
auto* field = &fields[i];
|
||||
|
||||
if (offset_it > offset)
|
||||
auto field_offset = field->offset;
|
||||
if (field_offset > offset)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = field;
|
||||
offset_it = (u32)align_forward(offset_it + get_byte_size(field->type), get_byte_alignment(field->type));
|
||||
}
|
||||
|
||||
assert(result);
|
||||
@ -3099,7 +3097,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
||||
|
||||
auto alloca = create_alloca(module, {
|
||||
.type = string_type,
|
||||
.name = string_literal("retval"),
|
||||
.name = string_literal("return_value"),
|
||||
});
|
||||
|
||||
auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block");
|
||||
@ -3278,6 +3276,15 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
||||
} break;
|
||||
}
|
||||
}
|
||||
else if (unary_type_id == UnaryTypeId::enum_names)
|
||||
{
|
||||
if (unary_type->id != TypeId::enumerator)
|
||||
{
|
||||
report_error();
|
||||
}
|
||||
|
||||
value_type = get_slice_type(module, get_slice_type(module, uint8(module)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (expected_type)
|
||||
@ -3312,6 +3319,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
||||
{
|
||||
value = integer_max_value(unary_type->integer.bit_count, unary_type->integer.is_signed);
|
||||
} break;
|
||||
case UnaryTypeId::enum_names:
|
||||
case UnaryTypeId::enum_values:
|
||||
{
|
||||
unreachable();
|
||||
@ -4302,12 +4310,12 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
||||
|
||||
auto return_value_alloca = create_alloca(module, {
|
||||
.type = enum_type,
|
||||
.name = string_literal("retval"),
|
||||
.name = string_literal("return_value"),
|
||||
});
|
||||
|
||||
auto return_boolean_alloca = create_alloca(module, {
|
||||
.type = u8_type,
|
||||
.name = string_literal("retbool"),
|
||||
.name = string_literal("return_bool"),
|
||||
});
|
||||
|
||||
auto index_alloca = create_alloca(module, {
|
||||
@ -6732,6 +6740,37 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type,
|
||||
auto value = emit_field_access(module, right, left_llvm, left_type, TypeKind::memory);
|
||||
right->llvm = value;
|
||||
} break;
|
||||
case ValueId::unary_type:
|
||||
{
|
||||
auto unary_type_id = right->unary_type.id;
|
||||
auto unary_type = right->unary_type.type;
|
||||
|
||||
switch (unary_type_id)
|
||||
{
|
||||
case UnaryTypeId::enum_names:
|
||||
{
|
||||
assert(unary_type->id == TypeId::enumerator);
|
||||
auto global = get_enum_name_array_global(module, unary_type);
|
||||
|
||||
auto u64_type = uint64(module);
|
||||
resolve_type_in_place(module, u64_type);
|
||||
|
||||
LLVMValueRef slice_values[] = {
|
||||
global->variable.storage->llvm,
|
||||
LLVMConstInt(u64_type->llvm.abi, unary_type->enumerator.fields.length, 0),
|
||||
};
|
||||
auto slice = LLVMConstStructInContext(module->llvm.context, slice_values, array_length(slice_values), 0);
|
||||
|
||||
create_store(module, {
|
||||
.source = slice,
|
||||
.destination = left_llvm,
|
||||
.type = resolved_value_type,
|
||||
});
|
||||
} break;
|
||||
default:
|
||||
trap();
|
||||
}
|
||||
} break;
|
||||
default: unreachable();
|
||||
}
|
||||
} break;
|
||||
@ -7042,11 +7081,6 @@ fn void emit_macro_instantiation(Module* module, Value* value)
|
||||
|
||||
LLVMPositionBuilderAtEnd(module->llvm.builder, return_block);
|
||||
|
||||
// END OF SCOPE
|
||||
if (module->has_debug_info)
|
||||
{
|
||||
LLVMSetCurrentDebugLocation2(module->llvm.builder, caller_debug_location);
|
||||
}
|
||||
module->llvm.inlined_at = older_inlined_at;
|
||||
module->current_macro_instantiation = old_macro_instantiation;
|
||||
module->current_function = current_function;
|
||||
@ -7055,7 +7089,7 @@ fn void emit_macro_instantiation(Module* module, Value* value)
|
||||
}
|
||||
}
|
||||
|
||||
fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u32* last_line, u32* last_column, LLVMMetadataRef* last_debug_location);
|
||||
fn void analyze_statement(Module* module, Scope* scope, Statement* statement);
|
||||
|
||||
fn void analyze_block(Module* module, Block* block)
|
||||
{
|
||||
@ -7071,7 +7105,7 @@ fn void analyze_block(Module* module, Block* block)
|
||||
|
||||
for (auto* statement = block->first_statement; statement; statement = statement->next)
|
||||
{
|
||||
analyze_statement(module, &block->scope, statement, &last_line, &last_column, &last_debug_location);
|
||||
analyze_statement(module, &block->scope, statement);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7344,6 +7378,10 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case UnaryTypeId::enum_names:
|
||||
{
|
||||
trap();
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case ValueId::binary:
|
||||
@ -8177,7 +8215,7 @@ fn void analyze_value(Module* module, Value* value, Type* expected_type, TypeKin
|
||||
emit_value(module, value, type_kind, must_be_constant);
|
||||
}
|
||||
|
||||
fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u32* last_line, u32* last_column, LLVMMetadataRef* last_debug_location)
|
||||
fn void analyze_statement(Module* module, Scope* scope, Statement* statement)
|
||||
{
|
||||
Global* parent_function_global;
|
||||
if (module->current_function)
|
||||
@ -8196,16 +8234,12 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
||||
auto* llvm_function = parent_function_global->variable.storage->llvm;
|
||||
assert(llvm_function);
|
||||
|
||||
LLVMMetadataRef statement_location = 0;
|
||||
|
||||
if (module->has_debug_info)
|
||||
{
|
||||
if (statement->line != *last_line || statement->column != *last_column)
|
||||
{
|
||||
auto new_location = LLVMDIBuilderCreateDebugLocation(module->llvm.context, statement->line, statement->column, scope->llvm, module->llvm.inlined_at);
|
||||
*last_debug_location = new_location;
|
||||
LLVMSetCurrentDebugLocation2(module->llvm.builder, new_location);
|
||||
*last_line = statement->line;
|
||||
*last_column = statement->column;
|
||||
}
|
||||
statement_location = LLVMDIBuilderCreateDebugLocation(module->llvm.context, statement->line, statement->column, scope->llvm, module->llvm.inlined_at);
|
||||
LLVMSetCurrentDebugLocation2(module->llvm.builder, statement_location);
|
||||
}
|
||||
|
||||
switch (statement->id)
|
||||
@ -8237,7 +8271,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
||||
{
|
||||
if (module->has_debug_info)
|
||||
{
|
||||
LLVMSetCurrentDebugLocation2(module->llvm.builder, *last_debug_location);
|
||||
LLVMSetCurrentDebugLocation2(module->llvm.builder, statement_location);
|
||||
}
|
||||
|
||||
auto return_alloca = module->current_function->variable.storage->function.llvm.return_alloca;
|
||||
@ -8304,7 +8338,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
||||
LLVMBuildCondBr(module->llvm.builder, llvm_condition, taken_block, not_taken_block);
|
||||
LLVMPositionBuilderAtEnd(module->llvm.builder, taken_block);
|
||||
|
||||
analyze_statement(module, scope, statement->if_st.if_statement, last_line, last_column, last_debug_location);
|
||||
analyze_statement(module, scope, statement->if_st.if_statement);
|
||||
|
||||
if (LLVMGetInsertBlock(module->llvm.builder))
|
||||
{
|
||||
@ -8315,7 +8349,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
||||
auto else_statement = statement->if_st.else_statement;
|
||||
if (else_statement)
|
||||
{
|
||||
analyze_statement(module, scope, else_statement, last_line, last_column, last_debug_location);
|
||||
analyze_statement(module, scope, else_statement);
|
||||
}
|
||||
|
||||
if (LLVMGetInsertBlock(module->llvm.builder))
|
||||
@ -8950,7 +8984,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
||||
|
||||
assert(!local);
|
||||
|
||||
analyze_statement(module, &statement->for_each.scope, statement->for_each.predicate, last_line, last_column, last_debug_location);
|
||||
analyze_statement(module, &statement->for_each.scope, statement->for_each.predicate);
|
||||
|
||||
if (LLVMGetInsertBlock(module->llvm.builder))
|
||||
{
|
||||
@ -9054,7 +9088,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
||||
LLVMBuildCondBr(module->llvm.builder, index_compare, body_block, exit_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(module->llvm.builder, body_block);
|
||||
analyze_statement(module, &statement->for_each.scope, statement->for_each.predicate, last_line, last_column, last_debug_location);
|
||||
analyze_statement(module, &statement->for_each.scope, statement->for_each.predicate);
|
||||
|
||||
if (LLVMGetInsertBlock(module->llvm.builder))
|
||||
{
|
||||
@ -9601,7 +9635,7 @@ void emit(Module* module)
|
||||
{
|
||||
auto alloca = create_alloca(module, {
|
||||
.type = function_type->abi.return_abi.semantic_type,
|
||||
.name = string_literal("retval"),
|
||||
.name = string_literal("return_value"),
|
||||
});
|
||||
global->variable.storage->function.llvm.return_alloca = alloca;
|
||||
} break;
|
||||
|
@ -7,6 +7,7 @@ enum class ValueIntrinsic
|
||||
byte_size,
|
||||
enum_from_int,
|
||||
enum_name,
|
||||
enum_names,
|
||||
enum_values,
|
||||
extend,
|
||||
field_parent_pointer,
|
||||
@ -1179,6 +1180,7 @@ fn Token tokenize(Module* module)
|
||||
string_literal("byte_size"),
|
||||
string_literal("enum_from_int"),
|
||||
string_literal("enum_name"),
|
||||
string_literal("enum_names"),
|
||||
string_literal("enum_values"),
|
||||
string_literal("extend"),
|
||||
string_literal("field_parent_pointer"),
|
||||
@ -1743,6 +1745,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
||||
case ValueIntrinsic::align_of:
|
||||
case ValueIntrinsic::byte_size:
|
||||
case ValueIntrinsic::enum_values:
|
||||
case ValueIntrinsic::enum_names:
|
||||
case ValueIntrinsic::integer_max:
|
||||
{
|
||||
skip_space(module);
|
||||
@ -1758,6 +1761,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
||||
{
|
||||
case ValueIntrinsic::align_of: id = UnaryTypeId::align_of; break;
|
||||
case ValueIntrinsic::byte_size: id = UnaryTypeId::byte_size; break;
|
||||
case ValueIntrinsic::enum_names: id = UnaryTypeId::enum_names; break;
|
||||
case ValueIntrinsic::enum_values: id = UnaryTypeId::enum_values; break;
|
||||
case ValueIntrinsic::integer_max: id = UnaryTypeId::integer_max; break;
|
||||
default: unreachable();
|
||||
|
Loading…
x
Reference in New Issue
Block a user