diff --git a/src/analyze.cpp b/src/analyze.cpp index 5eb1be4381..aa8fe0d060 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4168,6 +4168,16 @@ static TypeTableEntry *resolve_cast(CodeGen *g, BlockContext *context, AstNode * return wanted_type; } +static bool type_is_codegen_pointer(TypeTableEntry *type) { + if (type->id == TypeTableEntryIdPointer) return true; + if (type->id == TypeTableEntryIdFn) return true; + if (type->id == TypeTableEntryIdMaybe) { + if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return true; + if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return true; + } + return false; +} + static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) { @@ -4207,7 +4217,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B // explicit cast from pointer to isize or usize if ((wanted_type_canon == g->builtin_types.entry_isize || wanted_type_canon == g->builtin_types.entry_usize) && - actual_type_canon->id == TypeTableEntryIdPointer) + type_is_codegen_pointer(actual_type_canon)) { return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPtrToInt, false); } @@ -6193,9 +6203,8 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { AstNodeParamDecl *param_decl = ¶m_decl_node->data.param_decl; TypeTableEntry *type = unwrapped_node_type(param_decl->type); - if (param_decl->is_noalias && type->id != TypeTableEntryIdPointer) { - add_node_error(g, param_decl_node, - buf_sprintf("noalias on non-pointer parameter")); + if (param_decl->is_noalias && !type_is_codegen_pointer(type)) { + add_node_error(g, param_decl_node, buf_sprintf("noalias on non-pointer parameter")); } if (fn_type->data.fn.fn_type_id.is_extern && type->id == TypeTableEntryIdStruct) { diff --git a/src/codegen.cpp b/src/codegen.cpp index d30c9e3f44..f42cf5a1a0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3923,7 +3923,7 @@ static void do_code_gen(CodeGen *g) { TypeTableEntry *param_type = info->type; LLVMValueRef argument_val = LLVMGetParam(fn_table_entry->fn_value, gen_index); bool param_is_noalias = param_node->data.param_decl.is_noalias; - if (param_type->id == TypeTableEntryIdPointer && param_is_noalias) { + if (param_is_noalias) { LLVMAddAttribute(argument_val, LLVMNoAliasAttribute); } if ((param_type->id == TypeTableEntryIdPointer && (param_type->data.pointer.is_const || fn_table_entry->is_pure)) || diff --git a/std/linux.zig b/std/linux.zig index ec4988a70b..ae10a5e46a 100644 --- a/std/linux.zig +++ b/std/linux.zig @@ -402,7 +402,7 @@ pub fn recvmsg(fd: i32, msg: &arch.msghdr, flags: i32) -> isize { } pub fn recvfrom(fd: i32, noalias buf: &u8, len: isize, flags: i32, - noalias addr: &sockaddr, noalias alen: &socklen_t) -> isize + noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) -> isize { arch.syscall6(arch.SYS_recvfrom, fd, isize(buf), len, flags, isize(addr), isize(alen)) } @@ -419,7 +419,7 @@ pub fn listen(fd: i32, backlog: i32) -> isize { arch.syscall2(arch.SYS_listen, fd, backlog) } -pub fn sendto(fd: i32, buf: &const u8, len: isize, flags: i32, addr: &const sockaddr, alen: socklen_t) -> isize { +pub fn sendto(fd: i32, buf: &const u8, len: isize, flags: i32, addr: ?&const sockaddr, alen: socklen_t) -> isize { arch.syscall6(arch.SYS_sendto, fd, isize(buf), len, flags, isize(addr), isize(alen)) } diff --git a/std/net.zig b/std/net.zig index dafa31f277..f257ea7d22 100644 --- a/std/net.zig +++ b/std/net.zig @@ -6,10 +6,42 @@ pub error SigInterrupt; pub error Unexpected; pub error Io; pub error TimedOut; +pub error ConnectionReset; +pub error NoMem; +pub error NotSocket; struct Connection { socket_fd: i32, + pub fn send(c: Connection, buf: []const u8) -> %isize { + const send_ret = linux.sendto(c.socket_fd, buf.ptr, buf.len, 0, null, 0); + const send_err = linux.get_errno(send_ret); + switch (send_err) { + 0 => return send_ret, + errno.EINVAL => unreachable{}, + errno.EFAULT => unreachable{}, + errno.ECONNRESET => return error.ConnectionReset, + errno.EINTR => return error.SigInterrupt, + // TODO there are more possible errors + else => return error.Unexpected, + } + } + + pub fn recv(c: Connection, buf: []u8) -> %isize { + const recv_ret = linux.recvfrom(c.socket_fd, buf.ptr, buf.len, 0, null, null); + const recv_err = linux.get_errno(recv_ret); + switch (recv_err) { + 0 => return recv_ret, + errno.EINVAL => unreachable{}, + errno.EFAULT => unreachable{}, + errno.ENOTSOCK => return error.NotSocket, + errno.EINTR => return error.SigInterrupt, + errno.ENOMEM => return error.NoMem, + // TODO more error values + else => return error.Unexpected, + } + } + pub fn close(c: Connection) -> %void { switch (linux.get_errno(linux.close(c.socket_fd))) { 0 => return,