mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 07:08:48 +00:00
Merge branch 'master' of https://github.com/odin-lang/Odin
This commit is contained in:
@@ -406,6 +406,9 @@ unmarshal_expect_token :: proc(p: ^Parser, kind: Token_Kind, loc := #caller_loca
|
|||||||
return prev
|
return prev
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Struct tags can include not only the name of the JSON key, but also a tag such as `omitempty`.
|
||||||
|
// Example: `json:"key_name,omitempty"`
|
||||||
|
// This returns the first field as `json_name`, and the rest are returned as `extra`.
|
||||||
@(private)
|
@(private)
|
||||||
json_name_from_tag_value :: proc(value: string) -> (json_name, extra: string) {
|
json_name_from_tag_value :: proc(value: string) -> (json_name, extra: string) {
|
||||||
json_name = value
|
json_name = value
|
||||||
@@ -441,12 +444,6 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
|
|||||||
defer delete(key, p.allocator)
|
defer delete(key, p.allocator)
|
||||||
|
|
||||||
unmarshal_expect_token(p, .Colon)
|
unmarshal_expect_token(p, .Colon)
|
||||||
|
|
||||||
field_test :: #force_inline proc "contextless" (field_used: [^]byte, offset: uintptr) -> bool {
|
|
||||||
prev_set := field_used[offset/8] & byte(offset&7) != 0
|
|
||||||
field_used[offset/8] |= byte(offset&7)
|
|
||||||
return prev_set
|
|
||||||
}
|
|
||||||
|
|
||||||
field_used_bytes := (reflect.size_of_typeid(ti.id)+7)/8
|
field_used_bytes := (reflect.size_of_typeid(ti.id)+7)/8
|
||||||
field_used := intrinsics.alloca(field_used_bytes + 1, 1) // + 1 to not overflow on size_of 0 types.
|
field_used := intrinsics.alloca(field_used_bytes + 1, 1) // + 1 to not overflow on size_of 0 types.
|
||||||
@@ -465,7 +462,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
|
|||||||
|
|
||||||
if use_field_idx < 0 {
|
if use_field_idx < 0 {
|
||||||
for field, field_idx in fields {
|
for field, field_idx in fields {
|
||||||
if key == field.name {
|
tag_value := reflect.struct_tag_get(field.tag, "json")
|
||||||
|
json_name, _ := json_name_from_tag_value(tag_value)
|
||||||
|
if json_name == "" && key == field.name {
|
||||||
use_field_idx = field_idx
|
use_field_idx = field_idx
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -486,7 +485,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.name == key || (field.tag != "" && reflect.struct_tag_get(field.tag, "json") == key) {
|
tag_value := reflect.struct_tag_get(field.tag, "json")
|
||||||
|
json_name, _ := json_name_from_tag_value(tag_value)
|
||||||
|
if (json_name == "" && field.name == key) || json_name == key {
|
||||||
offset = field.offset
|
offset = field.offset
|
||||||
type = field.type
|
type = field.type
|
||||||
found = true
|
found = true
|
||||||
@@ -508,6 +509,11 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
|
|||||||
}
|
}
|
||||||
|
|
||||||
if field_found {
|
if field_found {
|
||||||
|
field_test :: #force_inline proc "contextless" (field_used: [^]byte, offset: uintptr) -> bool {
|
||||||
|
prev_set := field_used[offset/8] & byte(offset&7) != 0
|
||||||
|
field_used[offset/8] |= byte(offset&7)
|
||||||
|
return prev_set
|
||||||
|
}
|
||||||
if field_test(field_used, offset) {
|
if field_test(field_used, offset) {
|
||||||
return .Multiple_Use_Field
|
return .Multiple_Use_Field
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,8 @@ package all
|
|||||||
|
|
||||||
import linux "core:sys/linux"
|
import linux "core:sys/linux"
|
||||||
|
|
||||||
_ :: linux
|
import xlib "vendor:x11/xlib"
|
||||||
|
|
||||||
|
_ :: linux
|
||||||
|
|
||||||
|
_ :: xlib
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import nvg "vendor:nanovg"
|
|||||||
import nvg_gl "vendor:nanovg/gl"
|
import nvg_gl "vendor:nanovg/gl"
|
||||||
import fontstash "vendor:fontstash"
|
import fontstash "vendor:fontstash"
|
||||||
|
|
||||||
import xlib "vendor:x11/xlib"
|
|
||||||
|
|
||||||
_ :: cgltf
|
_ :: cgltf
|
||||||
// _ :: commonmark
|
// _ :: commonmark
|
||||||
_ :: ENet
|
_ :: ENet
|
||||||
@@ -57,8 +55,6 @@ _ :: nvg
|
|||||||
_ :: nvg_gl
|
_ :: nvg_gl
|
||||||
_ :: fontstash
|
_ :: fontstash
|
||||||
|
|
||||||
_ :: xlib
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE: needed for doc generator
|
// NOTE: needed for doc generator
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1246,7 +1246,7 @@ namespace lbAbiArm64 {
|
|||||||
cast_type = LLVMIntTypeInContext(c, cast(unsigned)(size*8));
|
cast_type = LLVMIntTypeInContext(c, cast(unsigned)(size*8));
|
||||||
} else {
|
} else {
|
||||||
LLVMTypeRef llvm_i64 = LLVMIntTypeInContext(c, 64);
|
LLVMTypeRef llvm_i64 = LLVMIntTypeInContext(c, 64);
|
||||||
cast_type = LLVMArrayType2(llvm_i64, 2);
|
cast_type = llvm_array_type(llvm_i64, 2);
|
||||||
}
|
}
|
||||||
return lb_arg_type_direct(return_type, cast_type, nullptr, nullptr);
|
return lb_arg_type_direct(return_type, cast_type, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1295,3 +1295,59 @@ gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gb_internal void lb_add_debug_label(lbProcedure *p, Ast *label, lbBlock *target) {
|
||||||
|
// NOTE(tf2spi): LLVM-C DILabel API used only existed for major versions 20+
|
||||||
|
#if LLVM_VERSION_MAJOR >= 20
|
||||||
|
if (p == nullptr || p->debug_info == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (target == nullptr || label == nullptr || label->kind != Ast_Label) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Token label_token = label->Label.token;
|
||||||
|
if (is_blank_ident(label_token.string)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lbModule *m = p->module;
|
||||||
|
if (m == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstFile *file = label->file();
|
||||||
|
LLVMMetadataRef llvm_file = lb_get_llvm_metadata(m, file);
|
||||||
|
if (llvm_file == nullptr) {
|
||||||
|
debugf("llvm file not found for label\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LLVMMetadataRef llvm_scope = p->debug_info;
|
||||||
|
if(llvm_scope == nullptr) {
|
||||||
|
debugf("llvm scope not found for label\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, label_token.pos);
|
||||||
|
LLVMBasicBlockRef llvm_block = target->block;
|
||||||
|
if (llvm_block == nullptr || llvm_debug_loc == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LLVMMetadataRef llvm_label = LLVMDIBuilderCreateLabel(
|
||||||
|
m->debug_builder,
|
||||||
|
llvm_scope,
|
||||||
|
(const char *)label_token.string.text,
|
||||||
|
(size_t)label_token.string.len,
|
||||||
|
llvm_file,
|
||||||
|
label_token.pos.line,
|
||||||
|
|
||||||
|
// NOTE(tf2spi): Defaults to false in LLVM API, but I'd rather not take chances
|
||||||
|
// Always preserve the label no matter what when debugging
|
||||||
|
true
|
||||||
|
);
|
||||||
|
GB_ASSERT(llvm_label != nullptr);
|
||||||
|
(void)LLVMDIBuilderInsertLabelAtEnd(
|
||||||
|
m->debug_builder,
|
||||||
|
llvm_label,
|
||||||
|
llvm_debug_loc,
|
||||||
|
llvm_block
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -136,7 +136,6 @@ gb_internal lbBranchBlocks lb_lookup_branch_blocks(lbProcedure *p, Ast *ident) {
|
|||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_internal lbTargetList *lb_push_target_list(lbProcedure *p, Ast *label, lbBlock *break_, lbBlock *continue_, lbBlock *fallthrough_) {
|
gb_internal lbTargetList *lb_push_target_list(lbProcedure *p, Ast *label, lbBlock *break_, lbBlock *continue_, lbBlock *fallthrough_) {
|
||||||
lbTargetList *tl = gb_alloc_item(permanent_allocator(), lbTargetList);
|
lbTargetList *tl = gb_alloc_item(permanent_allocator(), lbTargetList);
|
||||||
tl->prev = p->target_list;
|
tl->prev = p->target_list;
|
||||||
@@ -688,6 +687,18 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node,
|
|||||||
lbBlock *body = lb_create_block(p, "for.interval.body");
|
lbBlock *body = lb_create_block(p, "for.interval.body");
|
||||||
lbBlock *done = lb_create_block(p, "for.interval.done");
|
lbBlock *done = lb_create_block(p, "for.interval.done");
|
||||||
|
|
||||||
|
// TODO(tf2spi): This is inlined in more than several places.
|
||||||
|
// Putting this in a function might be preferred.
|
||||||
|
// LLVMSetCurrentDebugLocation2 has side effects,
|
||||||
|
// so I didn't want to hide that before it got reviewed.
|
||||||
|
if (rs->label != nullptr && p->debug_info != nullptr) {
|
||||||
|
lbBlock *label = lb_create_block(p, "for.interval.label");
|
||||||
|
lb_emit_jump(p, label);
|
||||||
|
lb_start_block(p, label);
|
||||||
|
|
||||||
|
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, rs->label));
|
||||||
|
lb_add_debug_label(p, rs->label, label);
|
||||||
|
}
|
||||||
lb_emit_jump(p, loop);
|
lb_emit_jump(p, loop);
|
||||||
lb_start_block(p, loop);
|
lb_start_block(p, loop);
|
||||||
|
|
||||||
@@ -893,6 +904,14 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs
|
|||||||
|
|
||||||
lbAddr index = lb_add_local_generated(p, t_int, false);
|
lbAddr index = lb_add_local_generated(p, t_int, false);
|
||||||
|
|
||||||
|
if (rs->label != nullptr && p->debug_info != nullptr) {
|
||||||
|
lbBlock *label = lb_create_block(p, "for.soa.label");
|
||||||
|
lb_emit_jump(p, label);
|
||||||
|
lb_start_block(p, label);
|
||||||
|
|
||||||
|
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, rs->label));
|
||||||
|
lb_add_debug_label(p, rs->label, label);
|
||||||
|
}
|
||||||
if (!is_reverse) {
|
if (!is_reverse) {
|
||||||
/*
|
/*
|
||||||
for x, i in array {
|
for x, i in array {
|
||||||
@@ -970,7 +989,6 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs
|
|||||||
lb_store_range_stmt_val(p, val1, lb_addr_load(p, index));
|
lb_store_range_stmt_val(p, val1, lb_addr_load(p, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lb_push_target_list(p, rs->label, done, loop, nullptr);
|
lb_push_target_list(p, rs->label, done, loop, nullptr);
|
||||||
|
|
||||||
lb_build_stmt(p, rs->body);
|
lb_build_stmt(p, rs->body);
|
||||||
@@ -1029,6 +1047,15 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
|
|||||||
lbBlock *done = nullptr;
|
lbBlock *done = nullptr;
|
||||||
bool is_map = false;
|
bool is_map = false;
|
||||||
|
|
||||||
|
if (rs->label != nullptr && p->debug_info != nullptr) {
|
||||||
|
lbBlock *label = lb_create_block(p, "for.range.label");
|
||||||
|
lb_emit_jump(p, label);
|
||||||
|
lb_start_block(p, label);
|
||||||
|
|
||||||
|
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, rs->label));
|
||||||
|
lb_add_debug_label(p, rs->label, label);
|
||||||
|
}
|
||||||
|
|
||||||
if (tav.mode == Addressing_Type) {
|
if (tav.mode == Addressing_Type) {
|
||||||
lb_build_range_enum(p, type_deref(tav.type), val0_type, &val, &key, &loop, &done);
|
lb_build_range_enum(p, type_deref(tav.type), val0_type, &val, &key, &loop, &done);
|
||||||
} else {
|
} else {
|
||||||
@@ -1530,6 +1557,14 @@ gb_internal bool lb_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss, boo
|
|||||||
gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *scope) {
|
gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *scope) {
|
||||||
lb_open_scope(p, scope);
|
lb_open_scope(p, scope);
|
||||||
|
|
||||||
|
if (ss->label != nullptr && p->debug_info != nullptr) {
|
||||||
|
lbBlock *label = lb_create_block(p, "switch.label");
|
||||||
|
lb_emit_jump(p, label);
|
||||||
|
lb_start_block(p, label);
|
||||||
|
|
||||||
|
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, ss->label));
|
||||||
|
lb_add_debug_label(p, ss->label, label);
|
||||||
|
}
|
||||||
if (ss->init != nullptr) {
|
if (ss->init != nullptr) {
|
||||||
lb_build_stmt(p, ss->init);
|
lb_build_stmt(p, ss->init);
|
||||||
}
|
}
|
||||||
@@ -1736,6 +1771,7 @@ gb_internal lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValu
|
|||||||
gb_internal void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBlock *body, lbBlock *done) {
|
gb_internal void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBlock *body, lbBlock *done) {
|
||||||
ast_node(cc, CaseClause, clause);
|
ast_node(cc, CaseClause, clause);
|
||||||
|
|
||||||
|
// NOTE(tf2spi): Debug info for label not generated here on purpose
|
||||||
lb_push_target_list(p, label, done, nullptr, nullptr);
|
lb_push_target_list(p, label, done, nullptr, nullptr);
|
||||||
lb_build_stmt_list(p, cc->stmts);
|
lb_build_stmt_list(p, cc->stmts);
|
||||||
lb_close_scope(p, lbDeferExit_Default, body, clause);
|
lb_close_scope(p, lbDeferExit_Default, body, clause);
|
||||||
@@ -2307,6 +2343,14 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
|
|||||||
else_ = lb_create_block(p, "if.else");
|
else_ = lb_create_block(p, "if.else");
|
||||||
}
|
}
|
||||||
if (is->label != nullptr) {
|
if (is->label != nullptr) {
|
||||||
|
if (p->debug_info != nullptr) {
|
||||||
|
lbBlock *label = lb_create_block(p, "if.label");
|
||||||
|
lb_emit_jump(p, label);
|
||||||
|
lb_start_block(p, label);
|
||||||
|
|
||||||
|
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, is->label));
|
||||||
|
lb_add_debug_label(p, is->label, label);
|
||||||
|
}
|
||||||
lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr);
|
lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr);
|
||||||
tl->is_block = true;
|
tl->is_block = true;
|
||||||
}
|
}
|
||||||
@@ -2399,12 +2443,19 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) {
|
|||||||
|
|
||||||
lb_push_target_list(p, fs->label, done, post, nullptr);
|
lb_push_target_list(p, fs->label, done, post, nullptr);
|
||||||
|
|
||||||
|
if (fs->label != nullptr && p->debug_info != nullptr) {
|
||||||
|
lbBlock *label = lb_create_block(p, "for.label");
|
||||||
|
lb_emit_jump(p, label);
|
||||||
|
lb_start_block(p, label);
|
||||||
|
|
||||||
|
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, fs->label));
|
||||||
|
lb_add_debug_label(p, fs->label, label);
|
||||||
|
}
|
||||||
if (fs->init != nullptr) {
|
if (fs->init != nullptr) {
|
||||||
#if 1
|
|
||||||
lbBlock *init = lb_create_block(p, "for.init");
|
lbBlock *init = lb_create_block(p, "for.init");
|
||||||
lb_emit_jump(p, init);
|
lb_emit_jump(p, init);
|
||||||
lb_start_block(p, init);
|
lb_start_block(p, init);
|
||||||
#endif
|
|
||||||
lb_build_stmt(p, fs->init);
|
lb_build_stmt(p, fs->init);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2420,7 +2471,6 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) {
|
|||||||
lb_start_block(p, body);
|
lb_start_block(p, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lb_build_stmt(p, fs->body);
|
lb_build_stmt(p, fs->body);
|
||||||
|
|
||||||
lb_pop_target_list(p);
|
lb_pop_target_list(p);
|
||||||
@@ -2694,9 +2744,21 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
|
|||||||
|
|
||||||
|
|
||||||
case_ast_node(bs, BlockStmt, node);
|
case_ast_node(bs, BlockStmt, node);
|
||||||
|
lbBlock *body = nullptr;
|
||||||
lbBlock *done = nullptr;
|
lbBlock *done = nullptr;
|
||||||
if (bs->label != nullptr) {
|
if (bs->label != nullptr) {
|
||||||
|
if (p->debug_info != nullptr) {
|
||||||
|
lbBlock *label = lb_create_block(p, "block.label");
|
||||||
|
lb_emit_jump(p, label);
|
||||||
|
lb_start_block(p, label);
|
||||||
|
|
||||||
|
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, bs->label));
|
||||||
|
lb_add_debug_label(p, bs->label, label);
|
||||||
|
}
|
||||||
|
body = lb_create_block(p, "block.body");
|
||||||
done = lb_create_block(p, "block.done");
|
done = lb_create_block(p, "block.done");
|
||||||
|
lb_emit_jump(p, body);
|
||||||
|
lb_start_block(p, body);
|
||||||
lbTargetList *tl = lb_push_target_list(p, bs->label, done, nullptr, nullptr);
|
lbTargetList *tl = lb_push_target_list(p, bs->label, done, nullptr, nullptr);
|
||||||
tl->is_block = true;
|
tl->is_block = true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user