mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-14 18:02:22 -07:00
Merge remote-tracking branch 'offical/master'
This commit is contained in:
+2
-1
@@ -2,7 +2,6 @@
|
||||
set -eu
|
||||
|
||||
: ${CPPFLAGS=}
|
||||
: ${CXX=clang++}
|
||||
: ${CXXFLAGS=}
|
||||
: ${LDFLAGS=}
|
||||
: ${LLVM_CONFIG=}
|
||||
@@ -44,6 +43,8 @@ if [ -z "$LLVM_CONFIG" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
: ${CXX=$($LLVM_CONFIG --bindir)/clang++}
|
||||
|
||||
LLVM_VERSION="$($LLVM_CONFIG --version)"
|
||||
LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')"
|
||||
LLVM_VERSION_MINOR="$(echo $LLVM_VERSION | awk -F. '{print $2}')"
|
||||
|
||||
@@ -2314,7 +2314,7 @@ futex :: proc {
|
||||
*/
|
||||
epoll_create :: proc(size: i32 = 1) -> (Fd, Errno) {
|
||||
when ODIN_ARCH != .arm64 {
|
||||
ret := syscall(SYS_epoll_create)
|
||||
ret := syscall(SYS_epoll_create, i32(1))
|
||||
return errno_unwrap(ret, Fd)
|
||||
} else {
|
||||
ret := syscall(SYS_epoll_create1, i32(0))
|
||||
|
||||
@@ -25,7 +25,7 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
|
||||
|
||||
when ODIN_OS != .Darwin {
|
||||
// We need to give the thread a moment to start up before we enable cancellation.
|
||||
can_set_thread_cancel_state := unix.pthread_setcancelstate(unix.PTHREAD_CANCEL_DISABLE, nil) == 0
|
||||
can_set_thread_cancel_state := unix.pthread_setcancelstate(unix.PTHREAD_CANCEL_ENABLE, nil) == 0
|
||||
}
|
||||
|
||||
sync.lock(&t.mutex)
|
||||
@@ -40,7 +40,7 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
|
||||
// Enable thread's cancelability.
|
||||
if can_set_thread_cancel_state {
|
||||
unix.pthread_setcanceltype (unix.PTHREAD_CANCEL_ASYNCHRONOUS, nil)
|
||||
unix.pthread_setcancelstate(unix.PTHREAD_CANCEL_DISABLE, nil)
|
||||
unix.pthread_setcancelstate(unix.PTHREAD_CANCEL_ENABLE, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2023,6 +2023,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
|
||||
Selection sel = lookup_field(type, field_name, false);
|
||||
if (sel.entity == nullptr) {
|
||||
ERROR_BLOCK();
|
||||
gbString type_str = type_to_string_shorthand(type);
|
||||
error(ce->args[0],
|
||||
"'%s' has no field named '%.*s'", type_str, LIT(field_name));
|
||||
@@ -2096,6 +2097,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
|
||||
Selection sel = lookup_field(type, field_name, false);
|
||||
if (sel.entity == nullptr) {
|
||||
ERROR_BLOCK();
|
||||
gbString type_str = type_to_string_shorthand(type);
|
||||
error(ce->args[0],
|
||||
"'%s' has no field named '%.*s'", type_str, LIT(field_name));
|
||||
@@ -5837,6 +5839,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
|
||||
Selection sel = lookup_field(type, field_name, false);
|
||||
if (sel.entity == nullptr) {
|
||||
ERROR_BLOCK();
|
||||
gbString type_str = type_to_string(bt);
|
||||
error(ce->args[0],
|
||||
"'%s' has no field named '%.*s'", type_str, LIT(field_name));
|
||||
|
||||
+8
-2
@@ -102,6 +102,7 @@ gb_internal Type * check_init_variable (CheckerContext *c, Entity *
|
||||
gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o, Type *type, i64 max_bit_size=0);
|
||||
gb_internal void add_map_key_type_dependencies(CheckerContext *ctx, Type *key);
|
||||
|
||||
gb_internal Type *make_soa_struct_fixed(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem, i64 count, Type *generic_type);
|
||||
gb_internal Type *make_soa_struct_slice(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem);
|
||||
gb_internal Type *make_soa_struct_dynamic_array(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem);
|
||||
|
||||
@@ -1409,11 +1410,16 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T
|
||||
poly->Struct.soa_kind != StructSoa_None) {
|
||||
bool ok = is_polymorphic_type_assignable(c, poly->Struct.soa_elem, source->Struct.soa_elem, true, modify_type);
|
||||
if (ok) switch (source->Struct.soa_kind) {
|
||||
case StructSoa_Fixed:
|
||||
case StructSoa_None:
|
||||
default:
|
||||
GB_PANIC("Unhandled SOA Kind");
|
||||
break;
|
||||
|
||||
case StructSoa_Fixed:
|
||||
if (modify_type) {
|
||||
Type *type = make_soa_struct_fixed(c, nullptr, poly->Struct.node, poly->Struct.soa_elem, poly->Struct.soa_count, nullptr);
|
||||
gb_memmove(poly, type, gb_size_of(*type));
|
||||
}
|
||||
break;
|
||||
case StructSoa_Slice:
|
||||
if (modify_type) {
|
||||
Type *type = make_soa_struct_slice(c, nullptr, poly->Struct.node, poly->Struct.soa_elem);
|
||||
|
||||
+28
-4
@@ -381,6 +381,7 @@ gb_internal Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *poly
|
||||
Type *type = nullptr;
|
||||
bool is_type_param = false;
|
||||
bool is_type_polymorphic_type = false;
|
||||
Type *specialization = nullptr;
|
||||
if (type_expr == nullptr && default_value == nullptr) {
|
||||
error(param, "Expected a type for this parameter");
|
||||
continue;
|
||||
@@ -393,7 +394,6 @@ gb_internal Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *poly
|
||||
}
|
||||
if (type_expr->kind == Ast_TypeidType) {
|
||||
is_type_param = true;
|
||||
Type *specialization = nullptr;
|
||||
if (type_expr->TypeidType.specialization != nullptr) {
|
||||
Ast *s = type_expr->TypeidType.specialization;
|
||||
specialization = check_type(ctx, s);
|
||||
@@ -471,6 +471,15 @@ gb_internal Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *poly
|
||||
if (is_type_polymorphic(base_type(operand.type))) {
|
||||
*is_polymorphic_ = true;
|
||||
can_check_fields = false;
|
||||
} else if (specialization &&
|
||||
!check_type_specialization_to(ctx, specialization, operand.type, false, /*modify_type*/true)) {
|
||||
if (!ctx->no_polymorphic_errors) {
|
||||
gbString t = type_to_string(operand.type);
|
||||
gbString s = type_to_string(specialization);
|
||||
error(operand.expr, "Cannot convert type '%s' to the specialization '%s'", t, s);
|
||||
gb_string_free(s);
|
||||
gb_string_free(t);
|
||||
}
|
||||
}
|
||||
e = alloc_entity_type_name(scope, token, operand.type);
|
||||
e->TypeName.is_type_alias = true;
|
||||
@@ -797,11 +806,11 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam
|
||||
enum_type->Enum.scope = ctx->scope;
|
||||
|
||||
Type *base_type = t_int;
|
||||
if (et->base_type != nullptr) {
|
||||
if (unparen_expr(et->base_type) != nullptr) {
|
||||
base_type = check_type(ctx, et->base_type);
|
||||
}
|
||||
|
||||
if (base_type == nullptr || !is_type_integer(base_type)) {
|
||||
if (base_type == nullptr || base_type == t_invalid || !is_type_integer(base_type)) {
|
||||
error(node, "Base type for enumeration must be an integer");
|
||||
return;
|
||||
}
|
||||
@@ -1080,6 +1089,8 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type,
|
||||
array_add(&tags, tag);
|
||||
|
||||
add_entity_use(ctx, field, e);
|
||||
|
||||
total_bit_size += bit_size_u8;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1094,7 +1105,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type,
|
||||
|
||||
if (total_bit_size > maximum_bit_size) {
|
||||
gbString s = type_to_string(backing_type);
|
||||
error(node, "The numbers required %llu exceeds the backing type's (%s) bit size %llu",
|
||||
error(node, "The total bit size of a bit_field's fields (%llu) must fit into its backing type's (%s) bit size of %llu",
|
||||
cast(unsigned long long)total_bit_size,
|
||||
s,
|
||||
cast(unsigned long long)maximum_bit_size);
|
||||
@@ -1428,6 +1439,10 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special
|
||||
bool can_convert = check_cast_internal(ctx, &o, specialization);
|
||||
return can_convert;
|
||||
} else if (t->kind == Type_Struct) {
|
||||
if (t->Struct.polymorphic_parent == nullptr &&
|
||||
t == s) {
|
||||
return true;
|
||||
}
|
||||
if (t->Struct.polymorphic_parent == specialization) {
|
||||
return true;
|
||||
}
|
||||
@@ -1477,6 +1492,10 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special
|
||||
return true;
|
||||
}
|
||||
} else if (t->kind == Type_Union) {
|
||||
if (t->Union.polymorphic_parent == nullptr &&
|
||||
t == s) {
|
||||
return true;
|
||||
}
|
||||
if (t->Union.polymorphic_parent == specialization) {
|
||||
return true;
|
||||
}
|
||||
@@ -3263,6 +3282,11 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
|
||||
case_end;
|
||||
|
||||
case_ast_node(pe, ParenExpr, e);
|
||||
if (pe->expr == nullptr) {
|
||||
error(e, "Expected an expression or type within the parentheses");
|
||||
*type = t_invalid;
|
||||
return true;
|
||||
}
|
||||
*type = check_type_expr(ctx, pe->expr, named_type);
|
||||
set_base_type(named_type, *type);
|
||||
return true;
|
||||
|
||||
+58
-34
@@ -12,7 +12,7 @@ struct ErrorValue {
|
||||
};
|
||||
|
||||
struct ErrorCollector {
|
||||
TokenPos prev;
|
||||
// TokenPos prev; // no point collecting because of the mulithreaded nature
|
||||
std::atomic<i64> count;
|
||||
std::atomic<i64> warning_count;
|
||||
std::atomic<bool> in_block;
|
||||
@@ -383,14 +383,13 @@ gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va
|
||||
}
|
||||
|
||||
push_error_value(pos, ErrorValue_Error);
|
||||
// NOTE(bill): Duplicate error, skip it
|
||||
if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
} else if (global_error_collector.prev != pos) {
|
||||
global_error_collector.prev = pos;
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
} else {
|
||||
@@ -402,10 +401,6 @@ gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
show_error_on_line(pos, end);
|
||||
} else {
|
||||
global_error_collector.curr_error_value = {};
|
||||
global_error_collector.curr_error_value_set.store(false);
|
||||
global_error_collector.count.fetch_sub(1);
|
||||
}
|
||||
try_pop_error_value();
|
||||
mutex_unlock(&global_error_collector.mutex);
|
||||
@@ -422,14 +417,13 @@ gb_internal void warning_va(TokenPos const &pos, TokenPos end, char const *fmt,
|
||||
push_error_value(pos, ErrorValue_Warning);
|
||||
|
||||
if (!global_ignore_warnings()) {
|
||||
// NOTE(bill): Duplicate error, skip it
|
||||
if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
} else if (global_error_collector.prev != pos) {
|
||||
global_error_collector.prev = pos;
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
} else {
|
||||
@@ -460,13 +454,12 @@ gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_li
|
||||
|
||||
push_error_value(pos, ErrorValue_Error);
|
||||
|
||||
// NOTE(bill): Duplicate error, skip it
|
||||
if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
|
||||
error_out_va(fmt, va);
|
||||
} else if (global_error_collector.prev != pos) {
|
||||
global_error_collector.prev = pos;
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
} else {
|
||||
@@ -493,9 +486,13 @@ gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const *
|
||||
|
||||
push_error_value(pos, ErrorValue_Warning);
|
||||
|
||||
// NOTE(bill): Duplicate error, skip it
|
||||
if (global_error_collector.prev != pos) {
|
||||
global_error_collector.prev = pos;
|
||||
if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
} else {
|
||||
@@ -505,11 +502,6 @@ gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const *
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
show_error_on_line(pos, end);
|
||||
} else if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
}
|
||||
|
||||
try_pop_error_value();
|
||||
@@ -526,14 +518,13 @@ gb_internal void syntax_error_with_verbose_va(TokenPos const &pos, TokenPos end,
|
||||
|
||||
push_error_value(pos, ErrorValue_Warning);
|
||||
|
||||
// NOTE(bill): Duplicate error, skip it
|
||||
if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Syntax_Error: ", TerminalStyle_Normal, TerminalColour_Red);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
} else if (global_error_collector.prev != pos) {
|
||||
global_error_collector.prev = pos;
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
} else {
|
||||
@@ -564,9 +555,13 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const
|
||||
push_error_value(pos, ErrorValue_Warning);
|
||||
|
||||
if (!global_ignore_warnings()) {
|
||||
// NOTE(bill): Duplicate error, skip it
|
||||
if (global_error_collector.prev != pos) {
|
||||
global_error_collector.prev = pos;
|
||||
if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
} else {
|
||||
@@ -576,11 +571,6 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
// show_error_on_line(pos, end);
|
||||
} else if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -705,9 +695,42 @@ gb_internal void print_all_errors(void) {
|
||||
|
||||
GB_ASSERT(any_errors() || any_warnings());
|
||||
|
||||
|
||||
array_sort(global_error_collector.error_values, error_value_cmp);
|
||||
|
||||
|
||||
{ // NOTE(bill): merge neighbouring errors
|
||||
isize default_lines_to_skip = 1;
|
||||
if (show_error_line()) {
|
||||
// NOTE(bill): this will always be 2 extra lines
|
||||
default_lines_to_skip += 2;
|
||||
}
|
||||
|
||||
ErrorValue *prev_ev = nullptr;
|
||||
for (isize i = 0; i < global_error_collector.error_values.count; /**/) {
|
||||
ErrorValue &ev = global_error_collector.error_values[i];
|
||||
|
||||
if (prev_ev && prev_ev->pos == ev.pos) {
|
||||
String_Iterator it = {{ev.msg.data, ev.msg.count}, 0};
|
||||
|
||||
for (isize lines_to_skip = default_lines_to_skip; lines_to_skip > 0; lines_to_skip -= 1) {
|
||||
String line = string_split_iterator(&it, '\n');
|
||||
if (line.len == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (it.str.len-it.pos > 0) {
|
||||
array_add_elems(&prev_ev->msg, it.str.text+it.pos, it.str.len-it.pos);
|
||||
}
|
||||
array_free(&ev.msg);
|
||||
array_ordered_remove(&global_error_collector.error_values, i);
|
||||
} else {
|
||||
prev_ev = &ev;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gbString res = gb_string_make(heap_allocator(), "");
|
||||
defer (gb_string_free(res));
|
||||
|
||||
@@ -715,6 +738,7 @@ gb_internal void print_all_errors(void) {
|
||||
res = gb_string_append_fmt(res, "{\n");
|
||||
res = gb_string_append_fmt(res, "\t\"error_count\": %td,\n", global_error_collector.error_values.count);
|
||||
res = gb_string_append_fmt(res, "\t\"errors\": [\n");
|
||||
|
||||
for_array(i, global_error_collector.error_values) {
|
||||
ErrorValue ev = global_error_collector.error_values[i];
|
||||
|
||||
|
||||
@@ -581,6 +581,10 @@ gb_internal LLVMTypeRef llvm_array_type(LLVMTypeRef ElementType, uint64_t Elemen
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
gb_internal void lb_set_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name, u64 value);
|
||||
gb_internal u64 lb_get_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name);
|
||||
|
||||
#define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
|
||||
#define LB_CLEANUP_RUNTIME_PROC_NAME "__$cleanup_runtime"
|
||||
#define LB_TYPE_INFO_DATA_NAME "__$type_info_data"
|
||||
@@ -719,4 +723,4 @@ gb_global char const *llvm_linkage_strings[] = {
|
||||
"linker private weak linkage"
|
||||
};
|
||||
|
||||
#define ODIN_METADATA_REQUIRE "odin-metadata-require", 21
|
||||
#define ODIN_METADATA_IS_PACKED str_lit("odin-is-packed")
|
||||
@@ -1107,6 +1107,12 @@ gb_internal lbValue lb_emit_load(lbProcedure *p, lbValue value) {
|
||||
GB_ASSERT(is_type_pointer(value.type));
|
||||
Type *t = type_deref(value.type);
|
||||
LLVMValueRef v = LLVMBuildLoad2(p->builder, lb_type(p->module, t), value.value, "");
|
||||
|
||||
u64 is_packed = lb_get_metadata_custom_u64(p->module, value.value, ODIN_METADATA_IS_PACKED);
|
||||
if (is_packed != 0) {
|
||||
LLVMSetAlignment(v, 1);
|
||||
}
|
||||
|
||||
return lbValue{v, t};
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,29 @@ gb_internal lbValue lb_correct_endianness(lbProcedure *p, lbValue value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
gb_internal void lb_set_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name, u64 value) {
|
||||
unsigned md_id = LLVMGetMDKindIDInContext(m->ctx, cast(char const *)name.text, cast(unsigned)name.len);
|
||||
LLVMMetadataRef md = LLVMValueAsMetadata(LLVMConstInt(lb_type(m, t_u64), value, false));
|
||||
LLVMValueRef node = LLVMMetadataAsValue(m->ctx, LLVMMDNodeInContext2(m->ctx, &md, 1));
|
||||
LLVMSetMetadata(v_ref, md_id, node);
|
||||
}
|
||||
gb_internal u64 lb_get_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name) {
|
||||
unsigned md_id = LLVMGetMDKindIDInContext(m->ctx, cast(char const *)name.text, cast(unsigned)name.len);
|
||||
LLVMValueRef v_md = LLVMGetMetadata(v_ref, md_id);
|
||||
if (v_md == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
unsigned node_count = LLVMGetMDNodeNumOperands(v_md);
|
||||
if (node_count == 0) {
|
||||
return 0;
|
||||
}
|
||||
GB_ASSERT(node_count == 1);
|
||||
LLVMValueRef value = nullptr;
|
||||
LLVMGetMDNodeOperands(v_md, &value);
|
||||
return LLVMConstIntGetZExtValue(value);
|
||||
}
|
||||
|
||||
gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile) {
|
||||
return lb_mem_zero_ptr_internal(p, ptr, LLVMConstInt(lb_type(p->module, t_uint), len, false), alignment, is_volatile);
|
||||
}
|
||||
@@ -1148,7 +1171,15 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
|
||||
|
||||
GB_ASSERT_MSG(result_type != nullptr, "%s %d", type_to_string(t), index);
|
||||
|
||||
return lb_emit_struct_ep_internal(p, s, index, result_type);
|
||||
lbValue gep = lb_emit_struct_ep_internal(p, s, index, result_type);
|
||||
|
||||
Type *bt = base_type(t);
|
||||
if (bt->kind == Type_Struct && bt->Struct.is_packed) {
|
||||
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1);
|
||||
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1);
|
||||
}
|
||||
|
||||
return gep;
|
||||
}
|
||||
|
||||
gb_internal lbValue lb_emit_tuple_ev(lbProcedure *p, lbValue value, i32 index) {
|
||||
|
||||
@@ -3499,6 +3499,10 @@ gb_internal Ast *parse_type(AstFile *f) {
|
||||
Token token = advance_token(f);
|
||||
syntax_error(token, "Expected a type");
|
||||
return ast_bad_expr(f, token, f->curr_token);
|
||||
} else if (type->kind == Ast_ParenExpr &&
|
||||
unparen_expr(type) == nullptr) {
|
||||
syntax_error(type, "Expected a type within the parentheses");
|
||||
return ast_bad_expr(f, type->ParenExpr.open, type->ParenExpr.close);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user