Pass an important chunk of tests #36

Merged
davidgmbb merged 16 commits from test-plus into main 2025-06-14 05:07:14 +00:00
4 changed files with 2689 additions and 879 deletions

View File

@ -51,3 +51,6 @@ target_link_libraries(bb PUBLIC llvm_bindings)
add_compile_options(-Wall -Wextra -pedantic -Wpedantic -Werror -Wno-c99-extensions -Wno-unused-function -Wno-missing-designated-field-initializers -fno-signed-char -fwrapv -fno-strict-aliasing) add_compile_options(-Wall -Wextra -pedantic -Wpedantic -Werror -Wno-c99-extensions -Wno-unused-function -Wno-missing-designated-field-initializers -fno-signed-char -fwrapv -fno-strict-aliasing)
add_compile_definitions(CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}") add_compile_definitions(CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}")
add_compile_definitions(BB_CI=${BB_CI}) add_compile_definitions(BB_CI=${BB_CI})
# add_compile_options(-fsanitize=address)
# add_link_options(-fsanitize=address)

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@ fn LLVMValueRef llvm_module_create_function(Arena* arena, LLVMModuleRef module,
return function; return function;
} }
fn LLVMValueRef llvm_module_create_global_variable(LLVMModuleRef module, LLVMTypeRef type, bool is_constant, LLVMLinkage linkage_type, LLVMValueRef initial_value, String name, LLVMThreadLocalMode thread_local_mode, bool externally_initialized, u32 alignment, LLVMUnnamedAddr unnamed_address) fn LLVMValueRef llvm_create_global_variable(LLVMModuleRef module, LLVMTypeRef type, bool is_constant, LLVMLinkage linkage_type, LLVMValueRef initial_value, String name, LLVMThreadLocalMode thread_local_mode, bool externally_initialized, u32 alignment, LLVMUnnamedAddr unnamed_address)
{ {
assert(name.pointer[name.length] == 0); assert(name.pointer[name.length] == 0);
auto global = LLVMAddGlobal(module, type, (char*)name.pointer); auto global = LLVMAddGlobal(module, type, (char*)name.pointer);
@ -609,21 +609,19 @@ fn bool contains_no_user_data(Type* type, u64 start, u64 end)
{ {
case TypeId::structure: case TypeId::structure:
{ {
u64 offset = 0;
for (auto& field: type->structure.fields) for (auto& field: type->structure.fields)
{ {
if (offset >= end) auto field_offset = field.offset;
if (field_offset >= end)
{ {
break; break;
} }
auto field_start = offset < start ? start - offset : 0; auto field_start = field_offset < start ? start - field_offset : 0;
if (!contains_no_user_data(field.type, field_start, end - offset)) if (!contains_no_user_data(field.type, field_start, end - field_offset))
{ {
return false; return false;
} }
offset += get_byte_size(field.type);
} }
return true; return true;
@ -855,7 +853,7 @@ fn AbiSystemVClassifyResult abi_system_v_classify_type(Type* type, AbiSystemVCla
u64 vector_size = 16; u64 vector_size = 16;
if (byte_size > 16 && (byte_size != get_byte_size(element_type) || byte_size > vector_size)) if (byte_size > 16 && (byte_size != element_size || byte_size > vector_size))
{ {
unreachable(); unreachable();
} }
@ -2541,7 +2539,6 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type)
auto u64_type = uint64(module); auto u64_type = uint64(module);
resolve_type_in_place(module, u8_type); resolve_type_in_place(module, u8_type);
resolve_type_in_place(module, u64_type); resolve_type_in_place(module, u64_type);
LLVMValueRef name_before = 0;
LLVMValueRef name_constant_buffer[64]; LLVMValueRef name_constant_buffer[64];
for (u32 i = 0; i < fields.length; i += 1) for (u32 i = 0; i < fields.length; i += 1)
@ -2555,11 +2552,9 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type)
string_literal("."), string_literal("."),
field.name, field.name,
}; };
unsigned address_space = 0;
auto initial_value = LLVMConstStringInContext2(module->llvm.context, (char*)field.name.pointer, field.name.length, false); auto initial_value = LLVMConstStringInContext2(module->llvm.context, (char*)field.name.pointer, field.name.length, false);
u32 alignment = 1; u32 alignment = 1;
auto name_global = llvm_module_create_global_variable(module->llvm.module, LLVMArrayType2(u8_type->llvm.abi, field.name.length + null_terminate), is_constant, LLVMInternalLinkage, initial_value, arena_join_string(module->arena, array_to_slice(name_parts)), LLVMNotThreadLocal, false, alignment, LLVMGlobalUnnamedAddr); auto name_global = llvm_create_global_variable(module->llvm.module, LLVMArrayType2(u8_type->llvm.abi, field.name.length + null_terminate), is_constant, LLVMInternalLinkage, initial_value, arena_join_string(module->arena, array_to_slice(name_parts)), LLVMNotThreadLocal, false, alignment, LLVMGlobalUnnamedAddr);
name_before = name_global;
LLVMValueRef constants[] = { LLVMValueRef constants[] = {
name_global, name_global,
LLVMConstInt(u64_type->llvm.abi, field.name.length, false), LLVMConstInt(u64_type->llvm.abi, field.name.length, false),
@ -2573,8 +2568,7 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type)
auto name_array = LLVMConstArray2(slice_type->llvm.abi, name_constant_buffer, array_element_count); auto name_array = LLVMConstArray2(slice_type->llvm.abi, name_constant_buffer, array_element_count);
auto name_array_type = LLVMArrayType2(slice_type->llvm.abi, array_element_count); auto name_array_type = LLVMArrayType2(slice_type->llvm.abi, array_element_count);
auto is_constant = true; auto is_constant = true;
unsigned address_space = 0; auto name_array_variable = llvm_create_global_variable(module->llvm.module, name_array_type, is_constant, LLVMInternalLinkage, name_array, string_literal("name.array.enum"), LLVMNotThreadLocal, false, get_byte_alignment(slice_type), LLVMGlobalUnnamedAddr);
auto name_array_variable = llvm_module_create_global_variable(module->llvm.module, name_array_type, is_constant, LLVMInternalLinkage, name_array, string_literal("name.array.enum"), LLVMNotThreadLocal, false, get_byte_alignment(slice_type), LLVMGlobalUnnamedAddr);
auto global_type = get_array_type(module, slice_type, array_element_count); auto global_type = get_array_type(module, slice_type, array_element_count);
resolve_type_in_place(module, global_type); resolve_type_in_place(module, global_type);
@ -4283,9 +4277,8 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
auto value_array_variable_type = LLVMArrayType2(enum_value_type, array_element_count); auto value_array_variable_type = LLVMArrayType2(enum_value_type, array_element_count);
auto is_constant = true; auto is_constant = true;
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal; LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
unsigned address_space = 0;
auto externally_initialized = false; auto externally_initialized = false;
auto value_array_variable = llvm_module_create_global_variable(module->llvm.module, value_array_variable_type, is_constant, LLVMInternalLinkage, value_array, string_literal("value.array.enum"), thread_local_mode, externally_initialized, enum_alignment, LLVMGlobalUnnamedAddr); auto value_array_variable = llvm_create_global_variable(module->llvm.module, value_array_variable_type, is_constant, LLVMInternalLinkage, value_array, string_literal("value.array.enum"), thread_local_mode, externally_initialized, enum_alignment, LLVMGlobalUnnamedAddr);
auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "entry"); auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "entry");
auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block"); auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block");
@ -5179,7 +5172,7 @@ fn SliceEmitResult emit_string_literal(Module* module, Value* value)
LLVMThreadLocalMode tlm = LLVMNotThreadLocal; LLVMThreadLocalMode tlm = LLVMNotThreadLocal;
bool externally_initialized = false; bool externally_initialized = false;
u32 alignment = 1; u32 alignment = 1;
auto global = llvm_module_create_global_variable(module->llvm.module, string_type, is_constant, LLVMInternalLinkage, constant_string, string_literal("conststring"), tlm, externally_initialized, alignment, LLVMGlobalUnnamedAddr); auto global = llvm_create_global_variable(module->llvm.module, string_type, is_constant, LLVMInternalLinkage, constant_string, string_literal("conststring"), tlm, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
return { global, LLVMConstInt(uint64(module)->llvm.abi, length, false) }; return { global, LLVMConstInt(uint64(module)->llvm.abi, length, false) };
} break; } break;
@ -5216,6 +5209,22 @@ fn void invalidate_analysis(Module* module, Value* value)
{ {
invalidate_analysis(module, value->unary.value); invalidate_analysis(module, value->unary.value);
} break; } break;
case ValueId::slice_expression:
{
invalidate_analysis(module, value->slice_expression.array_like);
auto start = value->slice_expression.start;
auto end = value->slice_expression.end;
if (start)
{
invalidate_analysis(module, start);
}
if (end)
{
invalidate_analysis(module, end);
}
} break;
default: trap(); default: trap();
} }
@ -5552,11 +5561,10 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
bool is_constant = true; bool is_constant = true;
LLVMLinkage linkage_type = LLVMInternalLinkage; LLVMLinkage linkage_type = LLVMInternalLinkage;
LLVMThreadLocalMode thread_local_mode = {}; LLVMThreadLocalMode thread_local_mode = {};
u32 address_space = 0;
bool externally_initialized = false; bool externally_initialized = false;
auto alignment = get_byte_alignment(semantic_argument_type); auto alignment = get_byte_alignment(semantic_argument_type);
auto global = llvm_module_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("conststruct"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); auto global = llvm_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("const.struct"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
for (u32 i = 0; i < coerce_fields.length; i += 1) for (u32 i = 0; i < coerce_fields.length; i += 1)
{ {
@ -5707,7 +5715,7 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
bool externally_initialized = false; bool externally_initialized = false;
auto alignment = get_byte_alignment(semantic_argument_type); auto alignment = get_byte_alignment(semantic_argument_type);
auto global = llvm_module_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("indirect.const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); auto global = llvm_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("indirect.const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
llvm_abi_argument_value_buffer[abi_argument_count] = global; llvm_abi_argument_value_buffer[abi_argument_count] = global;
abi_argument_count += 1; abi_argument_count += 1;
@ -5840,7 +5848,6 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
auto destination_type = return_abi.semantic_type; auto destination_type = return_abi.semantic_type;
auto source_value = llvm_call; auto source_value = llvm_call;
auto source_type = raw_function_type->function.abi.abi_return_type; auto source_type = raw_function_type->function.abi.abi_return_type;
auto destination_size = get_byte_size(destination_type); auto destination_size = get_byte_size(destination_type);
@ -6449,11 +6456,10 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type,
bool is_constant = true; bool is_constant = true;
LLVMLinkage linkage_type = LLVMInternalLinkage; LLVMLinkage linkage_type = LLVMInternalLinkage;
LLVMThreadLocalMode thread_local_mode = {}; LLVMThreadLocalMode thread_local_mode = {};
u32 address_space = 0;
bool externally_initialized = false; bool externally_initialized = false;
auto alignment = get_byte_alignment(resolved_value_type); auto alignment = get_byte_alignment(resolved_value_type);
auto global = llvm_module_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("array.init"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); auto global = llvm_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("array.init"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
u64 memcpy_size = get_byte_size(resolved_value_type); u64 memcpy_size = get_byte_size(resolved_value_type);
LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, LLVMConstInt(uint64_type->llvm.abi, memcpy_size, false)); LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, LLVMConstInt(uint64_type->llvm.abi, memcpy_size, false));
@ -6526,7 +6532,7 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type,
LLVMLinkage linkage_type = LLVMInternalLinkage; LLVMLinkage linkage_type = LLVMInternalLinkage;
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal; LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
bool externally_initialized = false; bool externally_initialized = false;
auto global = llvm_module_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); auto global = llvm_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, byte_size_value); LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, byte_size_value);
} }
else else
@ -7068,7 +7074,8 @@ fn void analyze_block(Module* module, Block* block)
fn LLVMValueRef emit_constant_array(Module* module, Slice<Value*> elements, Type* element_type) fn LLVMValueRef emit_constant_array(Module* module, Slice<Value*> elements, Type* element_type)
{ {
LLVMValueRef value_buffer[64]; LLVMValueRef value_buffer[128];
assert(elements.length <= array_length(value_buffer));
resolve_type_in_place(module, element_type); resolve_type_in_place(module, element_type);
@ -7329,7 +7336,7 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect
assert(array_type->id == TypeId::array); assert(array_type->id == TypeId::array);
resolve_type_in_place(module, array_type); resolve_type_in_place(module, array_type);
auto alignment = get_byte_alignment(resolved_value_type); auto alignment = get_byte_alignment(resolved_value_type);
auto value_array_variable = llvm_module_create_global_variable(module->llvm.module, array_type->llvm.memory, is_constant, LLVMInternalLinkage, array_value, string_literal("enum.values"), LLVMNotThreadLocal, 0, alignment, LLVMGlobalUnnamedAddr); auto value_array_variable = llvm_create_global_variable(module->llvm.module, array_type->llvm.memory, is_constant, LLVMInternalLinkage, array_value, string_literal("enum.values"), LLVMNotThreadLocal, 0, alignment, LLVMGlobalUnnamedAddr);
llvm_value = value_array_variable; llvm_value = value_array_variable;
} break; } break;
} }
@ -8615,6 +8622,10 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
if (else_clause_index == invalid_clause_index) if (else_clause_index == invalid_clause_index)
{ {
LLVMPositionBuilderAtEnd(module->llvm.builder, else_block); LLVMPositionBuilderAtEnd(module->llvm.builder, else_block);
if (module->has_debug_info && !build_mode_is_optimized(module->build_mode))
{
emit_intrinsic_call(module, IntrinsicIndex::trap, {}, {});
}
LLVMBuildUnreachable(module->llvm.builder); LLVMBuildUnreachable(module->llvm.builder);
LLVMClearInsertionPosition(module->llvm.builder); LLVMClearInsertionPosition(module->llvm.builder);
} }
@ -8678,6 +8689,16 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
Type* aggregate_type = 0; Type* aggregate_type = 0;
if (right->kind == ValueKind::left && right->type->id != TypeId::pointer)
{
if (!type_is_slice(right->type))
{
report_error();
}
right->kind = ValueKind::right;
}
switch (right->kind) switch (right->kind)
{ {
case ValueKind::right: case ValueKind::right:
@ -9504,7 +9525,7 @@ void emit(Module* module)
bool externally_initialized = false; bool externally_initialized = false;
auto alignment = get_byte_alignment(global_type); auto alignment = get_byte_alignment(global_type);
auto global_llvm = llvm_module_create_global_variable(module->llvm.module, global_type->llvm.memory, is_constant, linkage, global->variable.initial_value->llvm, global->variable.name, thread_local_mode, externally_initialized, alignment, LLVMNoUnnamedAddr); auto global_llvm = llvm_create_global_variable(module->llvm.module, global_type->llvm.memory, is_constant, linkage, global->variable.initial_value->llvm, global->variable.name, thread_local_mode, externally_initialized, alignment, LLVMNoUnnamedAddr);
global->variable.storage->llvm = global_llvm; global->variable.storage->llvm = global_llvm;
global->variable.storage->type = get_pointer_type(module, global_type); global->variable.storage->type = get_pointer_type(module, global_type);

View File

@ -1937,7 +1937,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
case TokenId::left_bracket: case TokenId::left_bracket:
{ {
u64 element_count = 0; u64 element_count = 0;
Value* value_buffer[64]; Value* value_buffer[128];
skip_space(module); skip_space(module);
@ -1976,6 +1976,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
} }
auto value = parse_value(module, scope, {}); auto value = parse_value(module, scope, {});
assert(element_count < array_length(value_buffer));
value_buffer[element_count] = value; value_buffer[element_count] = value;
element_count += 1; element_count += 1;
@ -2822,7 +2823,7 @@ fn Statement* parse_statement(Module* module, Scope* scope)
Value* right_value_buffer[64]; Value* right_value_buffer[64];
u64 right_value_count = 0; u64 right_value_count = 0;
right_value_buffer[right_value_count] = parse_value(module, scope, { .kind = ValueKind::left }); right_value_buffer[right_value_count] = parse_value(module, scope, {});
right_value_count += 1; right_value_count += 1;
skip_space(module); skip_space(module);
@ -2839,15 +2840,17 @@ fn Statement* parse_statement(Module* module, Scope* scope)
report_error(); report_error();
} }
right_value_buffer[0]->kind = ValueKind::right;
right_value_buffer[right_value_count] = parse_value(module, scope, {}); right_value_buffer[right_value_count] = parse_value(module, scope, {});
right_value_count += 1; right_value_count += 1;
expect_character(module, right_parenthesis); expect_character(module, right_parenthesis);
kind = ForEachKind::range; kind = ForEachKind::range;
} break; } break;
case TokenId::right_parenthesis: kind = ForEachKind::slice; break; case TokenId::right_parenthesis:
{
right_value_buffer[0]->kind = ValueKind::left;
kind = ForEachKind::slice;
} break;
default: report_error(); default: report_error();
} }