| author | |
| committer | |
| log | c400cb429abf2980962739731f5b64861a54ab61 |
| tree | afb244401d3aa18547ea7e6a5bf5fbe141472cee |
| parent | a1363b52278b68f59aa72adf985f11e6c1d02cf9 |
* See #204 - zig build system
* allow builtin types Os, Environ, Arch to be used at runtime.
they have zero_bits=false and debug info now.
* Eradicate use of `@alloca` in std for syscalls. See #225
* add `std.io.writeFile`
* `std.debug.panic` adds a newline to format10 files changed, 374 insertions(+), 148 deletions(-)
src/all_types.hpp+1| ... | @@ -944,6 +944,7 @@ struct TypeTableEntryEnum { | ... | @@ -944,6 +944,7 @@ struct TypeTableEntryEnum { |
| 944 | AstNode *decl_node; | 944 | AstNode *decl_node; |
| 945 | ContainerLayout layout; | 945 | ContainerLayout layout; |
| 946 | uint32_t src_field_count; | 946 | uint32_t src_field_count; |
| 947 | // number of fields in the union. 0 if enum with no payload | ||
| 947 | uint32_t gen_field_count; | 948 | uint32_t gen_field_count; |
| 948 | TypeEnumField *fields; | 949 | TypeEnumField *fields; |
| 949 | bool is_invalid; // true if any fields are invalid | 950 | bool is_invalid; // true if any fields are invalid |
src/codegen.cpp+33-20| ... | @@ -3802,6 +3802,35 @@ static const GlobalLinkageValue global_linkage_values[] = { | ... | @@ -3802,6 +3802,35 @@ static const GlobalLinkageValue global_linkage_values[] = { |
| 3802 | {GlobalLinkageIdLinkOnce, "LinkOnce"}, | 3802 | {GlobalLinkageIdLinkOnce, "LinkOnce"}, |
| 3803 | }; | 3803 | }; |
| 3804 | 3804 | ||
| 3805 | static void init_enum_debug_info(CodeGen *g, TypeTableEntry *enum_type) { | ||
| 3806 | uint32_t field_count = enum_type->data.enumeration.src_field_count; | ||
| 3807 | |||
| 3808 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); | ||
| 3809 | enum_type->data.enumeration.tag_type = tag_type_entry; | ||
| 3810 | |||
| 3811 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); | ||
| 3812 | for (uint32_t i = 0; i < field_count; i += 1) { | ||
| 3813 | TypeEnumField *field = &enum_type->data.enumeration.fields[i]; | ||
| 3814 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(field->name), i); | ||
| 3815 | } | ||
| 3816 | |||
| 3817 | // create debug type for tag | ||
| 3818 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 3819 | uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 3820 | enum_type->di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | ||
| 3821 | nullptr, buf_ptr(&enum_type->name), | ||
| 3822 | nullptr, 0, | ||
| 3823 | tag_debug_size_in_bits, | ||
| 3824 | tag_debug_align_in_bits, | ||
| 3825 | di_enumerators, field_count, | ||
| 3826 | tag_type_entry->di_type, ""); | ||
| 3827 | |||
| 3828 | enum_type->type_ref = tag_type_entry->type_ref; | ||
| 3829 | |||
| 3830 | enum_type->data.enumeration.complete = true; | ||
| 3831 | enum_type->data.enumeration.zero_bits_known = true; | ||
| 3832 | } | ||
| 3833 | |||
| 3805 | static void define_builtin_types(CodeGen *g) { | 3834 | static void define_builtin_types(CodeGen *g) { |
| 3806 | { | 3835 | { |
| 3807 | // if this type is anywhere in the AST, we should never hit codegen. | 3836 | // if this type is anywhere in the AST, we should never hit codegen. |
| ... | @@ -4022,7 +4051,6 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4022,7 +4051,6 @@ static void define_builtin_types(CodeGen *g) { |
| 4022 | 4051 | ||
| 4023 | { | 4052 | { |
| 4024 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); | 4053 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); |
| 4025 | entry->zero_bits = true; // only allowed at compile time | ||
| 4026 | buf_init_from_str(&entry->name, "Os"); | 4054 | buf_init_from_str(&entry->name, "Os"); |
| 4027 | uint32_t field_count = target_os_count(); | 4055 | uint32_t field_count = target_os_count(); |
| 4028 | entry->data.enumeration.src_field_count = field_count; | 4056 | entry->data.enumeration.src_field_count = field_count; |
| ... | @@ -4038,11 +4066,8 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4038,11 +4066,8 @@ static void define_builtin_types(CodeGen *g) { |
| 4038 | g->target_os_index = i; | 4066 | g->target_os_index = i; |
| 4039 | } | 4067 | } |
| 4040 | } | 4068 | } |
| 4041 | entry->data.enumeration.complete = true; | ||
| 4042 | entry->data.enumeration.zero_bits_known = true; | ||
| 4043 | 4069 | ||
| 4044 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); | 4070 | init_enum_debug_info(g, entry); |
| 4045 | entry->data.enumeration.tag_type = tag_type_entry; | ||
| 4046 | 4071 | ||
| 4047 | g->builtin_types.entry_os_enum = entry; | 4072 | g->builtin_types.entry_os_enum = entry; |
| 4048 | g->primitive_type_table.put(&entry->name, entry); | 4073 | g->primitive_type_table.put(&entry->name, entry); |
| ... | @@ -4050,7 +4075,6 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4050,7 +4075,6 @@ static void define_builtin_types(CodeGen *g) { |
| 4050 | 4075 | ||
| 4051 | { | 4076 | { |
| 4052 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); | 4077 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); |
| 4053 | entry->zero_bits = true; // only allowed at compile time | ||
| 4054 | buf_init_from_str(&entry->name, "Arch"); | 4078 | buf_init_from_str(&entry->name, "Arch"); |
| 4055 | uint32_t field_count = target_arch_count(); | 4079 | uint32_t field_count = target_arch_count(); |
| 4056 | entry->data.enumeration.src_field_count = field_count; | 4080 | entry->data.enumeration.src_field_count = field_count; |
| ... | @@ -4072,11 +4096,8 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4072,11 +4096,8 @@ static void define_builtin_types(CodeGen *g) { |
| 4072 | g->target_arch_index = i; | 4096 | g->target_arch_index = i; |
| 4073 | } | 4097 | } |
| 4074 | } | 4098 | } |
| 4075 | entry->data.enumeration.complete = true; | ||
| 4076 | entry->data.enumeration.zero_bits_known = true; | ||
| 4077 | 4099 | ||
| 4078 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); | 4100 | init_enum_debug_info(g, entry); |
| 4079 | entry->data.enumeration.tag_type = tag_type_entry; | ||
| 4080 | 4101 | ||
| 4081 | g->builtin_types.entry_arch_enum = entry; | 4102 | g->builtin_types.entry_arch_enum = entry; |
| 4082 | g->primitive_type_table.put(&entry->name, entry); | 4103 | g->primitive_type_table.put(&entry->name, entry); |
| ... | @@ -4084,7 +4105,6 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4084,7 +4105,6 @@ static void define_builtin_types(CodeGen *g) { |
| 4084 | 4105 | ||
| 4085 | { | 4106 | { |
| 4086 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); | 4107 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); |
| 4087 | entry->zero_bits = true; // only allowed at compile time | ||
| 4088 | buf_init_from_str(&entry->name, "Environ"); | 4108 | buf_init_from_str(&entry->name, "Environ"); |
| 4089 | uint32_t field_count = target_environ_count(); | 4109 | uint32_t field_count = target_environ_count(); |
| 4090 | entry->data.enumeration.src_field_count = field_count; | 4110 | entry->data.enumeration.src_field_count = field_count; |
| ... | @@ -4100,11 +4120,8 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4100,11 +4120,8 @@ static void define_builtin_types(CodeGen *g) { |
| 4100 | g->target_environ_index = i; | 4120 | g->target_environ_index = i; |
| 4101 | } | 4121 | } |
| 4102 | } | 4122 | } |
| 4103 | entry->data.enumeration.complete = true; | ||
| 4104 | entry->data.enumeration.zero_bits_known = true; | ||
| 4105 | 4123 | ||
| 4106 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); | 4124 | init_enum_debug_info(g, entry); |
| 4107 | entry->data.enumeration.tag_type = tag_type_entry; | ||
| 4108 | 4125 | ||
| 4109 | g->builtin_types.entry_environ_enum = entry; | 4126 | g->builtin_types.entry_environ_enum = entry; |
| 4110 | g->primitive_type_table.put(&entry->name, entry); | 4127 | g->primitive_type_table.put(&entry->name, entry); |
| ... | @@ -4112,7 +4129,6 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4112,7 +4129,6 @@ static void define_builtin_types(CodeGen *g) { |
| 4112 | 4129 | ||
| 4113 | { | 4130 | { |
| 4114 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); | 4131 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); |
| 4115 | entry->zero_bits = true; // only allowed at compile time | ||
| 4116 | buf_init_from_str(&entry->name, "ObjectFormat"); | 4132 | buf_init_from_str(&entry->name, "ObjectFormat"); |
| 4117 | uint32_t field_count = target_oformat_count(); | 4133 | uint32_t field_count = target_oformat_count(); |
| 4118 | entry->data.enumeration.src_field_count = field_count; | 4134 | entry->data.enumeration.src_field_count = field_count; |
| ... | @@ -4128,11 +4144,8 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4128,11 +4144,8 @@ static void define_builtin_types(CodeGen *g) { |
| 4128 | g->target_oformat_index = i; | 4144 | g->target_oformat_index = i; |
| 4129 | } | 4145 | } |
| 4130 | } | 4146 | } |
| 4131 | entry->data.enumeration.complete = true; | ||
| 4132 | entry->data.enumeration.zero_bits_known = true; | ||
| 4133 | 4147 | ||
| 4134 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); | 4148 | init_enum_debug_info(g, entry); |
| 4135 | entry->data.enumeration.tag_type = tag_type_entry; | ||
| 4136 | 4149 | ||
| 4137 | g->builtin_types.entry_oformat_enum = entry; | 4150 | g->builtin_types.entry_oformat_enum = entry; |
| 4138 | g->primitive_type_table.put(&entry->name, entry); | 4151 | g->primitive_type_table.put(&entry->name, entry); |
std/build.zig+202| ... | @@ -32,6 +32,8 @@ pub const Builder = struct { | ... | @@ -32,6 +32,8 @@ pub const Builder = struct { |
| 32 | *exe = Exe { | 32 | *exe = Exe { |
| 33 | .root_src = root_src, | 33 | .root_src = root_src, |
| 34 | .name = name, | 34 | .name = name, |
| 35 | .target = Target.Native, | ||
| 36 | .linker_script = LinkerScript.None, | ||
| 35 | }; | 37 | }; |
| 36 | %return self.exe_list.append(exe); | 38 | %return self.exe_list.append(exe); |
| 37 | return exe; | 39 | return exe; |
| ... | @@ -53,9 +55,43 @@ pub const Builder = struct { | ... | @@ -53,9 +55,43 @@ pub const Builder = struct { |
| 53 | 55 | ||
| 54 | %return zig_args.append("build_exe"[0...]); // TODO issue #296 | 56 | %return zig_args.append("build_exe"[0...]); // TODO issue #296 |
| 55 | %return zig_args.append(exe.root_src); | 57 | %return zig_args.append(exe.root_src); |
| 58 | |||
| 59 | if (verbose) { | ||
| 60 | %return zig_args.append("--verbose"[0...]); // TODO issue #296 | ||
| 61 | } | ||
| 62 | |||
| 56 | %return zig_args.append("--name"[0...]); // TODO issue #296 | 63 | %return zig_args.append("--name"[0...]); // TODO issue #296 |
| 57 | %return zig_args.append(exe.name); | 64 | %return zig_args.append(exe.name); |
| 58 | 65 | ||
| 66 | switch (exe.target) { | ||
| 67 | Target.Native => {}, | ||
| 68 | Target.Cross => |cross_target| { | ||
| 69 | %return zig_args.append("--target-arch"[0...]); // TODO issue #296 | ||
| 70 | %return zig_args.append(targetArchName(cross_target.arch)); | ||
| 71 | |||
| 72 | %return zig_args.append("--target-os"[0...]); // TODO issue #296 | ||
| 73 | %return zig_args.append(targetOsName(cross_target.os)); | ||
| 74 | |||
| 75 | %return zig_args.append("--target-environ"[0...]); // TODO issue #296 | ||
| 76 | %return zig_args.append(targetEnvironName(cross_target.environ)); | ||
| 77 | }, | ||
| 78 | } | ||
| 79 | |||
| 80 | switch (exe.linker_script) { | ||
| 81 | LinkerScript.None => {}, | ||
| 82 | LinkerScript.Embed => |script| { | ||
| 83 | const tmp_file_name = "linker.ld.tmp"; // TODO issue #298 | ||
| 84 | io.writeFile(tmp_file_name, script, self.allocator) | ||
| 85 | %% |err| debug.panic("unable to write linker script: {}\n", @errorName(err)); | ||
| 86 | %return zig_args.append("--linker-script"[0...]); // TODO issue #296 | ||
| 87 | %return zig_args.append(tmp_file_name[0...]); // TODO issue #296 | ||
| 88 | }, | ||
| 89 | LinkerScript.Path => |path| { | ||
| 90 | %return zig_args.append("--linker-script"[0...]); // TODO issue #296 | ||
| 91 | %return zig_args.append(path); | ||
| 92 | }, | ||
| 93 | } | ||
| 94 | |||
| 59 | printInvocation(self.zig_exe, zig_args); | 95 | printInvocation(self.zig_exe, zig_args); |
| 60 | var child = %return os.ChildProcess.spawn(self.zig_exe, zig_args.toSliceConst(), os.environ, | 96 | var child = %return os.ChildProcess.spawn(self.zig_exe, zig_args.toSliceConst(), os.environ, |
| 61 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, self.allocator); | 97 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, self.allocator); |
| ... | @@ -72,9 +108,48 @@ pub const Builder = struct { | ... | @@ -72,9 +108,48 @@ pub const Builder = struct { |
| 72 | } | 108 | } |
| 73 | }; | 109 | }; |
| 74 | 110 | ||
| 111 | const CrossTarget = struct { | ||
| 112 | arch: Arch, | ||
| 113 | os: Os, | ||
| 114 | environ: Environ, | ||
| 115 | }; | ||
| 116 | |||
| 117 | const Target = enum { | ||
| 118 | Native, | ||
| 119 | Cross: CrossTarget, | ||
| 120 | }; | ||
| 121 | |||
| 122 | const LinkerScript = enum { | ||
| 123 | None, | ||
| 124 | Embed: []const u8, | ||
| 125 | Path: []const u8, | ||
| 126 | }; | ||
| 127 | |||
| 75 | const Exe = struct { | 128 | const Exe = struct { |
| 76 | root_src: []const u8, | 129 | root_src: []const u8, |
| 77 | name: []const u8, | 130 | name: []const u8, |
| 131 | target: Target, | ||
| 132 | linker_script: LinkerScript, | ||
| 133 | |||
| 134 | fn setTarget(self: &Exe, target_arch: Arch, target_os: Os, target_environ: Environ) { | ||
| 135 | self.target = Target.Cross { | ||
| 136 | CrossTarget { | ||
| 137 | .arch = target_arch, | ||
| 138 | .os = target_os, | ||
| 139 | .environ = target_environ, | ||
| 140 | } | ||
| 141 | }; | ||
| 142 | } | ||
| 143 | |||
| 144 | /// Exe keeps a reference to script for its lifetime or until this function | ||
| 145 | /// is called again. | ||
| 146 | fn setLinkerScriptContents(self: &Exe, script: []const u8) { | ||
| 147 | self.linker_script = LinkerScript.Embed { script }; | ||
| 148 | } | ||
| 149 | |||
| 150 | fn setLinkerScriptPath(self: &Exe, path: []const u8) { | ||
| 151 | self.linker_script = LinkerScript.Path { path }; | ||
| 152 | } | ||
| 78 | }; | 153 | }; |
| 79 | 154 | ||
| 80 | fn handleErr(err: error) -> noreturn { | 155 | fn handleErr(err: error) -> noreturn { |
| ... | @@ -88,3 +163,130 @@ fn printInvocation(exe_name: []const u8, args: &const List([]const u8)) { | ... | @@ -88,3 +163,130 @@ fn printInvocation(exe_name: []const u8, args: &const List([]const u8)) { |
| 88 | } | 163 | } |
| 89 | %%io.stderr.printf("\n"); | 164 | %%io.stderr.printf("\n"); |
| 90 | } | 165 | } |
| 166 | |||
| 167 | // TODO issue #299 | ||
| 168 | fn targetOsName(target_os: Os) -> []const u8 { | ||
| 169 | return switch (target_os) { | ||
| 170 | Os.freestanding => ([]const u8)("freestanding"), | ||
| 171 | Os.cloudabi => ([]const u8)("cloudabi"), | ||
| 172 | Os.darwin => ([]const u8)("darwin"), | ||
| 173 | Os.dragonfly => ([]const u8)("dragonfly"), | ||
| 174 | Os.freebsd => ([]const u8)("freebsd"), | ||
| 175 | Os.ios => ([]const u8)("ios"), | ||
| 176 | Os.kfreebsd => ([]const u8)("kfreebsd"), | ||
| 177 | Os.linux => ([]const u8)("linux"), | ||
| 178 | Os.lv2 => ([]const u8)("lv2"), | ||
| 179 | Os.macosx => ([]const u8)("macosx"), | ||
| 180 | Os.netbsd => ([]const u8)("netbsd"), | ||
| 181 | Os.openbsd => ([]const u8)("openbsd"), | ||
| 182 | Os.solaris => ([]const u8)("solaris"), | ||
| 183 | Os.windows => ([]const u8)("windows"), | ||
| 184 | Os.haiku => ([]const u8)("haiku"), | ||
| 185 | Os.minix => ([]const u8)("minix"), | ||
| 186 | Os.rtems => ([]const u8)("rtems"), | ||
| 187 | Os.nacl => ([]const u8)("nacl"), | ||
| 188 | Os.cnk => ([]const u8)("cnk"), | ||
| 189 | Os.bitrig => ([]const u8)("bitrig"), | ||
| 190 | Os.aix => ([]const u8)("aix"), | ||
| 191 | Os.cuda => ([]const u8)("cuda"), | ||
| 192 | Os.nvcl => ([]const u8)("nvcl"), | ||
| 193 | Os.amdhsa => ([]const u8)("amdhsa"), | ||
| 194 | Os.ps4 => ([]const u8)("ps4"), | ||
| 195 | Os.elfiamcu => ([]const u8)("elfiamcu"), | ||
| 196 | Os.tvos => ([]const u8)("tvos"), | ||
| 197 | Os.watchos => ([]const u8)("watchos"), | ||
| 198 | Os.mesa3d => ([]const u8)("mesa3d"), | ||
| 199 | }; | ||
| 200 | } | ||
| 201 | |||
| 202 | // TODO issue #299 | ||
| 203 | fn targetArchName(target_arch: Arch) -> []const u8 { | ||
| 204 | return switch (target_arch) { | ||
| 205 | Arch.armv8_2a => ([]const u8)("armv8_2a"), | ||
| 206 | Arch.armv8_1a => ([]const u8)("armv8_1a"), | ||
| 207 | Arch.armv8 => ([]const u8)("armv8"), | ||
| 208 | Arch.armv8m_baseline => ([]const u8)("armv8m_baseline"), | ||
| 209 | Arch.armv8m_mainline => ([]const u8)("armv8m_mainline"), | ||
| 210 | Arch.armv7 => ([]const u8)("armv7"), | ||
| 211 | Arch.armv7em => ([]const u8)("armv7em"), | ||
| 212 | Arch.armv7m => ([]const u8)("armv7m"), | ||
| 213 | Arch.armv7s => ([]const u8)("armv7s"), | ||
| 214 | Arch.armv7k => ([]const u8)("armv7k"), | ||
| 215 | Arch.armv6 => ([]const u8)("armv6"), | ||
| 216 | Arch.armv6m => ([]const u8)("armv6m"), | ||
| 217 | Arch.armv6k => ([]const u8)("armv6k"), | ||
| 218 | Arch.armv6t2 => ([]const u8)("armv6t2"), | ||
| 219 | Arch.armv5 => ([]const u8)("armv5"), | ||
| 220 | Arch.armv5te => ([]const u8)("armv5te"), | ||
| 221 | Arch.armv4t => ([]const u8)("armv4t"), | ||
| 222 | Arch.armeb => ([]const u8)("armeb"), | ||
| 223 | Arch.aarch64 => ([]const u8)("aarch64"), | ||
| 224 | Arch.aarch64_be => ([]const u8)("aarch64_be"), | ||
| 225 | Arch.avr => ([]const u8)("avr"), | ||
| 226 | Arch.bpfel => ([]const u8)("bpfel"), | ||
| 227 | Arch.bpfeb => ([]const u8)("bpfeb"), | ||
| 228 | Arch.hexagon => ([]const u8)("hexagon"), | ||
| 229 | Arch.mips => ([]const u8)("mips"), | ||
| 230 | Arch.mipsel => ([]const u8)("mipsel"), | ||
| 231 | Arch.mips64 => ([]const u8)("mips64"), | ||
| 232 | Arch.mips64el => ([]const u8)("mips64el"), | ||
| 233 | Arch.msp430 => ([]const u8)("msp430"), | ||
| 234 | Arch.powerpc => ([]const u8)("powerpc"), | ||
| 235 | Arch.powerpc64 => ([]const u8)("powerpc64"), | ||
| 236 | Arch.powerpc64le => ([]const u8)("powerpc64le"), | ||
| 237 | Arch.r600 => ([]const u8)("r600"), | ||
| 238 | Arch.amdgcn => ([]const u8)("amdgcn"), | ||
| 239 | Arch.sparc => ([]const u8)("sparc"), | ||
| 240 | Arch.sparcv9 => ([]const u8)("sparcv9"), | ||
| 241 | Arch.sparcel => ([]const u8)("sparcel"), | ||
| 242 | Arch.s390x => ([]const u8)("s390x"), | ||
| 243 | Arch.tce => ([]const u8)("tce"), | ||
| 244 | Arch.thumb => ([]const u8)("thumb"), | ||
| 245 | Arch.thumbeb => ([]const u8)("thumbeb"), | ||
| 246 | Arch.i386 => ([]const u8)("i386"), | ||
| 247 | Arch.x86_64 => ([]const u8)("x86_64"), | ||
| 248 | Arch.xcore => ([]const u8)("xcore"), | ||
| 249 | Arch.nvptx => ([]const u8)("nvptx"), | ||
| 250 | Arch.nvptx64 => ([]const u8)("nvptx64"), | ||
| 251 | Arch.le32 => ([]const u8)("le32"), | ||
| 252 | Arch.le64 => ([]const u8)("le64"), | ||
| 253 | Arch.amdil => ([]const u8)("amdil"), | ||
| 254 | Arch.amdil64 => ([]const u8)("amdil64"), | ||
| 255 | Arch.hsail => ([]const u8)("hsail"), | ||
| 256 | Arch.hsail64 => ([]const u8)("hsail64"), | ||
| 257 | Arch.spir => ([]const u8)("spir"), | ||
| 258 | Arch.spir64 => ([]const u8)("spir64"), | ||
| 259 | Arch.kalimbav3 => ([]const u8)("kalimbav3"), | ||
| 260 | Arch.kalimbav4 => ([]const u8)("kalimbav4"), | ||
| 261 | Arch.kalimbav5 => ([]const u8)("kalimbav5"), | ||
| 262 | Arch.shave => ([]const u8)("shave"), | ||
| 263 | Arch.lanai => ([]const u8)("lanai"), | ||
| 264 | Arch.wasm32 => ([]const u8)("wasm32"), | ||
| 265 | Arch.wasm64 => ([]const u8)("wasm64"), | ||
| 266 | Arch.renderscript32 => ([]const u8)("renderscript32"), | ||
| 267 | Arch.renderscript64 => ([]const u8)("renderscript64"), | ||
| 268 | }; | ||
| 269 | } | ||
| 270 | |||
| 271 | // TODO issue #299 | ||
| 272 | fn targetEnvironName(target_environ: Environ) -> []const u8 { | ||
| 273 | return switch (target_environ) { | ||
| 274 | Environ.gnu => ([]const u8)("gnu"), | ||
| 275 | Environ.gnuabi64 => ([]const u8)("gnuabi64"), | ||
| 276 | Environ.gnueabi => ([]const u8)("gnueabi"), | ||
| 277 | Environ.gnueabihf => ([]const u8)("gnueabihf"), | ||
| 278 | Environ.gnux32 => ([]const u8)("gnux32"), | ||
| 279 | Environ.code16 => ([]const u8)("code16"), | ||
| 280 | Environ.eabi => ([]const u8)("eabi"), | ||
| 281 | Environ.eabihf => ([]const u8)("eabihf"), | ||
| 282 | Environ.android => ([]const u8)("android"), | ||
| 283 | Environ.musl => ([]const u8)("musl"), | ||
| 284 | Environ.musleabi => ([]const u8)("musleabi"), | ||
| 285 | Environ.musleabihf => ([]const u8)("musleabihf"), | ||
| 286 | Environ.msvc => ([]const u8)("msvc"), | ||
| 287 | Environ.itanium => ([]const u8)("itanium"), | ||
| 288 | Environ.cygnus => ([]const u8)("cygnus"), | ||
| 289 | Environ.amdopencl => ([]const u8)("amdopencl"), | ||
| 290 | Environ.coreclr => ([]const u8)("coreclr"), | ||
| 291 | }; | ||
| 292 | } |
std/debug.zig+3-3| ... | @@ -28,7 +28,7 @@ pub coldcc fn panic(comptime format: []const u8, args: ...) -> noreturn { | ... | @@ -28,7 +28,7 @@ pub coldcc fn panic(comptime format: []const u8, args: ...) -> noreturn { |
| 28 | panicking = true; | 28 | panicking = true; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | %%io.stderr.printf(format, args); | 31 | %%io.stderr.printf(format ++ "\n", args); |
| 32 | %%printStackTrace(); | 32 | %%printStackTrace(); |
| 33 | 33 | ||
| 34 | os.abort(); | 34 | os.abort(); |
| ... | @@ -52,8 +52,8 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void { | ... | @@ -52,8 +52,8 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void { |
| 52 | .compile_unit_list = List(CompileUnit).init(&global_allocator), | 52 | .compile_unit_list = List(CompileUnit).init(&global_allocator), |
| 53 | }; | 53 | }; |
| 54 | const st = &stack_trace; | 54 | const st = &stack_trace; |
| 55 | %return io.openSelfExe(&st.self_exe_stream); | 55 | st.self_exe_stream = %return io.openSelfExe(); |
| 56 | defer st.self_exe_stream.close() %% {}; | 56 | defer st.self_exe_stream.close(); |
| 57 | 57 | ||
| 58 | %return st.elf.openStream(&global_allocator, &st.self_exe_stream); | 58 | %return st.elf.openStream(&global_allocator, &st.self_exe_stream); |
| 59 | defer st.elf.close(); | 59 | defer st.elf.close(); |
std/io.zig+64-78| ... | @@ -69,6 +69,27 @@ pub const OutStream = struct { | ... | @@ -69,6 +69,27 @@ pub const OutStream = struct { |
| 69 | buffer: [buffer_size]u8, | 69 | buffer: [buffer_size]u8, |
| 70 | index: usize, | 70 | index: usize, |
| 71 | 71 | ||
| 72 | /// `path` may need to be copied in memory to add a null terminating byte. In this case | ||
| 73 | /// a fixed size buffer of size std.os.max_noalloc_path_len is an attempted solution. If the fixed | ||
| 74 | /// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned. | ||
| 75 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. | ||
| 76 | /// Call close to clean up. | ||
| 77 | pub fn open(path: []const u8, allocator: ?&mem.Allocator) -> %OutStream { | ||
| 78 | switch (@compileVar("os")) { | ||
| 79 | Os.linux, Os.darwin, Os.macosx, Os.ios => { | ||
| 80 | const flags = system.O_LARGEFILE|system.O_WRONLY|system.O_CREAT|system.O_CLOEXEC|system.O_TRUNC; | ||
| 81 | const fd = %return os.posixOpen(path, flags, 0o666, allocator); | ||
| 82 | return OutStream { | ||
| 83 | .fd = fd, | ||
| 84 | .index = 0, | ||
| 85 | .buffer = undefined, | ||
| 86 | }; | ||
| 87 | }, | ||
| 88 | else => @compileError("Unsupported OS"), | ||
| 89 | } | ||
| 90 | |||
| 91 | } | ||
| 92 | |||
| 72 | pub fn writeByte(self: &OutStream, b: u8) -> %void { | 93 | pub fn writeByte(self: &OutStream, b: u8) -> %void { |
| 73 | if (self.buffer.len == self.index) %return self.flush(); | 94 | if (self.buffer.len == self.index) %return self.flush(); |
| 74 | self.buffer[self.index] = b; | 95 | self.buffer[self.index] = b; |
| ... | @@ -76,6 +97,11 @@ pub const OutStream = struct { | ... | @@ -76,6 +97,11 @@ pub const OutStream = struct { |
| 76 | } | 97 | } |
| 77 | 98 | ||
| 78 | pub fn write(self: &OutStream, bytes: []const u8) -> %void { | 99 | pub fn write(self: &OutStream, bytes: []const u8) -> %void { |
| 100 | if (bytes.len >= buffer_size) { | ||
| 101 | %return self.flush(); | ||
| 102 | return os.posixWrite(self.fd, bytes); | ||
| 103 | } | ||
| 104 | |||
| 79 | var src_index: usize = 0; | 105 | var src_index: usize = 0; |
| 80 | 106 | ||
| 81 | while (src_index < bytes.len) { | 107 | while (src_index < bytes.len) { |
| ... | @@ -119,35 +145,15 @@ pub const OutStream = struct { | ... | @@ -119,35 +145,15 @@ pub const OutStream = struct { |
| 119 | } | 145 | } |
| 120 | 146 | ||
| 121 | pub fn flush(self: &OutStream) -> %void { | 147 | pub fn flush(self: &OutStream) -> %void { |
| 122 | while (true) { | 148 | if (self.index != 0) { |
| 123 | const write_ret = system.write(self.fd, &self.buffer[0], self.index); | 149 | %return os.posixWrite(self.fd, self.buffer[0...self.index]); |
| 124 | const write_err = system.getErrno(write_ret); | ||
| 125 | if (write_err > 0) { | ||
| 126 | return switch (write_err) { | ||
| 127 | errno.EINTR => continue, | ||
| 128 | errno.EINVAL => unreachable, | ||
| 129 | errno.EDQUOT => error.DiskQuota, | ||
| 130 | errno.EFBIG => error.FileTooBig, | ||
| 131 | errno.EIO => error.Io, | ||
| 132 | errno.ENOSPC => error.NoSpaceLeft, | ||
| 133 | errno.EPERM => error.BadPerm, | ||
| 134 | errno.EPIPE => error.PipeFail, | ||
| 135 | else => error.Unexpected, | ||
| 136 | } | ||
| 137 | } | ||
| 138 | self.index = 0; | 150 | self.index = 0; |
| 139 | return; | ||
| 140 | } | 151 | } |
| 141 | } | 152 | } |
| 142 | 153 | ||
| 143 | pub fn close(self: &OutStream) { | 154 | pub fn close(self: &OutStream) { |
| 144 | while (true) { | 155 | assert(self.index == 0); |
| 145 | const close_ret = system.close(self.fd); | 156 | os.posixClose(self.fd); |
| 146 | const close_err = system.getErrno(close_ret); | ||
| 147 | if (close_err > 0 and close_err == errno.EINTR) | ||
| 148 | continue; | ||
| 149 | return; | ||
| 150 | } | ||
| 151 | } | 157 | } |
| 152 | }; | 158 | }; |
| 153 | 159 | ||
| ... | @@ -156,65 +162,32 @@ pub const OutStream = struct { | ... | @@ -156,65 +162,32 @@ pub const OutStream = struct { |
| 156 | pub const InStream = struct { | 162 | pub const InStream = struct { |
| 157 | fd: i32, | 163 | fd: i32, |
| 158 | 164 | ||
| 165 | /// `path` may need to be copied in memory to add a null terminating byte. In this case | ||
| 166 | /// a fixed size buffer of size std.os.max_noalloc_path_len is an attempted solution. If the fixed | ||
| 167 | /// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned. | ||
| 168 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. | ||
| 159 | /// Call close to clean up. | 169 | /// Call close to clean up. |
| 160 | pub fn open(is: &InStream, path: []const u8) -> %void { | 170 | pub fn open(path: []const u8, allocator: ?&mem.Allocator) -> %InStream { |
| 161 | switch (@compileVar("os")) { | 171 | switch (@compileVar("os")) { |
| 162 | Os.linux, Os.darwin => { | 172 | Os.linux, Os.darwin, Os.macosx, Os.ios => { |
| 163 | while (true) { | 173 | const flags = system.O_LARGEFILE|system.O_RDONLY; |
| 164 | const result = system.open(path, system.O_LARGEFILE|system.O_RDONLY, 0); | 174 | const fd = %return os.posixOpen(path, flags, 0, allocator); |
| 165 | const err = system.getErrno(result); | 175 | return InStream { |
| 166 | if (err > 0) { | 176 | .fd = fd, |
| 167 | return switch (err) { | 177 | }; |
| 168 | errno.EINTR => continue, | ||
| 169 | |||
| 170 | errno.EFAULT => unreachable, | ||
| 171 | errno.EINVAL => unreachable, | ||
| 172 | errno.EACCES => error.BadPerm, | ||
| 173 | errno.EFBIG, errno.EOVERFLOW => error.FileTooBig, | ||
| 174 | errno.EISDIR => error.IsDir, | ||
| 175 | errno.ELOOP => error.SymLinkLoop, | ||
| 176 | errno.EMFILE => error.ProcessFdQuotaExceeded, | ||
| 177 | errno.ENAMETOOLONG => error.NameTooLong, | ||
| 178 | errno.ENFILE => error.SystemFdQuotaExceeded, | ||
| 179 | errno.ENODEV => error.NoDevice, | ||
| 180 | errno.ENOENT => error.PathNotFound, | ||
| 181 | errno.ENOMEM => error.NoMem, | ||
| 182 | errno.ENOSPC => error.NoSpaceLeft, | ||
| 183 | errno.ENOTDIR => error.NotDir, | ||
| 184 | errno.EPERM => error.BadPerm, | ||
| 185 | else => error.Unexpected, | ||
| 186 | } | ||
| 187 | } | ||
| 188 | is.fd = i32(result); | ||
| 189 | return; | ||
| 190 | } | ||
| 191 | }, | 178 | }, |
| 192 | else => @compileError("unsupported OS"), | 179 | else => @compileError("Unsupported OS"), |
| 193 | } | 180 | } |
| 194 | |||
| 195 | } | 181 | } |
| 196 | 182 | ||
| 197 | /// Upon success, the stream is in an uninitialized state. To continue using it, | 183 | /// Upon success, the stream is in an uninitialized state. To continue using it, |
| 198 | /// you must use the open() function. | 184 | /// you must use the open() function. |
| 199 | pub fn close(is: &InStream) -> %void { | 185 | pub fn close(self: &InStream) { |
| 200 | switch (@compileVar("os")) { | 186 | switch (@compileVar("os")) { |
| 201 | Os.linux, Os.darwin => { | 187 | Os.linux, Os.darwin, Os.macosx, Os.ios => { |
| 202 | while (true) { | 188 | os.posixClose(self.fd); |
| 203 | const close_ret = system.close(is.fd); | ||
| 204 | const close_err = system.getErrno(close_ret); | ||
| 205 | if (close_err > 0) { | ||
| 206 | return switch (close_err) { | ||
| 207 | errno.EINTR => continue, | ||
| 208 | |||
| 209 | errno.EIO => error.Io, | ||
| 210 | errno.EBADF => error.BadFd, | ||
| 211 | else => error.Unexpected, | ||
| 212 | } | ||
| 213 | } | ||
| 214 | return; | ||
| 215 | } | ||
| 216 | }, | 189 | }, |
| 217 | else => @compileError("unsupported OS"), | 190 | else => @compileError("Unsupported OS"), |
| 218 | } | 191 | } |
| 219 | } | 192 | } |
| 220 | 193 | ||
| ... | @@ -373,15 +346,28 @@ pub const InStream = struct { | ... | @@ -373,15 +346,28 @@ pub const InStream = struct { |
| 373 | } | 346 | } |
| 374 | }; | 347 | }; |
| 375 | 348 | ||
| 376 | pub fn openSelfExe(stream: &InStream) -> %void { | 349 | pub fn openSelfExe() -> %InStream { |
| 377 | switch (@compileVar("os")) { | 350 | switch (@compileVar("os")) { |
| 378 | Os.linux => { | 351 | Os.linux => { |
| 379 | %return stream.open("/proc/self/exe"); | 352 | return InStream.open("/proc/self/exe", null); |
| 380 | }, | 353 | }, |
| 381 | Os.darwin => { | 354 | Os.darwin => { |
| 382 | %%stderr.printf("TODO: openSelfExe on Darwin\n"); | 355 | debug.panic("TODO: openSelfExe on Darwin"); |
| 383 | os.abort(); | ||
| 384 | }, | 356 | }, |
| 385 | else => @compileError("unsupported os"), | 357 | else => @compileError("Unsupported OS"), |
| 386 | } | 358 | } |
| 387 | } | 359 | } |
| 360 | |||
| 361 | /// `path` may need to be copied in memory to add a null terminating byte. In this case | ||
| 362 | /// a fixed size buffer of size std.os.max_noalloc_path_len is an attempted solution. If the fixed | ||
| 363 | /// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned. | ||
| 364 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. | ||
| 365 | pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator) -> %void { | ||
| 366 | // TODO have an unbuffered File abstraction and use that here. | ||
| 367 | // Then a buffered out stream abstraction can go on top of that for | ||
| 368 | // use cases like stdout and stderr. | ||
| 369 | var out_stream = %return OutStream.open(path, allocator); | ||
| 370 | defer out_stream.close(); | ||
| 371 | %return out_stream.write(data); | ||
| 372 | %return out_stream.flush(); | ||
| 373 | } |
std/os/darwin.zig+1-8| ... | @@ -71,17 +71,10 @@ pub fn close(fd: i32) -> usize { | ... | @@ -71,17 +71,10 @@ pub fn close(fd: i32) -> usize { |
| 71 | arch.syscall1(arch.SYS_close, usize(fd)) | 71 | arch.syscall1(arch.SYS_close, usize(fd)) |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | pub fn open_c(path: &const u8, flags: usize, perm: usize) -> usize { | 74 | pub fn open(path: &const u8, flags: usize, perm: usize) -> usize { |
| 75 | arch.syscall3(arch.SYS_open, usize(path), flags, perm) | 75 | arch.syscall3(arch.SYS_open, usize(path), flags, perm) |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | pub fn open(path: []const u8, flags: usize, perm: usize) -> usize { | ||
| 79 | const buf = @alloca(u8, path.len + 1); | ||
| 80 | @memcpy(&buf[0], &path[0], path.len); | ||
| 81 | buf[path.len] = 0; | ||
| 82 | return open_c(buf.ptr, flags, perm); | ||
| 83 | } | ||
| 84 | |||
| 85 | pub fn read(fd: i32, buf: &u8, count: usize) -> usize { | 78 | pub fn read(fd: i32, buf: &u8, count: usize) -> usize { |
| 86 | arch.syscall3(arch.SYS_read, usize(fd), usize(buf), count) | 79 | arch.syscall3(arch.SYS_read, usize(fd), usize(buf), count) |
| 87 | } | 80 | } |
std/os/index.zig+64-14| ... | @@ -8,6 +8,8 @@ pub const posix = switch(@compileVar("os")) { | ... | @@ -8,6 +8,8 @@ pub const posix = switch(@compileVar("os")) { |
| 8 | else => @compileError("Unsupported OS"), | 8 | else => @compileError("Unsupported OS"), |
| 9 | }; | 9 | }; |
| 10 | 10 | ||
| 11 | pub const max_noalloc_path_len = 1024; | ||
| 12 | |||
| 11 | const debug = @import("../debug.zig"); | 13 | const debug = @import("../debug.zig"); |
| 12 | const assert = debug.assert; | 14 | const assert = debug.assert; |
| 13 | 15 | ||
| ... | @@ -105,11 +107,12 @@ fn makePipe() -> %[2]i32 { | ... | @@ -105,11 +107,12 @@ fn makePipe() -> %[2]i32 { |
| 105 | } | 107 | } |
| 106 | 108 | ||
| 107 | fn destroyPipe(pipe: &const [2]i32) { | 109 | fn destroyPipe(pipe: &const [2]i32) { |
| 108 | closeNoIntr((*pipe)[0]); | 110 | posixClose((*pipe)[0]); |
| 109 | closeNoIntr((*pipe)[1]); | 111 | posixClose((*pipe)[1]); |
| 110 | } | 112 | } |
| 111 | 113 | ||
| 112 | fn closeNoIntr(fd: i32) { | 114 | /// Calls POSIX close, and keeps trying if it gets interrupted. |
| 115 | pub fn posixClose(fd: i32) { | ||
| 113 | while (true) { | 116 | while (true) { |
| 114 | const err = posix.getErrno(posix.close(fd)); | 117 | const err = posix.getErrno(posix.close(fd)); |
| 115 | if (err == errno.EINTR) { | 118 | if (err == errno.EINTR) { |
| ... | @@ -120,9 +123,56 @@ fn closeNoIntr(fd: i32) { | ... | @@ -120,9 +123,56 @@ fn closeNoIntr(fd: i32) { |
| 120 | } | 123 | } |
| 121 | } | 124 | } |
| 122 | 125 | ||
| 123 | fn openNoIntr(path: []const u8, flags: usize, perm: usize) -> %i32 { | 126 | /// Calls POSIX write, and keeps trying if it gets interrupted. |
| 127 | pub fn posixWrite(fd: i32, bytes: []const u8) -> %void { | ||
| 128 | while (true) { | ||
| 129 | const write_ret = posix.write(fd, bytes.ptr, bytes.len); | ||
| 130 | const write_err = posix.getErrno(write_ret); | ||
| 131 | if (write_err > 0) { | ||
| 132 | return switch (write_err) { | ||
| 133 | errno.EINTR => continue, | ||
| 134 | errno.EINVAL => unreachable, | ||
| 135 | errno.EDQUOT => error.DiskQuota, | ||
| 136 | errno.EFBIG => error.FileTooBig, | ||
| 137 | errno.EIO => error.Io, | ||
| 138 | errno.ENOSPC => error.NoSpaceLeft, | ||
| 139 | errno.EPERM => error.BadPerm, | ||
| 140 | errno.EPIPE => error.PipeFail, | ||
| 141 | else => error.Unexpected, | ||
| 142 | } | ||
| 143 | } | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | |||
| 149 | /// ::path may need to be copied in memory to add a null terminating byte. In this case | ||
| 150 | /// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed | ||
| 151 | /// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned. | ||
| 152 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. | ||
| 153 | /// Calls POSIX open, keeps trying if it gets interrupted, and translates | ||
| 154 | /// the return value into zig errors. | ||
| 155 | pub fn posixOpen(path: []const u8, flags: usize, perm: usize, allocator: ?&Allocator) -> %i32 { | ||
| 156 | var stack_buf: [max_noalloc_path_len]u8 = undefined; | ||
| 157 | var path0: []u8 = undefined; | ||
| 158 | var need_free = false; | ||
| 159 | |||
| 160 | if (path.len < stack_buf.len) { | ||
| 161 | path0 = stack_buf[0...path.len + 1]; | ||
| 162 | } else if (const a ?= allocator) { | ||
| 163 | path0 = %return a.alloc(u8, path.len + 1); | ||
| 164 | need_free = true; | ||
| 165 | } else { | ||
| 166 | return error.NameTooLong; | ||
| 167 | } | ||
| 168 | defer if (need_free) { | ||
| 169 | (??allocator).free(path0); | ||
| 170 | }; | ||
| 171 | mem.copy(u8, path0, path); | ||
| 172 | path0[path.len] = 0; | ||
| 173 | |||
| 124 | while (true) { | 174 | while (true) { |
| 125 | const result = posix.open(path, flags, perm); | 175 | const result = posix.open(path0.ptr, flags, perm); |
| 126 | const err = posix.getErrno(result); | 176 | const err = posix.getErrno(result); |
| 127 | if (err > 0) { | 177 | if (err > 0) { |
| 128 | return switch (err) { | 178 | return switch (err) { |
| ... | @@ -247,8 +297,8 @@ pub const ChildProcess = struct { | ... | @@ -247,8 +297,8 @@ pub const ChildProcess = struct { |
| 247 | 297 | ||
| 248 | pub fn wait(self: &ChildProcess) -> %Term { | 298 | pub fn wait(self: &ChildProcess) -> %Term { |
| 249 | defer { | 299 | defer { |
| 250 | closeNoIntr(self.err_pipe[0]); | 300 | posixClose(self.err_pipe[0]); |
| 251 | closeNoIntr(self.err_pipe[1]); | 301 | posixClose(self.err_pipe[1]); |
| 252 | }; | 302 | }; |
| 253 | 303 | ||
| 254 | var status: i32 = undefined; | 304 | var status: i32 = undefined; |
| ... | @@ -328,13 +378,13 @@ pub const ChildProcess = struct { | ... | @@ -328,13 +378,13 @@ pub const ChildProcess = struct { |
| 328 | const any_ignore = (stdin == StdIo.Ignore or stdout == StdIo.Ignore or stderr == StdIo.Ignore); | 378 | const any_ignore = (stdin == StdIo.Ignore or stdout == StdIo.Ignore or stderr == StdIo.Ignore); |
| 329 | // TODO issue #295 | 379 | // TODO issue #295 |
| 330 | //const dev_null_fd = if (any_ignore) { | 380 | //const dev_null_fd = if (any_ignore) { |
| 331 | // %return openNoIntr("/dev/null", posix.O_RDWR, 0) | 381 | // %return posixOpen("/dev/null", posix.O_RDWR, 0, null) |
| 332 | //} else { | 382 | //} else { |
| 333 | // undefined | 383 | // undefined |
| 334 | //}; | 384 | //}; |
| 335 | var dev_null_fd: i32 = undefined; | 385 | var dev_null_fd: i32 = undefined; |
| 336 | if (any_ignore) | 386 | if (any_ignore) |
| 337 | dev_null_fd = %return openNoIntr("/dev/null", posix.O_RDWR, 0); | 387 | dev_null_fd = %return posixOpen("/dev/null", posix.O_RDWR, 0, null); |
| 338 | 388 | ||
| 339 | // This pipe is used to communicate errors between the time of fork | 389 | // This pipe is used to communicate errors between the time of fork |
| 340 | // and execve from the child process to the parent process. | 390 | // and execve from the child process to the parent process. |
| ... | @@ -374,10 +424,10 @@ pub const ChildProcess = struct { | ... | @@ -374,10 +424,10 @@ pub const ChildProcess = struct { |
| 374 | } | 424 | } |
| 375 | 425 | ||
| 376 | // we are the parent | 426 | // we are the parent |
| 377 | if (stdin == StdIo.Pipe) { closeNoIntr(stdin_pipe[0]); } | 427 | if (stdin == StdIo.Pipe) { posixClose(stdin_pipe[0]); } |
| 378 | if (stdout == StdIo.Pipe) { closeNoIntr(stdout_pipe[1]); } | 428 | if (stdout == StdIo.Pipe) { posixClose(stdout_pipe[1]); } |
| 379 | if (stderr == StdIo.Pipe) { closeNoIntr(stderr_pipe[1]); } | 429 | if (stderr == StdIo.Pipe) { posixClose(stderr_pipe[1]); } |
| 380 | if (any_ignore) { closeNoIntr(dev_null_fd); } | 430 | if (any_ignore) { posixClose(dev_null_fd); } |
| 381 | 431 | ||
| 382 | return ChildProcess { | 432 | return ChildProcess { |
| 383 | .pid = i32(pid), | 433 | .pid = i32(pid), |
| ... | @@ -412,7 +462,7 @@ pub const ChildProcess = struct { | ... | @@ -412,7 +462,7 @@ pub const ChildProcess = struct { |
| 412 | fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) -> %void { | 462 | fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) -> %void { |
| 413 | switch (stdio) { | 463 | switch (stdio) { |
| 414 | StdIo.Pipe => %return dup2NoIntr(pipe_fd, std_fileno), | 464 | StdIo.Pipe => %return dup2NoIntr(pipe_fd, std_fileno), |
| 415 | StdIo.Close => closeNoIntr(std_fileno), | 465 | StdIo.Close => posixClose(std_fileno), |
| 416 | StdIo.Inherit => {}, | 466 | StdIo.Inherit => {}, |
| 417 | StdIo.Ignore => %return dup2NoIntr(dev_null_fd, std_fileno), | 467 | StdIo.Ignore => %return dup2NoIntr(dev_null_fd, std_fileno), |
| 418 | } | 468 | } |
std/os/linux.zig+3-24| ... | @@ -303,39 +303,18 @@ pub fn pwrite(fd: i32, buf: &const u8, count: usize, offset: usize) -> usize { | ... | @@ -303,39 +303,18 @@ pub fn pwrite(fd: i32, buf: &const u8, count: usize, offset: usize) -> usize { |
| 303 | arch.syscall4(arch.SYS_pwrite, usize(fd), usize(buf), count, offset) | 303 | arch.syscall4(arch.SYS_pwrite, usize(fd), usize(buf), count, offset) |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | pub fn open_c(path: &const u8, flags: usize, perm: usize) -> usize { | 306 | pub fn open(path: &const u8, flags: usize, perm: usize) -> usize { |
| 307 | arch.syscall3(arch.SYS_open, usize(path), flags, perm) | 307 | arch.syscall3(arch.SYS_open, usize(path), flags, perm) |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | pub fn open(path: []const u8, flags: usize, perm: usize) -> usize { | 310 | pub fn create(path: &const u8, perm: usize) -> usize { |
| 311 | const buf = @alloca(u8, path.len + 1); | ||
| 312 | @memcpy(&buf[0], &path[0], path.len); | ||
| 313 | buf[path.len] = 0; | ||
| 314 | return open_c(buf.ptr, flags, perm); | ||
| 315 | } | ||
| 316 | |||
| 317 | pub fn create_c(path: &const u8, perm: usize) -> usize { | ||
| 318 | arch.syscall2(arch.SYS_creat, usize(path), perm) | 311 | arch.syscall2(arch.SYS_creat, usize(path), perm) |
| 319 | } | 312 | } |
| 320 | 313 | ||
| 321 | pub fn create(path: []const u8, perm: usize) -> usize { | 314 | pub fn openat(dirfd: i32, path: &const u8, flags: usize, mode: usize) -> usize { |
| 322 | const buf = @alloca(u8, path.len + 1); | ||
| 323 | @memcpy(&buf[0], &path[0], path.len); | ||
| 324 | buf[path.len] = 0; | ||
| 325 | return create_c(buf.ptr, perm); | ||
| 326 | } | ||
| 327 | |||
| 328 | pub fn openat_c(dirfd: i32, path: &const u8, flags: usize, mode: usize) -> usize { | ||
| 329 | arch.syscall4(arch.SYS_openat, usize(dirfd), usize(path), flags, mode) | 315 | arch.syscall4(arch.SYS_openat, usize(dirfd), usize(path), flags, mode) |
| 330 | } | 316 | } |
| 331 | 317 | ||
| 332 | pub fn openat(dirfd: i32, path: []const u8, flags: usize, mode: usize) -> usize { | ||
| 333 | const buf = @alloca(u8, path.len + 1); | ||
| 334 | @memcpy(&buf[0], &path[0], path.len); | ||
| 335 | buf[path.len] = 0; | ||
| 336 | return openat_c(dirfd, buf.ptr, flags, mode); | ||
| 337 | } | ||
| 338 | |||
| 339 | pub fn close(fd: i32) -> usize { | 318 | pub fn close(fd: i32) -> usize { |
| 340 | arch.syscall1(arch.SYS_close, usize(fd)) | 319 | arch.syscall1(arch.SYS_close, usize(fd)) |
| 341 | } | 320 | } |
std/special/bootstrap.zig+2| ... | @@ -33,6 +33,7 @@ export nakedcc fn _start() -> noreturn { | ... | @@ -33,6 +33,7 @@ export nakedcc fn _start() -> noreturn { |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | fn callMain(envp: &?&u8) -> %void { | 35 | fn callMain(envp: &?&u8) -> %void { |
| 36 | // TODO issue #225 | ||
| 36 | const args = @alloca([]u8, argc); | 37 | const args = @alloca([]u8, argc); |
| 37 | for (args) |_, i| { | 38 | for (args) |_, i| { |
| 38 | const ptr = argv[i]; | 39 | const ptr = argv[i]; |
| ... | @@ -41,6 +42,7 @@ fn callMain(envp: &?&u8) -> %void { | ... | @@ -41,6 +42,7 @@ fn callMain(envp: &?&u8) -> %void { |
| 41 | 42 | ||
| 42 | var env_count: usize = 0; | 43 | var env_count: usize = 0; |
| 43 | while (envp[env_count] != null; env_count += 1) {} | 44 | while (envp[env_count] != null; env_count += 1) {} |
| 45 | // TODO issue #225 | ||
| 44 | const environ = @alloca(std.os.EnvPair, env_count); | 46 | const environ = @alloca(std.os.EnvPair, env_count); |
| 45 | for (environ) |_, env_i| { | 47 | for (environ) |_, env_i| { |
| 46 | const ptr = ??envp[env_i]; | 48 | const ptr = ??envp[env_i]; |
std/special/zigrt.zig+1-1| ... | @@ -11,6 +11,6 @@ export coldcc fn __zig_panic(message_ptr: &const u8, message_len: usize) -> nore | ... | @@ -11,6 +11,6 @@ export coldcc fn __zig_panic(message_ptr: &const u8, message_len: usize) -> nore |
| 11 | } else if (@compileVar("os") == Os.freestanding) { | 11 | } else if (@compileVar("os") == Os.freestanding) { |
| 12 | while (true) {} | 12 | while (true) {} |
| 13 | } else { | 13 | } else { |
| 14 | @import("std").debug.panic("{}\n", message_ptr[0...message_len]); | 14 | @import("std").debug.panic("{}", message_ptr[0...message_len]); |
| 15 | } | 15 | } |
| 16 | } | 16 | } |