| 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 | 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 | 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 | 412 | level code will not use this function, instead using something like this: |
| 413 | 413 | |
| 414 | 414 | ```zig |
| 415 | // assume dest is a slice | |
| 416 | for (dest) |*b| *b = c; | |
| 415 | for (destSlice) |*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 | 420 | This function copies bytes from one region of memory to another. `dest` and |
| 422 | 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 | 425 | |
| 427 | 426 | ```zig |
| 428 | 427 | const mem = @import("std").mem; |
| 429 | // assume dest and source are slices | |
| 430 | mem.copy(dest, source); | |
| 428 | mem.copy(destSlice, sourceSlice); | |
| 431 | 429 | ``` |
| 432 | 430 | |
| 433 | 431 | ### @breakpoint() |
src/all_types.hpp-2| ... | ... | @@ -870,7 +870,6 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id); |
| 870 | 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 | 873 | struct FnTypeId { |
| 875 | 874 | TypeTableEntry *return_type; |
| 876 | 875 | FnTypeParamInfo *param_info; |
| ... | ... | @@ -879,7 +878,6 @@ struct FnTypeId { |
| 879 | 878 | bool is_naked; |
| 880 | 879 | bool is_cold; |
| 881 | 880 | bool is_extern; |
| 882 | FnTypeParamInfo prealloc_param_info[fn_type_id_prealloc_param_info_count]; | |
| 883 | 881 | }; |
| 884 | 882 | |
| 885 | 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 | 682 | TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn); |
| 683 | 683 | fn_type->deep_const = true; |
| 684 | 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 | 686 | if (fn_type_id->is_cold) { |
| 690 | 687 | fn_type->data.fn.calling_convention = LLVMColdCallConv; |
| ... | ... | @@ -915,12 +912,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor |
| 915 | 912 | fn_type_id.is_naked = is_naked; |
| 916 | 913 | fn_type_id.is_cold = is_cold; |
| 917 | 914 | fn_type_id.param_count = fn_proto->params.length; |
| 918 | ||
| 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 | } | |
| 915 | fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count); | |
| 924 | 916 | |
| 925 | 917 | fn_type_id.is_var_args = fn_proto->is_var_args; |
| 926 | 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 | 1483 | } |
| 1484 | 1484 | |
| 1485 | 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 | 1488 | LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index); |
| 1488 | 1489 | TypeTableEntry *array_type = instruction->array_ptr->type_entry; |
| 1489 | 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 | 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 | 3269 | void codegen_generate_h_file(CodeGen *g) { |
| 3282 | 3270 | assert(!g->is_test_build); |
| 3283 | 3271 | |
| ... | ... | @@ -3303,25 +3291,27 @@ void codegen_generate_h_file(CodeGen *g) { |
| 3303 | 3291 | if (fn_proto->top_level_decl.visib_mod != VisibModExport) |
| 3304 | 3292 | continue; |
| 3305 | 3293 | |
| 3294 | FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id; | |
| 3306 | 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 | 3298 | buf_appendf(&h_buf, "%s %s %s(", |
| 3310 | 3299 | buf_ptr(export_macro), |
| 3311 | 3300 | buf_ptr(&return_type_c), |
| 3312 | buf_ptr(fn_proto->name)); | |
| 3301 | buf_ptr(&fn_table_entry->symbol_name)); | |
| 3313 | 3302 | |
| 3314 | 3303 | Buf param_type_c = BUF_INIT; |
| 3315 | if (fn_proto->params.length) { | |
| 3316 | for (size_t param_i = 0; param_i < fn_proto->params.length; param_i += 1) { | |
| 3304 | if (fn_type_id->param_count > 0) { | |
| 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 | 3307 | AstNode *param_decl_node = fn_proto->params.at(param_i); |
| 3318 | AstNode *param_type = param_decl_node->data.param_decl.type; | |
| 3319 | get_c_type_node(g, param_type, &param_type_c); | |
| 3320 | buf_appendf(&h_buf, "%s %s", | |
| 3321 | buf_ptr(&param_type_c), | |
| 3322 | buf_ptr(param_decl_node->data.param_decl.name)); | |
| 3323 | if (param_i < fn_proto->params.length - 1) | |
| 3324 | buf_appendf(&h_buf, ", "); | |
| 3308 | Buf *param_name = param_decl_node->data.param_decl.name; | |
| 3309 | ||
| 3310 | const char *comma_str = (param_i == 0) ? "" : ", "; | |
| 3311 | const char *restrict_str = param_info->is_noalias ? "restrict" : ""; | |
| 3312 | get_c_type(g, param_info->type, &param_type_c); | |
| 3313 | buf_appendf(&h_buf, "%s%s%s %s", comma_str, buf_ptr(&param_type_c), | |
| 3314 | restrict_str, buf_ptr(param_name)); | |
| 3325 | 3315 | } |
| 3326 | 3316 | buf_appendf(&h_buf, ")"); |
| 3327 | 3317 | } else { |
src/ir.cpp+6-2| ... | ... | @@ -36,6 +36,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont |
| 36 | 36 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 37 | 37 | |
| 38 | 38 | ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) { |
| 39 | assert(const_val->special == ConstValSpecialStatic); | |
| 39 | 40 | ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr; |
| 40 | 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 | 3621 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 3621 | 3622 | |
| 3622 | 3623 | TypeTableEntry *array_type = ptr_type->data.pointer.child_type; |
| 3623 | ConstExprValue *array_ptr_val = const_ptr_pointee(&array_ptr->static_value); | |
| 3624 | 3624 | TypeTableEntry *return_type; |
| 3625 | 3625 | |
| 3626 | 3626 | if (array_type->id == TypeTableEntryIdInvalid) { |
| ... | ... | @@ -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 | 3667 | bool depends_on_compile_var = array_ptr_val->depends_on_compile_var || |
| 3664 | 3668 | casted_elem_index->static_value.depends_on_compile_var; |
| 3665 | 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 | 602 | } |
| 603 | 603 | } |
| 604 | 604 | |
| 605 | if (fn_type_id.param_count > fn_type_id_prealloc_param_info_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 | ||
| 605 | fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count); | |
| 611 | 606 | for (size_t i = 0; i < fn_type_id.param_count; i += 1) { |
| 612 | 607 | QualType qt = fn_proto_ty->getParamType(i); |
| 613 | 608 | TypeTableEntry *param_type = resolve_qual_type(c, qt, decl); |
std/builtin.zig+6-6| ... | ... | @@ -1,24 +1,24 @@ |
| 1 | 1 | // These functions are provided when not linking against libc because LLVM |
| 2 | 2 | // sometimes generates code that calls them. |
| 3 | 3 | |
| 4 | // TODO dest should be nullable and return value should be nullable | |
| 4 | 5 | export fn memset(dest: &u8, c: u8, n: usize) -> &u8 { |
| 5 | 6 | @setDebugSafety(this, false); |
| 6 | 7 | |
| 7 | 8 | var index: usize = 0; |
| 8 | while (index != n) { | |
| 9 | while (index != n; index += 1) | |
| 9 | 10 | dest[index] = c; |
| 10 | index += 1; | |
| 11 | } | |
| 11 | ||
| 12 | 12 | return dest; |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | // TODO dest, source, and return value should be nullable | |
| 15 | 16 | export fn memcpy(noalias dest: &u8, noalias src: &const u8, n: usize) -> &u8 { |
| 16 | 17 | @setDebugSafety(this, false); |
| 17 | 18 | |
| 18 | 19 | var index: usize = 0; |
| 19 | while (index != n) { | |
| 20 | while (index != n; index += 1) | |
| 20 | 21 | dest[index] = src[index]; |
| 21 | index += 1; | |
| 22 | } | |
| 22 | ||
| 23 | 23 | return dest; |
| 24 | 24 | } |