Commit 8e3ab28be9

Andrew Kelley <superjoe30@gmail.com>
2016-05-13 18:23:03
ability to cast maybe pointer to isize/usize
also ability to put noalias on maybe pointer
1 parent 774ec1f
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 = &param_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) {
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)) ||
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))
 }
 
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,