mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Update logic for slice literals, backing array to be on the stack if possible (LLVM C API)
This commit is contained in:
+15
-5
@@ -4347,17 +4347,27 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|||||||
case BuiltinProc_swizzle: {
|
case BuiltinProc_swizzle: {
|
||||||
// swizzle :: proc(v: [N]T, ..int) -> [M]T
|
// swizzle :: proc(v: [N]T, ..int) -> [M]T
|
||||||
Type *type = base_type(operand->type);
|
Type *type = base_type(operand->type);
|
||||||
if (!is_type_array(type)) {
|
i64 max_count = 0;
|
||||||
|
Type *elem_type = nullptr;
|
||||||
|
|
||||||
|
if (!is_type_array(type) && !is_type_simd_vector(type)) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
error(call,
|
error(call,
|
||||||
"You can only 'swizzle' an array, got '%s'",
|
"'swizzle' is only allowed on an array or #simd vector, got '%s'",
|
||||||
type_str);
|
type_str);
|
||||||
gb_string_free(type_str);
|
gb_string_free(type_str);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (type->kind == Type_Array) {
|
||||||
i64 max_count = type->Array.count;
|
max_count = type->Array.count;
|
||||||
Type *elem_type = type->Array.elem;
|
elem_type = type->Array.elem;
|
||||||
|
} else if (type->kind == Type_SimdVector) {
|
||||||
|
max_count = type->SimdVector.count;
|
||||||
|
elem_type = type->SimdVector.elem;
|
||||||
|
if (!build_context.use_llvm_api) {
|
||||||
|
error(call, "'swizzle' with #simd vector is not supported on this backend");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
i64 arg_count = 0;
|
i64 arg_count = 0;
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
|
|||||||
+103
-40
@@ -33,10 +33,10 @@ struct lbCompoundLitElemTempData {
|
|||||||
lbLoopData lb_loop_start(lbProcedure *p, isize count, Type *index_type=t_i32);
|
lbLoopData lb_loop_start(lbProcedure *p, isize count, Type *index_type=t_i32);
|
||||||
void lb_loop_end(lbProcedure *p, lbLoopData const &data);
|
void lb_loop_end(lbProcedure *p, lbLoopData const &data);
|
||||||
|
|
||||||
LLVMValueRef llvm_zero32(lbModule *m) {
|
LLVMValueRef llvm_zero(lbModule *m) {
|
||||||
return LLVMConstInt(lb_type(m, t_i32), 0, false);
|
return LLVMConstInt(lb_type(m, t_int), 0, false);
|
||||||
}
|
}
|
||||||
LLVMValueRef llvm_one32(lbModule *m) {
|
LLVMValueRef llvm_one(lbModule *m) {
|
||||||
return LLVMConstInt(lb_type(m, t_i32), 1, false);
|
return LLVMConstInt(lb_type(m, t_i32), 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4459,7 +4459,7 @@ LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String const &str) {
|
|||||||
if (found != nullptr) {
|
if (found != nullptr) {
|
||||||
return *found;
|
return *found;
|
||||||
} else {
|
} else {
|
||||||
LLVMValueRef indices[2] = {llvm_zero32(m), llvm_zero32(m)};
|
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
|
||||||
LLVMValueRef data = LLVMConstStringInContext(m->ctx,
|
LLVMValueRef data = LLVMConstStringInContext(m->ctx,
|
||||||
cast(char const *)str.text,
|
cast(char const *)str.text,
|
||||||
cast(unsigned)str.len,
|
cast(unsigned)str.len,
|
||||||
@@ -4494,7 +4494,7 @@ lbValue lb_find_or_add_entity_string(lbModule *m, String const &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str) {
|
lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str) {
|
||||||
LLVMValueRef indices[2] = {llvm_zero32(m), llvm_zero32(m)};
|
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
|
||||||
LLVMValueRef data = LLVMConstStringInContext(m->ctx,
|
LLVMValueRef data = LLVMConstStringInContext(m->ctx,
|
||||||
cast(char const *)str.text,
|
cast(char const *)str.text,
|
||||||
cast(unsigned)str.len,
|
cast(unsigned)str.len,
|
||||||
@@ -4685,35 +4685,59 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value) {
|
|||||||
Type *t = alloc_type_array(elem, count);
|
Type *t = alloc_type_array(elem, count);
|
||||||
lbValue backing_array = lb_const_value(m, t, value);
|
lbValue backing_array = lb_const_value(m, t, value);
|
||||||
|
|
||||||
|
LLVMValueRef array_data = nullptr;
|
||||||
|
|
||||||
isize max_len = 7+8+1;
|
if (m->curr_procedure != nullptr) {
|
||||||
char *str = gb_alloc_array(heap_allocator(), char, max_len);
|
// NOTE(bill, 2020-06-08): This is a bit of a hack but a "constant" slice needs
|
||||||
isize len = gb_snprintf(str, max_len, "csba$%x", m->global_array_index);
|
// its backing data on the stack
|
||||||
m->global_array_index++;
|
lbProcedure *p = m->curr_procedure;
|
||||||
|
LLVMPositionBuilderAtEnd(p->builder, p->decl_block->block);
|
||||||
|
|
||||||
String name = make_string(cast(u8 *)str, len-1);
|
LLVMTypeRef llvm_type = lb_type(m, t);
|
||||||
|
array_data = LLVMBuildAlloca(p->builder, llvm_type, "");
|
||||||
|
LLVMSetAlignment(array_data, 16); // TODO(bill): Make this configurable
|
||||||
|
LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block);
|
||||||
|
LLVMBuildStore(p->builder, backing_array.value, array_data);
|
||||||
|
|
||||||
Entity *e = alloc_entity_constant(nullptr, make_token_ident(name), t, value);
|
{
|
||||||
LLVMValueRef global_data = LLVMAddGlobal(m->mod, lb_type(m, t), str);
|
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
|
||||||
LLVMSetInitializer(global_data, backing_array.value);
|
LLVMValueRef ptr = LLVMBuildInBoundsGEP(p->builder, array_data, indices, 2, "");
|
||||||
|
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
|
||||||
|
lbAddr slice = lb_add_local_generated(p, type, false);
|
||||||
|
lb_fill_slice(p, slice, {ptr, alloc_type_pointer(elem)}, {len, t_int});
|
||||||
|
return lb_addr_load(p, slice);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isize max_len = 7+8+1;
|
||||||
|
char *str = gb_alloc_array(heap_allocator(), char, max_len);
|
||||||
|
isize len = gb_snprintf(str, max_len, "csba$%x", m->global_array_index);
|
||||||
|
m->global_array_index++;
|
||||||
|
|
||||||
lbValue g = {};
|
String name = make_string(cast(u8 *)str, len-1);
|
||||||
g.value = global_data;
|
|
||||||
g.type = t;
|
|
||||||
|
|
||||||
lb_add_entity(m, e, g);
|
Entity *e = alloc_entity_constant(nullptr, make_token_ident(name), t, value);
|
||||||
lb_add_member(m, name, g);
|
array_data = LLVMAddGlobal(m->mod, lb_type(m, t), str);
|
||||||
|
LLVMSetInitializer(array_data, backing_array.value);
|
||||||
|
|
||||||
{
|
lbValue g = {};
|
||||||
LLVMValueRef indices[2] = {llvm_zero32(m), llvm_zero32(m)};
|
g.value = array_data;
|
||||||
LLVMValueRef ptr = LLVMConstInBoundsGEP(global_data, indices, 2);
|
g.type = t;
|
||||||
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
|
|
||||||
LLVMValueRef values[2] = {ptr, len};
|
|
||||||
|
|
||||||
res.value = LLVMConstNamedStruct(lb_type(m, original_type), values, 2);
|
lb_add_entity(m, e, g);
|
||||||
return res;
|
lb_add_member(m, name, g);
|
||||||
|
|
||||||
|
{
|
||||||
|
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
|
||||||
|
LLVMValueRef ptr = LLVMConstInBoundsGEP(array_data, indices, 2);
|
||||||
|
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
|
||||||
|
LLVMValueRef values[2] = {ptr, len};
|
||||||
|
|
||||||
|
res.value = LLVMConstNamedStruct(lb_type(m, original_type), values, 2);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (is_type_array(type) && value.kind == ExactValue_String && !is_type_u8(core_array_type(type))) {
|
} else if (is_type_array(type) && value.kind == ExactValue_String && !is_type_u8(core_array_type(type))) {
|
||||||
LLVMValueRef data = LLVMConstStringInContext(ctx,
|
LLVMValueRef data = LLVMConstStringInContext(ctx,
|
||||||
@@ -6525,7 +6549,7 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
|
|||||||
if (lb_is_const(s)) {
|
if (lb_is_const(s)) {
|
||||||
lbModule *m = p->module;
|
lbModule *m = p->module;
|
||||||
lbValue res = {};
|
lbValue res = {};
|
||||||
LLVMValueRef indices[2] = {llvm_zero32(m), LLVMConstInt(lb_type(m, t_i32), index, false)};
|
LLVMValueRef indices[2] = {llvm_zero(m), LLVMConstInt(lb_type(m, t_i32), index, false)};
|
||||||
res.value = LLVMConstGEP(s.value, indices, gb_count_of(indices));
|
res.value = LLVMConstGEP(s.value, indices, gb_count_of(indices));
|
||||||
res.type = alloc_type_pointer(result_type);
|
res.type = alloc_type_pointer(result_type);
|
||||||
return res;
|
return res;
|
||||||
@@ -7031,7 +7055,7 @@ lbValue lb_emit_array_ep(lbProcedure *p, lbValue s, lbValue index) {
|
|||||||
GB_ASSERT_MSG(is_type_integer(index.type), "%s", type_to_string(index.type));
|
GB_ASSERT_MSG(is_type_integer(index.type), "%s", type_to_string(index.type));
|
||||||
|
|
||||||
LLVMValueRef indices[2] = {};
|
LLVMValueRef indices[2] = {};
|
||||||
indices[0] = llvm_zero32(p->module);
|
indices[0] = llvm_zero(p->module);
|
||||||
indices[1] = lb_emit_conv(p, index, t_int).value;
|
indices[1] = lb_emit_conv(p, index, t_int).value;
|
||||||
|
|
||||||
Type *ptr = base_array_type(st);
|
Type *ptr = base_array_type(st);
|
||||||
@@ -7367,8 +7391,37 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case BuiltinProc_swizzle: {
|
case BuiltinProc_swizzle: {
|
||||||
lbAddr addr = lb_build_addr(p, ce->args[0]);
|
|
||||||
isize index_count = ce->args.count-1;
|
isize index_count = ce->args.count-1;
|
||||||
|
if (is_type_simd_vector(tv.type)) {
|
||||||
|
lbValue vec = lb_build_expr(p, ce->args[0]);
|
||||||
|
if (index_count == 0) {
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned mask_len = cast(unsigned)index_count;
|
||||||
|
LLVMValueRef *mask_elems = gb_alloc_array(heap_allocator(), LLVMValueRef, index_count);
|
||||||
|
for (isize i = 1; i < ce->args.count; i++) {
|
||||||
|
TypeAndValue tv = type_and_value_of_expr(ce->args[i]);
|
||||||
|
GB_ASSERT(is_type_integer(tv.type));
|
||||||
|
GB_ASSERT(tv.value.kind == ExactValue_Integer);
|
||||||
|
|
||||||
|
u32 index = cast(u32)big_int_to_i64(&tv.value.value_integer);
|
||||||
|
mask_elems[i-1] = LLVMConstInt(lb_type(p->module, t_u32), index, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMValueRef mask = LLVMConstVector(mask_elems, mask_len);
|
||||||
|
|
||||||
|
LLVMValueRef v1 = vec.value;
|
||||||
|
LLVMValueRef v2 = vec.value;
|
||||||
|
|
||||||
|
lbValue res = {};
|
||||||
|
res.type = tv.type;
|
||||||
|
res.value = LLVMBuildShuffleVector(p->builder, v1, v2, mask, "");
|
||||||
|
return res;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
lbAddr addr = lb_build_addr(p, ce->args[0]);
|
||||||
if (index_count == 0) {
|
if (index_count == 0) {
|
||||||
return lb_addr_load(p, addr);
|
return lb_addr_load(p, addr);
|
||||||
}
|
}
|
||||||
@@ -10468,12 +10521,15 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
GB_ASSERT(lb_is_const(slice));
|
|
||||||
unsigned indices[1] = {1};
|
|
||||||
|
|
||||||
lbValue count = {};
|
lbValue count = {};
|
||||||
count.type = t_int;
|
count.type = t_int;
|
||||||
count.value = LLVMConstExtractValue(slice.value, indices, gb_count_of(indices));
|
|
||||||
|
if (lb_is_const(slice)) {
|
||||||
|
unsigned indices[1] = {1};
|
||||||
|
count.value = LLVMConstExtractValue(slice.value, indices, gb_count_of(indices));
|
||||||
|
} else {
|
||||||
|
count.value = LLVMBuildExtractValue(p->builder, slice.value, 1, "");
|
||||||
|
}
|
||||||
lb_fill_slice(p, v, data, count);
|
lb_fill_slice(p, v, data, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10501,7 +10557,8 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
lb_emit_runtime_call(p, "__dynamic_array_reserve", args);
|
lb_emit_runtime_call(p, "__dynamic_array_reserve", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
lbValue items = lb_generate_array(p->module, et, item_count, str_lit("dacl$"), cast(i64)cast(intptr)expr);
|
lbValue items = lb_generate_local_array(p, et, item_count);
|
||||||
|
// lbValue items = lb_generate_global_array(p->module, et, item_count, str_lit("dacl$"), cast(i64)cast(intptr)expr);
|
||||||
|
|
||||||
for_array(i, cl->elems) {
|
for_array(i, cl->elems) {
|
||||||
Ast *elem = cl->elems[i];
|
Ast *elem = cl->elems[i];
|
||||||
@@ -10830,8 +10887,12 @@ lbValue lb_type_info_member_tags_offset(lbProcedure *p, isize count) {
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lbValue lb_generate_local_array(lbProcedure *p, Type *elem_type, i64 count, bool zero_init) {
|
||||||
|
lbAddr addr = lb_add_local_generated(p, alloc_type_array(elem_type, count), zero_init);
|
||||||
|
return lb_addr_get_ptr(p, addr);
|
||||||
|
}
|
||||||
|
|
||||||
lbValue lb_generate_array(lbModule *m, Type *elem_type, i64 count, String prefix, i64 id) {
|
lbValue lb_generate_global_array(lbModule *m, Type *elem_type, i64 count, String prefix, i64 id) {
|
||||||
gbAllocator a = heap_allocator();
|
gbAllocator a = heap_allocator();
|
||||||
Token token = {Token_Ident};
|
Token token = {Token_Ident};
|
||||||
isize name_len = prefix.len + 1 + 20;
|
isize name_len = prefix.len + 1 + 20;
|
||||||
@@ -10868,7 +10929,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
|
|||||||
Type *type = base_type(lb_addr_type(lb_global_type_info_data));
|
Type *type = base_type(lb_addr_type(lb_global_type_info_data));
|
||||||
GB_ASSERT(is_type_array(type));
|
GB_ASSERT(is_type_array(type));
|
||||||
|
|
||||||
LLVMValueRef indices[2] = {llvm_zero32(m), llvm_zero32(m)};
|
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
|
||||||
LLVMValueRef values[2] = {
|
LLVMValueRef values[2] = {
|
||||||
LLVMConstInBoundsGEP(lb_global_type_info_data.addr.value, indices, gb_count_of(indices)),
|
LLVMConstInBoundsGEP(lb_global_type_info_data.addr.value, indices, gb_count_of(indices)),
|
||||||
LLVMConstInt(lb_type(m, t_int), type->Array.count, true),
|
LLVMConstInt(lb_type(m, t_int), type->Array.count, true),
|
||||||
@@ -11231,9 +11292,9 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
|
|||||||
vals[0] = lb_type_info(m, t->Enum.base_type).value;
|
vals[0] = lb_type_info(m, t->Enum.base_type).value;
|
||||||
if (t->Enum.fields.count > 0) {
|
if (t->Enum.fields.count > 0) {
|
||||||
auto fields = t->Enum.fields;
|
auto fields = t->Enum.fields;
|
||||||
lbValue name_array = lb_generate_array(m, t_string, fields.count,
|
lbValue name_array = lb_generate_global_array(m, t_string, fields.count,
|
||||||
str_lit("$enum_names"), cast(i64)entry_index);
|
str_lit("$enum_names"), cast(i64)entry_index);
|
||||||
lbValue value_array = lb_generate_array(m, t_type_info_enum_value, fields.count,
|
lbValue value_array = lb_generate_global_array(m, t_type_info_enum_value, fields.count,
|
||||||
str_lit("$enum_values"), cast(i64)entry_index);
|
str_lit("$enum_values"), cast(i64)entry_index);
|
||||||
|
|
||||||
|
|
||||||
@@ -11438,9 +11499,9 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
|
|||||||
isize count = t->BitField.fields.count;
|
isize count = t->BitField.fields.count;
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
auto fields = t->BitField.fields;
|
auto fields = t->BitField.fields;
|
||||||
lbValue name_array = lb_generate_array(m, t_string, count, str_lit("$bit_field_names"), cast(i64)entry_index);
|
lbValue name_array = lb_generate_global_array(m, t_string, count, str_lit("$bit_field_names"), cast(i64)entry_index);
|
||||||
lbValue bit_array = lb_generate_array(m, t_i32, count, str_lit("$bit_field_bits"), cast(i64)entry_index);
|
lbValue bit_array = lb_generate_global_array(m, t_i32, count, str_lit("$bit_field_bits"), cast(i64)entry_index);
|
||||||
lbValue offset_array = lb_generate_array(m, t_i32, count, str_lit("$bit_field_offsets"), cast(i64)entry_index);
|
lbValue offset_array = lb_generate_global_array(m, t_i32, count, str_lit("$bit_field_offsets"), cast(i64)entry_index);
|
||||||
|
|
||||||
for (isize i = 0; i < count; i++) {
|
for (isize i = 0; i < count; i++) {
|
||||||
Entity *f = fields[i];
|
Entity *f = fields[i];
|
||||||
@@ -12148,10 +12209,12 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (p->body != nullptr) { // Build Procedure
|
if (p->body != nullptr) { // Build Procedure
|
||||||
|
m->curr_procedure = p;
|
||||||
lb_begin_procedure_body(p);
|
lb_begin_procedure_body(p);
|
||||||
lb_build_stmt(p, p->body);
|
lb_build_stmt(p, p->body);
|
||||||
lb_end_procedure_body(p);
|
lb_end_procedure_body(p);
|
||||||
p->is_done = true;
|
p->is_done = true;
|
||||||
|
m->curr_procedure = nullptr;
|
||||||
}
|
}
|
||||||
lb_end_procedure(p);
|
lb_end_procedure(p);
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ struct lbModule {
|
|||||||
Array<lbProcedure *> procedures_to_generate;
|
Array<lbProcedure *> procedures_to_generate;
|
||||||
Array<String> foreign_library_paths;
|
Array<String> foreign_library_paths;
|
||||||
|
|
||||||
|
lbProcedure *curr_procedure;
|
||||||
|
|
||||||
LLVMDIBuilderRef debug_builder;
|
LLVMDIBuilderRef debug_builder;
|
||||||
LLVMMetadataRef debug_compile_unit;
|
LLVMMetadataRef debug_compile_unit;
|
||||||
@@ -341,7 +341,8 @@ bool lb_is_const(lbValue value);
|
|||||||
bool lb_is_const_nil(lbValue value);
|
bool lb_is_const_nil(lbValue value);
|
||||||
String lb_get_const_string(lbModule *m, lbValue value);
|
String lb_get_const_string(lbModule *m, lbValue value);
|
||||||
|
|
||||||
lbValue lb_generate_array(lbModule *m, Type *elem_type, i64 count, String prefix, i64 id);
|
lbValue lb_generate_local_array(lbProcedure *p, Type *elem_type, i64 count, bool zero_init=true);
|
||||||
|
lbValue lb_generate_global_array(lbModule *m, Type *elem_type, i64 count, String prefix, i64 id);
|
||||||
lbValue lb_gen_map_header(lbProcedure *p, lbValue map_val_ptr, Type *map_type);
|
lbValue lb_gen_map_header(lbProcedure *p, lbValue map_val_ptr, Type *map_type);
|
||||||
lbValue lb_gen_map_key(lbProcedure *p, lbValue key, Type *key_type);
|
lbValue lb_gen_map_key(lbProcedure *p, lbValue key, Type *key_type);
|
||||||
void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbAddr addr, Type *map_type, lbValue map_key, lbValue map_value);
|
void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbAddr addr, Type *map_type, lbValue map_key, lbValue map_value);
|
||||||
|
|||||||
Reference in New Issue
Block a user