| author | |
| committer | |
| log | d94cb0566be6463594f0904aa759de9e52585842 |
| tree | 470044a3b58fbeee7e270617da76fca54b3a6f0f |
| parent | bf7cde62c52b370f953db2cd6167a156771d8343 |
7 files changed, 33 insertions(+), 56 deletions(-)
doc/langref.md+4-6| ... | @@ -404,7 +404,7 @@ Function Operation | ... | @@ -404,7 +404,7 @@ Function Operation |
| 404 | @shlWithOverflow(inline T: type, a: T, b: T, result: &T) -> bool *x = a << b | 404 | @shlWithOverflow(inline T: type, a: T, b: T, result: &T) -> bool *x = a << b |
| 405 | ``` | 405 | ``` |
| 406 | 406 | ||
| 407 | ### @memset(dest, c: u8, byte_count: usize) | 407 | ### @memset(dest: &T, c: u8, byte_count: usize) |
| 408 | 408 | ||
| 409 | This function sets a region of memory to `c`. `dest` is a pointer. | 409 | This function sets a region of memory to `c`. `dest` is a pointer. |
| 410 | 410 | ||
| ... | @@ -412,11 +412,10 @@ This function is a low level intrinsic with no safety mechanisms. Most higher | ... | @@ -412,11 +412,10 @@ This function is a low level intrinsic with no safety mechanisms. Most higher |
| 412 | level code will not use this function, instead using something like this: | 412 | level code will not use this function, instead using something like this: |
| 413 | 413 | ||
| 414 | ```zig | 414 | ```zig |
| 415 | // assume dest is a slice | 415 | for (destSlice) |*b| *b = c; |
| 416 | for (dest) |*b| *b = c; | ||
| 417 | ``` | 416 | ``` |
| 418 | 417 | ||
| 419 | ### @memcpy(dest, source, byte_count: usize) | 418 | ### @memcpy(noalias dest: &T, noalias source: &const T, byte_count: usize) |
| 420 | 419 | ||
| 421 | This function copies bytes from one region of memory to another. `dest` and | 420 | This function copies bytes from one region of memory to another. `dest` and |
| 422 | `source` are both pointers and must not overlap. | 421 | `source` are both pointers and must not overlap. |
| ... | @@ -426,8 +425,7 @@ level code will not use this function, instead using something like this: | ... | @@ -426,8 +425,7 @@ level code will not use this function, instead using something like this: |
| 426 | 425 | ||
| 427 | ```zig | 426 | ```zig |
| 428 | const mem = @import("std").mem; | 427 | const mem = @import("std").mem; |
| 429 | // assume dest and source are slices | 428 | mem.copy(destSlice, sourceSlice); |
| 430 | mem.copy(dest, source); | ||
| 431 | ``` | 429 | ``` |
| 432 | 430 | ||
| 433 | ### @breakpoint() | 431 | ### @breakpoint() |
src/all_types.hpp-2| ... | @@ -870,7 +870,6 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id); | ... | @@ -870,7 +870,6 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id); |
| 870 | bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b); | 870 | bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b); |
| 871 | 871 | ||
| 872 | 872 | ||
| 873 | static const size_t fn_type_id_prealloc_param_info_count = 4; | ||
| 874 | struct FnTypeId { | 873 | struct FnTypeId { |
| 875 | TypeTableEntry *return_type; | 874 | TypeTableEntry *return_type; |
| 876 | FnTypeParamInfo *param_info; | 875 | FnTypeParamInfo *param_info; |
| ... | @@ -879,7 +878,6 @@ struct FnTypeId { | ... | @@ -879,7 +878,6 @@ struct FnTypeId { |
| 879 | bool is_naked; | 878 | bool is_naked; |
| 880 | bool is_cold; | 879 | bool is_cold; |
| 881 | bool is_extern; | 880 | bool is_extern; |
| 882 | FnTypeParamInfo prealloc_param_info[fn_type_id_prealloc_param_info_count]; | ||
| 883 | }; | 881 | }; |
| 884 | 882 | ||
| 885 | uint32_t fn_type_id_hash(FnTypeId*); | 883 | uint32_t fn_type_id_hash(FnTypeId*); |
src/analyze.cpp+1-9| ... | @@ -682,9 +682,6 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id, bool gen_debug_inf | ... | @@ -682,9 +682,6 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id, bool gen_debug_inf |
| 682 | TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn); | 682 | TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn); |
| 683 | fn_type->deep_const = true; | 683 | fn_type->deep_const = true; |
| 684 | fn_type->data.fn.fn_type_id = *fn_type_id; | 684 | fn_type->data.fn.fn_type_id = *fn_type_id; |
| 685 | if (fn_type_id->param_info == &fn_type_id->prealloc_param_info[0]) { | ||
| 686 | fn_type->data.fn.fn_type_id.param_info = &fn_type->data.fn.fn_type_id.prealloc_param_info[0]; | ||
| 687 | } | ||
| 688 | 685 | ||
| 689 | if (fn_type_id->is_cold) { | 686 | if (fn_type_id->is_cold) { |
| 690 | fn_type->data.fn.calling_convention = LLVMColdCallConv; | 687 | fn_type->data.fn.calling_convention = LLVMColdCallConv; |
| ... | @@ -915,12 +912,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor | ... | @@ -915,12 +912,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor |
| 915 | fn_type_id.is_naked = is_naked; | 912 | fn_type_id.is_naked = is_naked; |
| 916 | fn_type_id.is_cold = is_cold; | 913 | fn_type_id.is_cold = is_cold; |
| 917 | fn_type_id.param_count = fn_proto->params.length; | 914 | fn_type_id.param_count = fn_proto->params.length; |
| 918 | 915 | fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count); | |
| 919 | if (fn_type_id.param_count > fn_type_id_prealloc_param_info_count) { | ||
| 920 | fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count); | ||
| 921 | } else { | ||
| 922 | fn_type_id.param_info = &fn_type_id.prealloc_param_info[0]; | ||
| 923 | } | ||
| 924 | 916 | ||
| 925 | fn_type_id.is_var_args = fn_proto->is_var_args; | 917 | fn_type_id.is_var_args = fn_proto->is_var_args; |
| 926 | fn_type_id.return_type = analyze_type_expr(g, import, context, fn_proto->return_type); | 918 | fn_type_id.return_type = analyze_type_expr(g, import, context, fn_proto->return_type); |
src/codegen.cpp+15-25| ... | @@ -1483,7 +1483,8 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn | ... | @@ -1483,7 +1483,8 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn |
| 1483 | } | 1483 | } |
| 1484 | 1484 | ||
| 1485 | static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) { | 1485 | static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) { |
| 1486 | LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array_ptr); | 1486 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); |
| 1487 | LLVMValueRef array_ptr = LLVMBuildLoad(g->builder, array_ptr_ptr, ""); | ||
| 1487 | LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index); | 1488 | LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index); |
| 1488 | TypeTableEntry *array_type = instruction->array_ptr->type_entry; | 1489 | TypeTableEntry *array_type = instruction->array_ptr->type_entry; |
| 1489 | return gen_array_elem_ptr(g, instruction->base.source_node, array_ptr, array_type, subscript_value); | 1490 | return gen_array_elem_ptr(g, instruction->base.source_node, array_ptr, array_type, subscript_value); |
| ... | @@ -3265,19 +3266,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { | ... | @@ -3265,19 +3266,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { |
| 3265 | } | 3266 | } |
| 3266 | } | 3267 | } |
| 3267 | 3268 | ||
| 3268 | static void get_c_type_node(CodeGen *g, AstNode *type_node, Buf *out_buf) { | ||
| 3269 | Expr *expr = get_resolved_expr(type_node); | ||
| 3270 | assert(expr->instruction->type_entry); | ||
| 3271 | assert(expr->instruction->type_entry->id == TypeTableEntryIdMetaType); | ||
| 3272 | |||
| 3273 | ConstExprValue *const_val = &expr->instruction->static_value; | ||
| 3274 | assert(const_val->special != ConstValSpecialRuntime); | ||
| 3275 | |||
| 3276 | TypeTableEntry *type_entry = const_val->data.x_type; | ||
| 3277 | |||
| 3278 | return get_c_type(g, type_entry, out_buf); | ||
| 3279 | } | ||
| 3280 | |||
| 3281 | void codegen_generate_h_file(CodeGen *g) { | 3269 | void codegen_generate_h_file(CodeGen *g) { |
| 3282 | assert(!g->is_test_build); | 3270 | assert(!g->is_test_build); |
| 3283 | 3271 | ||
| ... | @@ -3303,25 +3291,27 @@ void codegen_generate_h_file(CodeGen *g) { | ... | @@ -3303,25 +3291,27 @@ void codegen_generate_h_file(CodeGen *g) { |
| 3303 | if (fn_proto->top_level_decl.visib_mod != VisibModExport) | 3291 | if (fn_proto->top_level_decl.visib_mod != VisibModExport) |
| 3304 | continue; | 3292 | continue; |
| 3305 | 3293 | ||
| 3294 | FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id; | ||
| 3306 | Buf return_type_c = BUF_INIT; | 3295 | Buf return_type_c = BUF_INIT; |
| 3307 | get_c_type(g, fn_table_entry->type_entry->data.fn.fn_type_id.return_type, &return_type_c); | 3296 | get_c_type(g, fn_type_id->return_type, &return_type_c); |
| 3308 | 3297 | ||
| 3309 | buf_appendf(&h_buf, "%s %s %s(", | 3298 | buf_appendf(&h_buf, "%s %s %s(", |
| 3310 | buf_ptr(export_macro), | 3299 | buf_ptr(export_macro), |
| 3311 | buf_ptr(&return_type_c), | 3300 | buf_ptr(&return_type_c), |
| 3312 | buf_ptr(fn_proto->name)); | 3301 | buf_ptr(&fn_table_entry->symbol_name)); |
| 3313 | 3302 | ||
| 3314 | Buf param_type_c = BUF_INIT; | 3303 | Buf param_type_c = BUF_INIT; |
| 3315 | if (fn_proto->params.length) { | 3304 | if (fn_type_id->param_count > 0) { |
| 3316 | for (size_t param_i = 0; param_i < fn_proto->params.length; param_i += 1) { | 3305 | for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) { |
| 3306 | FnTypeParamInfo *param_info = &fn_type_id->param_info[param_i]; | ||
| 3317 | AstNode *param_decl_node = fn_proto->params.at(param_i); | 3307 | AstNode *param_decl_node = fn_proto->params.at(param_i); |
| 3318 | AstNode *param_type = param_decl_node->data.param_decl.type; | 3308 | Buf *param_name = param_decl_node->data.param_decl.name; |
| 3319 | get_c_type_node(g, param_type, &param_type_c); | 3309 | |
| 3320 | buf_appendf(&h_buf, "%s %s", | 3310 | const char *comma_str = (param_i == 0) ? "" : ", "; |
| 3321 | buf_ptr(&param_type_c), | 3311 | const char *restrict_str = param_info->is_noalias ? "restrict" : ""; |
| 3322 | buf_ptr(param_decl_node->data.param_decl.name)); | 3312 | get_c_type(g, param_info->type, &param_type_c); |
| 3323 | if (param_i < fn_proto->params.length - 1) | 3313 | buf_appendf(&h_buf, "%s%s%s %s", comma_str, buf_ptr(&param_type_c), |
| 3324 | buf_appendf(&h_buf, ", "); | 3314 | restrict_str, buf_ptr(param_name)); |
| 3325 | } | 3315 | } |
| 3326 | buf_appendf(&h_buf, ")"); | 3316 | buf_appendf(&h_buf, ")"); |
| 3327 | } else { | 3317 | } else { |
src/ir.cpp+6-2| ... | @@ -36,6 +36,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont | ... | @@ -36,6 +36,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont |
| 36 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); | 36 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 37 | 37 | ||
| 38 | ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) { | 38 | ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) { |
| 39 | assert(const_val->special == ConstValSpecialStatic); | ||
| 39 | ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr; | 40 | ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr; |
| 40 | size_t index = const_val->data.x_ptr.index; | 41 | size_t index = const_val->data.x_ptr.index; |
| 41 | 42 | ||
| ... | @@ -3620,7 +3621,6 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -3620,7 +3621,6 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 3620 | assert(ptr_type->id == TypeTableEntryIdPointer); | 3621 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 3621 | 3622 | ||
| 3622 | TypeTableEntry *array_type = ptr_type->data.pointer.child_type; | 3623 | TypeTableEntry *array_type = ptr_type->data.pointer.child_type; |
| 3623 | ConstExprValue *array_ptr_val = const_ptr_pointee(&array_ptr->static_value); | ||
| 3624 | TypeTableEntry *return_type; | 3624 | TypeTableEntry *return_type; |
| 3625 | 3625 | ||
| 3626 | if (array_type->id == TypeTableEntryIdInvalid) { | 3626 | if (array_type->id == TypeTableEntryIdInvalid) { |
| ... | @@ -3659,7 +3659,11 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -3659,7 +3659,11 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 3659 | } | 3659 | } |
| 3660 | } | 3660 | } |
| 3661 | 3661 | ||
| 3662 | if (array_ptr_val->special != ConstValSpecialRuntime) { | 3662 | ConstExprValue *array_ptr_val; |
| 3663 | if (array_ptr->static_value.special != ConstValSpecialRuntime && | ||
| 3664 | (array_ptr_val = const_ptr_pointee(&array_ptr->static_value)) && | ||
| 3665 | array_ptr_val->special != ConstValSpecialRuntime) | ||
| 3666 | { | ||
| 3663 | bool depends_on_compile_var = array_ptr_val->depends_on_compile_var || | 3667 | bool depends_on_compile_var = array_ptr_val->depends_on_compile_var || |
| 3664 | casted_elem_index->static_value.depends_on_compile_var; | 3668 | casted_elem_index->static_value.depends_on_compile_var; |
| 3665 | ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var); | 3669 | ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var); |
src/parseh.cpp+1-6| ... | @@ -602,12 +602,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const | ... | @@ -602,12 +602,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 602 | } | 602 | } |
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | if (fn_type_id.param_count > fn_type_id_prealloc_param_info_count) { | 605 | fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count); |
| 606 | fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count); | ||
| 607 | } else { | ||
| 608 | fn_type_id.param_info = &fn_type_id.prealloc_param_info[0]; | ||
| 609 | } | ||
| 610 | |||
| 611 | for (size_t i = 0; i < fn_type_id.param_count; i += 1) { | 606 | for (size_t i = 0; i < fn_type_id.param_count; i += 1) { |
| 612 | QualType qt = fn_proto_ty->getParamType(i); | 607 | QualType qt = fn_proto_ty->getParamType(i); |
| 613 | TypeTableEntry *param_type = resolve_qual_type(c, qt, decl); | 608 | TypeTableEntry *param_type = resolve_qual_type(c, qt, decl); |
std/builtin.zig+6-6| ... | @@ -1,24 +1,24 @@ | ... | @@ -1,24 +1,24 @@ |
| 1 | // These functions are provided when not linking against libc because LLVM | 1 | // These functions are provided when not linking against libc because LLVM |
| 2 | // sometimes generates code that calls them. | 2 | // sometimes generates code that calls them. |
| 3 | 3 | ||
| 4 | // TODO dest should be nullable and return value should be nullable | ||
| 4 | export fn memset(dest: &u8, c: u8, n: usize) -> &u8 { | 5 | export fn memset(dest: &u8, c: u8, n: usize) -> &u8 { |
| 5 | @setDebugSafety(this, false); | 6 | @setDebugSafety(this, false); |
| 6 | 7 | ||
| 7 | var index: usize = 0; | 8 | var index: usize = 0; |
| 8 | while (index != n) { | 9 | while (index != n; index += 1) |
| 9 | dest[index] = c; | 10 | dest[index] = c; |
| 10 | index += 1; | 11 | |
| 11 | } | ||
| 12 | return dest; | 12 | return dest; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | // TODO dest, source, and return value should be nullable | ||
| 15 | export fn memcpy(noalias dest: &u8, noalias src: &const u8, n: usize) -> &u8 { | 16 | export fn memcpy(noalias dest: &u8, noalias src: &const u8, n: usize) -> &u8 { |
| 16 | @setDebugSafety(this, false); | 17 | @setDebugSafety(this, false); |
| 17 | 18 | ||
| 18 | var index: usize = 0; | 19 | var index: usize = 0; |
| 19 | while (index != n) { | 20 | while (index != n; index += 1) |
| 20 | dest[index] = src[index]; | 21 | dest[index] = src[index]; |
| 21 | index += 1; | 22 | |
| 22 | } | ||
| 23 | return dest; | 23 | return dest; |
| 24 | } | 24 | } |