| author | |
| committer | |
| log | 47336abae3992ef343bd9cb6099b89bad1dfb634 |
| tree | 4b05465b2d964d8110b9c912b81d82d6dfcada19 |
| parent | d16ce67106796011706e9f3653bb843c21c9d708 |
* zig build system: create standard dynamic library sym links
* unwrapping an error results in a panic message that contains
the error name
* rename error.SysResources to error.SystemResources
* add std.os.symLink
* add std.os.deleteFile7 files changed, 260 insertions(+), 89 deletions(-)
src/all_types.hpp+2-1| ... | ... | @@ -1211,7 +1211,6 @@ enum PanicMsgId { |
| 1211 | 1211 | PanicMsgIdExactDivisionRemainder, |
| 1212 | 1212 | PanicMsgIdSliceWidenRemainder, |
| 1213 | 1213 | PanicMsgIdUnwrapMaybeFail, |
| 1214 | PanicMsgIdUnwrapErrFail, | |
| 1215 | 1214 | PanicMsgIdInvalidErrorCode, |
| 1216 | 1215 | |
| 1217 | 1216 | PanicMsgIdCount, |
| ... | ... | @@ -1445,6 +1444,8 @@ struct CodeGen { |
| 1445 | 1444 | ZigList<AstNode *> error_decls; |
| 1446 | 1445 | bool generate_error_name_table; |
| 1447 | 1446 | LLVMValueRef err_name_table; |
| 1447 | size_t largest_err_name_len; | |
| 1448 | LLVMValueRef safety_crash_err_fn; | |
| 1448 | 1449 | |
| 1449 | 1450 | IrInstruction *invalid_instruction; |
| 1450 | 1451 | ConstExprValue const_void_val; |
src/codegen.cpp+141-39| ... | ... | @@ -255,6 +255,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script) { |
| 255 | 255 | static void render_const_val(CodeGen *g, ConstExprValue *const_val); |
| 256 | 256 | static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name); |
| 257 | 257 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val); |
| 258 | static void generate_error_name_table(CodeGen *g); | |
| 258 | 259 | |
| 259 | 260 | static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) { |
| 260 | 261 | unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name)); |
| ... | ... | @@ -545,6 +546,34 @@ static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) { |
| 545 | 546 | return true; |
| 546 | 547 | } |
| 547 | 548 | |
| 549 | static bool is_array_of_at_least_n_bytes(CodeGen *g, TypeTableEntry *type_entry, uint32_t n) { | |
| 550 | if (type_entry->id != TypeTableEntryIdArray) | |
| 551 | return false; | |
| 552 | ||
| 553 | TypeTableEntry *child_type = type_entry->data.array.child_type; | |
| 554 | if (child_type->id != TypeTableEntryIdInt) | |
| 555 | return false; | |
| 556 | ||
| 557 | if (child_type != g->builtin_types.entry_u8) | |
| 558 | return false; | |
| 559 | ||
| 560 | if (type_entry->data.array.len < n) | |
| 561 | return false; | |
| 562 | ||
| 563 | return true; | |
| 564 | } | |
| 565 | ||
| 566 | static uint32_t get_type_alignment(CodeGen *g, TypeTableEntry *type_entry) { | |
| 567 | uint32_t alignment = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, type_entry->type_ref); | |
| 568 | uint32_t dbl_ptr_bytes = g->pointer_size_bytes * 2; | |
| 569 | if (is_array_of_at_least_n_bytes(g, type_entry, dbl_ptr_bytes)) { | |
| 570 | return (alignment < dbl_ptr_bytes) ? dbl_ptr_bytes : alignment; | |
| 571 | } else { | |
| 572 | return alignment; | |
| 573 | } | |
| 574 | } | |
| 575 | ||
| 576 | ||
| 548 | 577 | static Buf *panic_msg_buf(PanicMsgId msg_id) { |
| 549 | 578 | switch (msg_id) { |
| 550 | 579 | case PanicMsgIdCount: |
| ... | ... | @@ -569,8 +598,6 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { |
| 569 | 598 | return buf_create_from_str("slice widening size mismatch"); |
| 570 | 599 | case PanicMsgIdUnwrapMaybeFail: |
| 571 | 600 | return buf_create_from_str("attempt to unwrap null"); |
| 572 | case PanicMsgIdUnwrapErrFail: | |
| 573 | return buf_create_from_str("attempt to unwrap error"); | |
| 574 | 601 | case PanicMsgIdUnreachable: |
| 575 | 602 | return buf_create_from_str("reached unreachable code"); |
| 576 | 603 | case PanicMsgIdInvalidErrorCode: |
| ... | ... | @@ -595,28 +622,128 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) { |
| 595 | 622 | return val->llvm_global; |
| 596 | 623 | } |
| 597 | 624 | |
| 598 | static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) { | |
| 625 | static void gen_panic_raw(CodeGen *g, LLVMValueRef msg_ptr, LLVMValueRef msg_len) { | |
| 599 | 626 | FnTableEntry *panic_fn = get_extern_panic_fn(g); |
| 600 | 627 | LLVMValueRef fn_val = fn_llvm_value(g, panic_fn); |
| 628 | LLVMValueRef args[] = { msg_ptr, msg_len }; | |
| 629 | ZigLLVMBuildCall(g->builder, fn_val, args, 2, panic_fn->type_entry->data.fn.calling_convention, false, ""); | |
| 630 | LLVMBuildUnreachable(g->builder); | |
| 631 | } | |
| 601 | 632 | |
| 633 | static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) { | |
| 602 | 634 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); |
| 603 | 635 | size_t ptr_index = str_type->data.structure.fields[slice_ptr_index].gen_index; |
| 604 | 636 | size_t len_index = str_type->data.structure.fields[slice_len_index].gen_index; |
| 605 | 637 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, msg_arg, (unsigned)ptr_index, ""); |
| 606 | 638 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, msg_arg, (unsigned)len_index, ""); |
| 607 | 639 | |
| 608 | LLVMValueRef args[] = { | |
| 609 | LLVMBuildLoad(g->builder, ptr_ptr, ""), | |
| 610 | LLVMBuildLoad(g->builder, len_ptr, ""), | |
| 611 | }; | |
| 612 | ZigLLVMBuildCall(g->builder, fn_val, args, 2, panic_fn->type_entry->data.fn.calling_convention, false, ""); | |
| 613 | LLVMBuildUnreachable(g->builder); | |
| 640 | LLVMValueRef msg_ptr = LLVMBuildLoad(g->builder, ptr_ptr, ""); | |
| 641 | LLVMValueRef msg_len = LLVMBuildLoad(g->builder, len_ptr, ""); | |
| 642 | gen_panic_raw(g, msg_ptr, msg_len); | |
| 614 | 643 | } |
| 615 | 644 | |
| 616 | 645 | static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) { |
| 617 | 646 | gen_panic(g, get_panic_msg_ptr_val(g, msg_id)); |
| 618 | 647 | } |
| 619 | 648 | |
| 649 | static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { | |
| 650 | if (g->safety_crash_err_fn != nullptr) | |
| 651 | return g->safety_crash_err_fn; | |
| 652 | ||
| 653 | static const char *unwrap_err_msg_text = "attempt to unwrap error: "; | |
| 654 | ||
| 655 | g->generate_error_name_table = true; | |
| 656 | generate_error_name_table(g); | |
| 657 | ||
| 658 | size_t unwrap_err_msg_text_len = strlen(unwrap_err_msg_text); | |
| 659 | size_t err_buf_len = strlen(unwrap_err_msg_text) + g->largest_err_name_len; | |
| 660 | LLVMValueRef *err_buf_vals = allocate<LLVMValueRef>(err_buf_len); | |
| 661 | size_t i = 0; | |
| 662 | for (; i < unwrap_err_msg_text_len; i += 1) { | |
| 663 | err_buf_vals[i] = LLVMConstInt(LLVMInt8Type(), unwrap_err_msg_text[i], false); | |
| 664 | } | |
| 665 | for (; i < err_buf_len; i += 1) { | |
| 666 | err_buf_vals[i] = LLVMGetUndef(LLVMInt8Type()); | |
| 667 | } | |
| 668 | LLVMValueRef init_value = LLVMConstArray(LLVMInt8Type(), err_buf_vals, err_buf_len); | |
| 669 | Buf *global_name = get_mangled_name(g, buf_create_from_str("__zig_panic_buf"), false); | |
| 670 | LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_value), buf_ptr(global_name)); | |
| 671 | LLVMSetInitializer(global_value, init_value); | |
| 672 | LLVMSetLinkage(global_value, LLVMInternalLinkage); | |
| 673 | LLVMSetGlobalConstant(global_value, false); | |
| 674 | LLVMSetUnnamedAddr(global_value, true); | |
| 675 | LLVMSetAlignment(global_value, get_type_alignment(g, g->builtin_types.entry_u8)); | |
| 676 | ||
| 677 | TypeTableEntry *usize = g->builtin_types.entry_usize; | |
| 678 | LLVMValueRef full_buf_ptr_indices[] = { | |
| 679 | LLVMConstNull(usize->type_ref), | |
| 680 | LLVMConstNull(usize->type_ref), | |
| 681 | }; | |
| 682 | LLVMValueRef full_buf_ptr = LLVMConstInBoundsGEP(global_value, full_buf_ptr_indices, 2); | |
| 683 | ||
| 684 | LLVMValueRef offset_ptr_indices[] = { | |
| 685 | LLVMConstNull(usize->type_ref), | |
| 686 | LLVMConstInt(usize->type_ref, unwrap_err_msg_text_len, false), | |
| 687 | }; | |
| 688 | LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_value, offset_ptr_indices, 2); | |
| 689 | ||
| 690 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false); | |
| 691 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), &g->err_tag_type->type_ref, 1, false); | |
| 692 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); | |
| 693 | addLLVMFnAttr(fn_val, "noreturn"); | |
| 694 | addLLVMFnAttr(fn_val, "cold"); | |
| 695 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); | |
| 696 | LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv); | |
| 697 | ||
| 698 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); | |
| 699 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); | |
| 700 | LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder); | |
| 701 | LLVMPositionBuilderAtEnd(g->builder, entry_block); | |
| 702 | ZigLLVMClearCurrentDebugLocation(g->builder); | |
| 703 | ||
| 704 | LLVMValueRef err_val = LLVMGetParam(fn_val, 0); | |
| 705 | ||
| 706 | LLVMValueRef err_table_indices[] = { | |
| 707 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), | |
| 708 | err_val, | |
| 709 | }; | |
| 710 | LLVMValueRef err_name_val = LLVMBuildInBoundsGEP(g->builder, g->err_name_table, err_table_indices, 2, ""); | |
| 711 | ||
| 712 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, err_name_val, slice_ptr_index, ""); | |
| 713 | LLVMValueRef err_name_ptr = LLVMBuildLoad(g->builder, ptr_field_ptr, ""); | |
| 714 | ||
| 715 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, err_name_val, slice_len_index, ""); | |
| 716 | LLVMValueRef err_name_len = LLVMBuildLoad(g->builder, len_field_ptr, ""); | |
| 717 | ||
| 718 | LLVMValueRef params[] = { | |
| 719 | offset_buf_ptr, // dest pointer | |
| 720 | err_name_ptr, // source pointer | |
| 721 | err_name_len, // size bytes | |
| 722 | LLVMConstInt(LLVMInt32Type(), 1, false), // align bytes | |
| 723 | LLVMConstNull(LLVMInt1Type()), // is volatile | |
| 724 | }; | |
| 725 | ||
| 726 | LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, ""); | |
| 727 | ||
| 728 | LLVMValueRef const_prefix_len = LLVMConstInt(LLVMTypeOf(err_name_len), strlen(unwrap_err_msg_text), false); | |
| 729 | LLVMValueRef full_buf_len = LLVMBuildNUWAdd(g->builder, const_prefix_len, err_name_len, ""); | |
| 730 | ||
| 731 | gen_panic_raw(g, full_buf_ptr, full_buf_len); | |
| 732 | ||
| 733 | LLVMPositionBuilderAtEnd(g->builder, prev_block); | |
| 734 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); | |
| 735 | ||
| 736 | g->safety_crash_err_fn = fn_val; | |
| 737 | return fn_val; | |
| 738 | } | |
| 739 | ||
| 740 | static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) { | |
| 741 | LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g); | |
| 742 | LLVMBuildCall(g->builder, safety_crash_err_fn, &err_val, 1, ""); | |
| 743 | LLVMBuildUnreachable(g->builder); | |
| 744 | ||
| 745 | } | |
| 746 | ||
| 620 | 747 | static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, |
| 621 | 748 | LLVMIntPredicate lower_pred, LLVMValueRef lower_value, |
| 622 | 749 | LLVMIntPredicate upper_pred, LLVMValueRef upper_value) |
| ... | ... | @@ -790,33 +917,6 @@ static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) { |
| 790 | 917 | } |
| 791 | 918 | } |
| 792 | 919 | |
| 793 | static bool is_array_of_at_least_n_bytes(CodeGen *g, TypeTableEntry *type_entry, uint32_t n) { | |
| 794 | if (type_entry->id != TypeTableEntryIdArray) | |
| 795 | return false; | |
| 796 | ||
| 797 | TypeTableEntry *child_type = type_entry->data.array.child_type; | |
| 798 | if (child_type->id != TypeTableEntryIdInt) | |
| 799 | return false; | |
| 800 | ||
| 801 | if (child_type != g->builtin_types.entry_u8) | |
| 802 | return false; | |
| 803 | ||
| 804 | if (type_entry->data.array.len < n) | |
| 805 | return false; | |
| 806 | ||
| 807 | return true; | |
| 808 | } | |
| 809 | ||
| 810 | static uint32_t get_type_alignment(CodeGen *g, TypeTableEntry *type_entry) { | |
| 811 | uint32_t alignment = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, type_entry->type_ref); | |
| 812 | uint32_t dbl_ptr_bytes = g->pointer_size_bytes * 2; | |
| 813 | if (is_array_of_at_least_n_bytes(g, type_entry, dbl_ptr_bytes)) { | |
| 814 | return (alignment < dbl_ptr_bytes) ? dbl_ptr_bytes : alignment; | |
| 815 | } else { | |
| 816 | return alignment; | |
| 817 | } | |
| 818 | } | |
| 819 | ||
| 820 | 920 | static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest, |
| 821 | 921 | TypeTableEntry *type_entry) |
| 822 | 922 | { |
| ... | ... | @@ -2522,7 +2622,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 2522 | 2622 | LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block); |
| 2523 | 2623 | |
| 2524 | 2624 | LLVMPositionBuilderAtEnd(g->builder, err_block); |
| 2525 | gen_debug_safety_crash(g, PanicMsgIdUnwrapErrFail); | |
| 2625 | gen_debug_safety_crash_for_err(g, err_val); | |
| 2526 | 2626 | |
| 2527 | 2627 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 2528 | 2628 | } |
| ... | ... | @@ -3384,7 +3484,7 @@ static LLVMValueRef gen_test_fn_val(CodeGen *g, FnTableEntry *fn_entry) { |
| 3384 | 3484 | } |
| 3385 | 3485 | |
| 3386 | 3486 | static void generate_error_name_table(CodeGen *g) { |
| 3387 | if (!g->generate_error_name_table || g->error_decls.length == 1) { | |
| 3487 | if (g->err_name_table != nullptr || !g->generate_error_name_table || g->error_decls.length == 1) { | |
| 3388 | 3488 | return; |
| 3389 | 3489 | } |
| 3390 | 3490 | |
| ... | ... | @@ -3400,6 +3500,8 @@ static void generate_error_name_table(CodeGen *g) { |
| 3400 | 3500 | assert(error_decl_node->type == NodeTypeErrorValueDecl); |
| 3401 | 3501 | Buf *name = error_decl_node->data.error_value_decl.name; |
| 3402 | 3502 | |
| 3503 | g->largest_err_name_len = max(g->largest_err_name_len, buf_len(name)); | |
| 3504 | ||
| 3403 | 3505 | LLVMValueRef str_init = LLVMConstString(buf_ptr(name), (unsigned)buf_len(name), true); |
| 3404 | 3506 | LLVMValueRef str_global = LLVMAddGlobal(g->module, LLVMTypeOf(str_init), ""); |
| 3405 | 3507 | LLVMSetInitializer(str_global, str_init); |
| ... | ... | @@ -3417,7 +3519,7 @@ static void generate_error_name_table(CodeGen *g) { |
| 3417 | 3519 | LLVMValueRef err_name_table_init = LLVMConstArray(str_type->type_ref, values, (unsigned)g->error_decls.length); |
| 3418 | 3520 | |
| 3419 | 3521 | g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init), |
| 3420 | buf_ptr(get_mangled_name(g, buf_create_from_str("err_name_table"), false))); | |
| 3522 | buf_ptr(get_mangled_name(g, buf_create_from_str("__zig_err_name_table"), false))); | |
| 3421 | 3523 | LLVMSetInitializer(g->err_name_table, err_name_table_init); |
| 3422 | 3524 | LLVMSetLinkage(g->err_name_table, LLVMPrivateLinkage); |
| 3423 | 3525 | LLVMSetGlobalConstant(g->err_name_table, true); |
src/main.cpp-2| ... | ... | @@ -248,8 +248,6 @@ int main(int argc, char **argv) { |
| 248 | 248 | fprintf(stderr, " %s", args.at(i)); |
| 249 | 249 | } |
| 250 | 250 | fprintf(stderr, "\n"); |
| 251 | } else { | |
| 252 | os_delete_file(buf_create_from_str("./build")); | |
| 253 | 251 | } |
| 254 | 252 | return (term.how == TerminationIdClean) ? term.code : -1; |
| 255 | 253 | } |
std/build.zig+42-39| ... | ... | @@ -395,6 +395,33 @@ pub const Builder = struct { |
| 395 | 395 | |
| 396 | 396 | return self.invalid_user_input; |
| 397 | 397 | } |
| 398 | ||
| 399 | fn spawnChild(self: &Builder, exe_path: []const u8, args: []const []const u8) { | |
| 400 | if (self.verbose) { | |
| 401 | %%io.stderr.printf("{}", exe_path); | |
| 402 | for (args) |arg| { | |
| 403 | %%io.stderr.printf(" {}", arg); | |
| 404 | } | |
| 405 | %%io.stderr.printf("\n"); | |
| 406 | } | |
| 407 | ||
| 408 | var child = os.ChildProcess.spawn(exe_path, args, &self.env_map, | |
| 409 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, self.allocator) | |
| 410 | %% |err| debug.panic("Unable to spawn {}: {}\n", exe_path, @errorName(err)); | |
| 411 | ||
| 412 | const term = %%child.wait(); | |
| 413 | switch (term) { | |
| 414 | Term.Clean => |code| { | |
| 415 | if (code != 0) { | |
| 416 | debug.panic("Process {} exited with error code {}\n", exe_path, code); | |
| 417 | } | |
| 418 | }, | |
| 419 | else => { | |
| 420 | debug.panic("Process {} terminated unexpectedly\n", exe_path); | |
| 421 | }, | |
| 422 | }; | |
| 423 | ||
| 424 | } | |
| 398 | 425 | }; |
| 399 | 426 | |
| 400 | 427 | const Version = struct { |
| ... | ... | @@ -568,14 +595,7 @@ const Exe = struct { |
| 568 | 595 | %return zig_args.append(lib_path); |
| 569 | 596 | } |
| 570 | 597 | |
| 571 | if (builder.verbose) { | |
| 572 | printInvocation(builder.zig_exe, zig_args); | |
| 573 | } | |
| 574 | // TODO issue #301 | |
| 575 | var child = os.ChildProcess.spawn(builder.zig_exe, zig_args.toSliceConst(), &builder.env_map, | |
| 576 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, builder.allocator) | |
| 577 | %% |err| debug.panic("Unable to spawn zig compiler: {}\n", @errorName(err)); | |
| 578 | %return waitForCleanExit(&child); | |
| 598 | builder.spawnChild(builder.zig_exe, zig_args.toSliceConst()); | |
| 579 | 599 | } |
| 580 | 600 | }; |
| 581 | 601 | |
| ... | ... | @@ -700,14 +720,7 @@ const CLibrary = struct { |
| 700 | 720 | %%cc_args.append(dir); |
| 701 | 721 | } |
| 702 | 722 | |
| 703 | if (builder.verbose) { | |
| 704 | printInvocation(cc, cc_args); | |
| 705 | } | |
| 706 | ||
| 707 | var child = os.ChildProcess.spawn(cc, cc_args.toSliceConst(), &builder.env_map, | |
| 708 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, builder.allocator) | |
| 709 | %% |err| debug.panic("Unable to spawn compiler: {}\n", @errorName(err)); | |
| 710 | %return waitForCleanExit(&child); | |
| 723 | builder.spawnChild(cc, cc_args.toSliceConst()); | |
| 711 | 724 | |
| 712 | 725 | %%self.object_files.append(o_file); |
| 713 | 726 | } |
| ... | ... | @@ -732,14 +745,18 @@ const CLibrary = struct { |
| 732 | 745 | %%cc_args.append(object_file); |
| 733 | 746 | } |
| 734 | 747 | |
| 735 | if (builder.verbose) { | |
| 736 | printInvocation(cc, cc_args); | |
| 737 | } | |
| 748 | builder.spawnChild(cc, cc_args.toSliceConst()); | |
| 738 | 749 | |
| 739 | var child = os.ChildProcess.spawn(cc, cc_args.toSliceConst(), &builder.env_map, | |
| 740 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, builder.allocator) | |
| 741 | %% |err| debug.panic("Unable to spawn compiler: {}\n", @errorName(err)); | |
| 742 | %return waitForCleanExit(&child); | |
| 750 | // sym link for libfoo.so.1 to libfoo.so.1.2.3 | |
| 751 | const major_only = %%fmt.allocPrint(builder.allocator, "lib{}.so.{d}", self.name, self.version.major); | |
| 752 | defer builder.allocator.free(major_only); | |
| 753 | _ = os.deleteFile(builder.allocator, major_only); | |
| 754 | %%os.symLink(builder.allocator, self.out_filename, major_only); | |
| 755 | // sym link for libfoo.so to libfoo.so.1 | |
| 756 | const name_only = %%fmt.allocPrint(builder.allocator, "lib{}.so", self.name); | |
| 757 | defer builder.allocator.free(name_only); | |
| 758 | _ = os.deleteFile(builder.allocator, name_only); | |
| 759 | %%os.symLink(builder.allocator, major_only, name_only); | |
| 743 | 760 | } |
| 744 | 761 | } |
| 745 | 762 | |
| ... | ... | @@ -848,14 +865,7 @@ const CExecutable = struct { |
| 848 | 865 | %%cc_args.append(dir); |
| 849 | 866 | } |
| 850 | 867 | |
| 851 | if (builder.verbose) { | |
| 852 | printInvocation(cc, cc_args); | |
| 853 | } | |
| 854 | ||
| 855 | var child = os.ChildProcess.spawn(cc, cc_args.toSliceConst(), &builder.env_map, | |
| 856 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, builder.allocator) | |
| 857 | %% |err| debug.panic("Unable to spawn compiler: {}\n", @errorName(err)); | |
| 858 | %return waitForCleanExit(&child); | |
| 868 | builder.spawnChild(cc, cc_args.toSliceConst()); | |
| 859 | 869 | |
| 860 | 870 | %%self.object_files.append(o_file); |
| 861 | 871 | } |
| ... | ... | @@ -879,14 +889,7 @@ const CExecutable = struct { |
| 879 | 889 | %%cc_args.append(full_path_lib); |
| 880 | 890 | } |
| 881 | 891 | |
| 882 | if (builder.verbose) { | |
| 883 | printInvocation(cc, cc_args); | |
| 884 | } | |
| 885 | ||
| 886 | var child = os.ChildProcess.spawn(cc, cc_args.toSliceConst(), &builder.env_map, | |
| 887 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, builder.allocator) | |
| 888 | %% |err| debug.panic("Unable to spawn compiler: {}\n", @errorName(err)); | |
| 889 | %return waitForCleanExit(&child); | |
| 892 | builder.spawnChild(cc, cc_args.toSliceConst()); | |
| 890 | 893 | } |
| 891 | 894 | |
| 892 | 895 | pub fn setTarget(self: &CExecutable, target_arch: Arch, target_os: Os, target_environ: Environ) { |
std/os/child_process.zig+4-4| ... | ... | @@ -142,7 +142,7 @@ pub const ChildProcess = struct { |
| 142 | 142 | const pid_err = posix.getErrno(pid); |
| 143 | 143 | if (pid_err > 0) { |
| 144 | 144 | return switch (pid_err) { |
| 145 | errno.EAGAIN, errno.ENOMEM, errno.ENOSYS => error.SysResources, | |
| 145 | errno.EAGAIN, errno.ENOMEM, errno.ENOSYS => error.SystemResources, | |
| 146 | 146 | else => error.Unexpected, |
| 147 | 147 | }; |
| 148 | 148 | } |
| ... | ... | @@ -210,7 +210,7 @@ fn makePipe() -> %[2]i32 { |
| 210 | 210 | const err = posix.getErrno(posix.pipe(&fds)); |
| 211 | 211 | if (err > 0) { |
| 212 | 212 | return switch (err) { |
| 213 | errno.EMFILE, errno.ENFILE => error.SysResources, | |
| 213 | errno.EMFILE, errno.ENFILE => error.SystemResources, | |
| 214 | 214 | else => error.Unexpected, |
| 215 | 215 | } |
| 216 | 216 | } |
| ... | ... | @@ -242,7 +242,7 @@ fn writeIntFd(fd: i32, value: ErrInt) -> %void { |
| 242 | 242 | switch (err) { |
| 243 | 243 | errno.EINTR => continue, |
| 244 | 244 | errno.EINVAL => unreachable, |
| 245 | else => return error.SysResources, | |
| 245 | else => return error.SystemResources, | |
| 246 | 246 | } |
| 247 | 247 | } |
| 248 | 248 | index += amt_written; |
| ... | ... | @@ -260,7 +260,7 @@ fn readIntFd(fd: i32) -> %ErrInt { |
| 260 | 260 | switch (err) { |
| 261 | 261 | errno.EINTR => continue, |
| 262 | 262 | errno.EINVAL => unreachable, |
| 263 | else => return error.SysResources, | |
| 263 | else => return error.SystemResources, | |
| 264 | 264 | } |
| 265 | 265 | } |
| 266 | 266 | index += amt_written; |
std/os/index.zig+63-4| ... | ... | @@ -25,13 +25,16 @@ const BufMap = @import("../buf_map.zig").BufMap; |
| 25 | 25 | const cstr = @import("../cstr.zig"); |
| 26 | 26 | |
| 27 | 27 | error Unexpected; |
| 28 | error SysResources; | |
| 28 | error SystemResources; | |
| 29 | 29 | error AccessDenied; |
| 30 | 30 | error InvalidExe; |
| 31 | 31 | error FileSystem; |
| 32 | 32 | error IsDir; |
| 33 | 33 | error FileNotFound; |
| 34 | 34 | error FileBusy; |
| 35 | error LinkPathAlreadyExists; | |
| 36 | error SymLinkLoop; | |
| 37 | error ReadOnlyFileSystem; | |
| 35 | 38 | |
| 36 | 39 | /// Fills `buf` with random bytes. If linking against libc, this calls the |
| 37 | 40 | /// appropriate OS-specific library call. Otherwise it uses the zig standard |
| ... | ... | @@ -174,7 +177,7 @@ pub fn posixOpen(path: []const u8, flags: usize, perm: usize, allocator: ?&Alloc |
| 174 | 177 | errno.ENFILE => error.SystemFdQuotaExceeded, |
| 175 | 178 | errno.ENODEV => error.NoDevice, |
| 176 | 179 | errno.ENOENT => error.PathNotFound, |
| 177 | errno.ENOMEM => error.NoMem, | |
| 180 | errno.ENOMEM => error.SystemResources, | |
| 178 | 181 | errno.ENOSPC => error.NoSpaceLeft, |
| 179 | 182 | errno.ENOTDIR => error.NotDir, |
| 180 | 183 | errno.EPERM => error.BadPerm, |
| ... | ... | @@ -191,7 +194,7 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { |
| 191 | 194 | if (err > 0) { |
| 192 | 195 | return switch (err) { |
| 193 | 196 | errno.EBUSY, errno.EINTR => continue, |
| 194 | errno.EMFILE => error.SysResources, | |
| 197 | errno.EMFILE => error.SystemResources, | |
| 195 | 198 | errno.EINVAL => unreachable, |
| 196 | 199 | else => error.Unexpected, |
| 197 | 200 | }; |
| ... | ... | @@ -305,7 +308,7 @@ fn posixExecveErrnoToErr(err: usize) -> error { |
| 305 | 308 | assert(err > 0); |
| 306 | 309 | return switch (err) { |
| 307 | 310 | errno.EFAULT => unreachable, |
| 308 | errno.E2BIG, errno.EMFILE, errno.ENAMETOOLONG, errno.ENFILE, errno.ENOMEM => error.SysResources, | |
| 311 | errno.E2BIG, errno.EMFILE, errno.ENAMETOOLONG, errno.ENFILE, errno.ENOMEM => error.SystemResources, | |
| 309 | 312 | errno.EACCES, errno.EPERM => error.AccessDenied, |
| 310 | 313 | errno.EINVAL, errno.ENOEXEC => error.InvalidExe, |
| 311 | 314 | errno.EIO, errno.ELOOP => error.FileSystem, |
| ... | ... | @@ -381,3 +384,59 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { |
| 381 | 384 | return buf; |
| 382 | 385 | } |
| 383 | 386 | } |
| 387 | ||
| 388 | pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) -> %void { | |
| 389 | const full_buf = %return allocator.alloc(u8, existing_path.len + new_path.len + 2); | |
| 390 | defer allocator.free(full_buf); | |
| 391 | ||
| 392 | const existing_buf = full_buf; | |
| 393 | mem.copy(u8, existing_buf, existing_path); | |
| 394 | existing_buf[existing_path.len] = 0; | |
| 395 | ||
| 396 | const new_buf = full_buf[existing_path.len + 1...]; | |
| 397 | mem.copy(u8, new_buf, new_path); | |
| 398 | new_buf[new_path.len] = 0; | |
| 399 | ||
| 400 | const err = posix.getErrno(posix.symlink(existing_buf.ptr, new_buf.ptr)); | |
| 401 | if (err > 0) { | |
| 402 | return switch (err) { | |
| 403 | errno.EFAULT, errno.EINVAL => unreachable, | |
| 404 | errno.EACCES, errno.EPERM => error.AccessDenied, | |
| 405 | errno.EDQUOT => error.DiskQuota, | |
| 406 | errno.EEXIST => error.LinkPathAlreadyExists, | |
| 407 | errno.EIO => error.FileSystem, | |
| 408 | errno.ELOOP => error.SymLinkLoop, | |
| 409 | errno.ENAMETOOLONG => error.NameTooLong, | |
| 410 | errno.ENOENT, errno.ENOTDIR => error.FileNotFound, | |
| 411 | errno.ENOMEM => error.SystemResources, | |
| 412 | errno.ENOSPC => error.NoSpaceLeft, | |
| 413 | errno.EROFS => error.ReadOnlyFileSystem, | |
| 414 | else => error.Unexpected, | |
| 415 | }; | |
| 416 | } | |
| 417 | } | |
| 418 | ||
| 419 | pub fn deleteFile(allocator: &Allocator, path: []const u8) -> %void { | |
| 420 | const buf = %return allocator.alloc(u8, path.len + 1); | |
| 421 | defer allocator.free(buf); | |
| 422 | ||
| 423 | mem.copy(u8, buf, path); | |
| 424 | buf[path.len] = 0; | |
| 425 | ||
| 426 | const err = posix.getErrno(posix.unlink(buf.ptr)); | |
| 427 | if (err > 0) { | |
| 428 | return switch (err) { | |
| 429 | errno.EACCES, errno.EPERM => error.AccessDenied, | |
| 430 | errno.EBUSY => error.FileBusy, | |
| 431 | errno.EFAULT, errno.EINVAL => unreachable, | |
| 432 | errno.EIO => error.FileSystem, | |
| 433 | errno.EISDIR => error.IsDir, | |
| 434 | errno.ELOOP => error.SymLinkLoop, | |
| 435 | errno.ENAMETOOLONG => error.NameTooLong, | |
| 436 | errno.ENOENT, errno.ENOTDIR => error.FileNotFound, | |
| 437 | errno.ENOMEM => error.SystemResources, | |
| 438 | errno.EROFS => error.ReadOnlyFileSystem, | |
| 439 | else => error.Unexpected, | |
| 440 | }; | |
| 441 | } | |
| 442 | } |
std/os/linux.zig+8| ... | ... | @@ -287,6 +287,10 @@ pub fn read(fd: i32, buf: &u8, count: usize) -> usize { |
| 287 | 287 | arch.syscall3(arch.SYS_read, usize(fd), usize(buf), count) |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | pub fn symlink(existing: &const u8, new: &const u8) -> usize { | |
| 291 | arch.syscall2(arch.SYS_symlink, usize(existing), usize(new)) | |
| 292 | } | |
| 293 | ||
| 290 | 294 | pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) -> usize { |
| 291 | 295 | arch.syscall4(arch.SYS_pread, usize(fd), usize(buf), count, offset) |
| 292 | 296 | } |
| ... | ... | @@ -340,6 +344,10 @@ pub fn kill(pid: i32, sig: i32) -> usize { |
| 340 | 344 | arch.syscall2(arch.SYS_kill, usize(pid), usize(sig)) |
| 341 | 345 | } |
| 342 | 346 | |
| 347 | pub fn unlink(path: &const u8) -> usize { | |
| 348 | arch.syscall1(arch.SYS_unlink, usize(path)) | |
| 349 | } | |
| 350 | ||
| 343 | 351 | pub fn waitpid(pid: i32, status: &i32, options: i32) -> usize { |
| 344 | 352 | arch.syscall4(arch.SYS_wait4, usize(pid), usize(status), usize(options), 0) |
| 345 | 353 | } |