authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-29 18:25:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-29 18:25:25-07:00
logba9b9cb38dbd66c7a600606c5599c80b115e0f85
tree0709a9bef6a253f2ec082085a9c95cf33069fcf7
parent2eef83e85f1f701fb67d410d3ffc1a1b344b4c13

AstGen: implement function prototypes with alignment exprs


5 files changed, 51 insertions(+), 10 deletions(-)

BRANCH_TODO+1
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1 * decouple AstGen from Module, Compilation
1 * modify dbg_stmt ZIR instructions to have line/column rather than node indexes2 * modify dbg_stmt ZIR instructions to have line/column rather than node indexes
2 * AstGen threadlocal3 * AstGen threadlocal
3 * extern "foo" for vars and for functions4 * extern "foo" for vars and for functions
src/AstGen.zig+9-3
...@@ -1048,10 +1048,12 @@ pub fn fnProtoExpr(...@@ -1048,10 +1048,12 @@ pub fn fnProtoExpr(
1048 assert(param_type_i == param_count);1048 assert(param_type_i == param_count);
1049 }1049 }
10501050
1051 if (fn_proto.ast.align_expr != 0) {1051 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
1052 return astgen.failNode(fn_proto.ast.align_expr, "TODO: AstGen: implement function prototypes with alignment expressions", .{});1052 break :inst try expr(gz, scope, align_rl, fn_proto.ast.align_expr);
1053 };
1054 if (fn_proto.ast.section_expr != 0) {
1055 return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{});
1053 }1056 }
1054 assert(fn_proto.ast.section_expr == 0); // caught by the parser
10551057
1056 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;1058 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1057 const is_inferred_error = token_tags[maybe_bang] == .bang;1059 const is_inferred_error = token_tags[maybe_bang] == .bang;
...@@ -1081,6 +1083,7 @@ pub fn fnProtoExpr(...@@ -1081,6 +1083,7 @@ pub fn fnProtoExpr(
1081 .param_types = param_types,1083 .param_types = param_types,
1082 .body = &[0]Zir.Inst.Index{},1084 .body = &[0]Zir.Inst.Index{},
1083 .cc = cc,1085 .cc = cc,
1086 .align_inst = align_inst,
1084 .lib_name = 0,1087 .lib_name = 0,
1085 .is_var_args = is_var_args,1088 .is_var_args = is_var_args,
1086 .is_inferred_error = false,1089 .is_inferred_error = false,
...@@ -2794,6 +2797,7 @@ fn fnDecl(...@@ -2794,6 +2797,7 @@ fn fnDecl(
2794 .param_types = param_types,2797 .param_types = param_types,
2795 .body = &[0]Zir.Inst.Index{},2798 .body = &[0]Zir.Inst.Index{},
2796 .cc = cc,2799 .cc = cc,
2800 .align_inst = .none, // passed in the per-decl data
2797 .lib_name = lib_name,2801 .lib_name = lib_name,
2798 .is_var_args = is_var_args,2802 .is_var_args = is_var_args,
2799 .is_inferred_error = false,2803 .is_inferred_error = false,
...@@ -2866,6 +2870,7 @@ fn fnDecl(...@@ -2866,6 +2870,7 @@ fn fnDecl(
2866 .param_types = param_types,2870 .param_types = param_types,
2867 .body = fn_gz.instructions.items,2871 .body = fn_gz.instructions.items,
2868 .cc = cc,2872 .cc = cc,
2873 .align_inst = .none, // passed in the per-decl data
2869 .lib_name = lib_name,2874 .lib_name = lib_name,
2870 .is_var_args = is_var_args,2875 .is_var_args = is_var_args,
2871 .is_inferred_error = is_inferred_error,2876 .is_inferred_error = is_inferred_error,
...@@ -3167,6 +3172,7 @@ fn testDecl(...@@ -3167,6 +3172,7 @@ fn testDecl(
3167 .param_types = &[0]Zir.Inst.Ref{},3172 .param_types = &[0]Zir.Inst.Ref{},
3168 .body = fn_block.instructions.items,3173 .body = fn_block.instructions.items,
3169 .cc = .none,3174 .cc = .none,
3175 .align_inst = .none,
3170 .lib_name = 0,3176 .lib_name = 0,
3171 .is_var_args = false,3177 .is_var_args = false,
3172 .is_inferred_error = true,3178 .is_inferred_error = true,
src/Module.zig+11-3
...@@ -1372,6 +1372,7 @@ pub const Scope = struct {...@@ -1372,6 +1372,7 @@ pub const Scope = struct {
1372 body: []const Zir.Inst.Index,1372 body: []const Zir.Inst.Index,
1373 ret_ty: Zir.Inst.Ref,1373 ret_ty: Zir.Inst.Ref,
1374 cc: Zir.Inst.Ref,1374 cc: Zir.Inst.Ref,
1375 align_inst: Zir.Inst.Ref,
1375 lib_name: u32,1376 lib_name: u32,
1376 is_var_args: bool,1377 is_var_args: bool,
1377 is_inferred_error: bool,1378 is_inferred_error: bool,
...@@ -1385,12 +1386,15 @@ pub const Scope = struct {...@@ -1385,12 +1386,15 @@ pub const Scope = struct {
1385 try gz.instructions.ensureUnusedCapacity(gpa, 1);1386 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1386 try astgen.instructions.ensureUnusedCapacity(gpa, 1);1387 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
13871388
1388 if (args.cc != .none or args.lib_name != 0 or args.is_var_args or args.is_test) {1389 if (args.cc != .none or args.lib_name != 0 or
1390 args.is_var_args or args.is_test or args.align_inst != .none)
1391 {
1389 try astgen.extra.ensureUnusedCapacity(1392 try astgen.extra.ensureUnusedCapacity(
1390 gpa,1393 gpa,
1391 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +1394 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
1392 args.param_types.len + args.body.len +1395 args.param_types.len + args.body.len +
1393 @boolToInt(args.lib_name != 0) +1396 @boolToInt(args.lib_name != 0) +
1397 @boolToInt(args.align_inst != .none) +
1394 @boolToInt(args.cc != .none),1398 @boolToInt(args.cc != .none),
1395 );1399 );
1396 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{1400 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
...@@ -1399,11 +1403,14 @@ pub const Scope = struct {...@@ -1399,11 +1403,14 @@ pub const Scope = struct {
1399 .param_types_len = @intCast(u32, args.param_types.len),1403 .param_types_len = @intCast(u32, args.param_types.len),
1400 .body_len = @intCast(u32, args.body.len),1404 .body_len = @intCast(u32, args.body.len),
1401 });1405 });
1406 if (args.lib_name != 0) {
1407 astgen.extra.appendAssumeCapacity(args.lib_name);
1408 }
1402 if (args.cc != .none) {1409 if (args.cc != .none) {
1403 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));1410 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));
1404 }1411 }
1405 if (args.lib_name != 0) {1412 if (args.align_inst != .none) {
1406 astgen.extra.appendAssumeCapacity(args.lib_name);1413 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
1407 }1414 }
1408 astgen.appendRefsAssumeCapacity(args.param_types);1415 astgen.appendRefsAssumeCapacity(args.param_types);
1409 astgen.extra.appendSliceAssumeCapacity(args.body);1416 astgen.extra.appendSliceAssumeCapacity(args.body);
...@@ -1418,6 +1425,7 @@ pub const Scope = struct {...@@ -1418,6 +1425,7 @@ pub const Scope = struct {
1418 .is_inferred_error = args.is_inferred_error,1425 .is_inferred_error = args.is_inferred_error,
1419 .has_lib_name = args.lib_name != 0,1426 .has_lib_name = args.lib_name != 0,
1420 .has_cc = args.cc != .none,1427 .has_cc = args.cc != .none,
1428 .has_align = args.align_inst != .none,
1421 .is_test = args.is_test,1429 .is_test = args.is_test,
1422 }),1430 }),
1423 .operand = payload_index,1431 .operand = payload_index,
src/Sema.zig+16-1
...@@ -2737,6 +2737,7 @@ fn zirFunc(...@@ -2737,6 +2737,7 @@ fn zirFunc(
2737 body,2737 body,
2738 extra.data.return_type,2738 extra.data.return_type,
2739 .Unspecified,2739 .Unspecified,
2740 Value.initTag(.null_value),
2740 false,2741 false,
2741 inferred_error_set,2742 inferred_error_set,
2742 );2743 );
...@@ -2750,6 +2751,7 @@ fn funcCommon(...@@ -2750,6 +2751,7 @@ fn funcCommon(
2750 body: []const Zir.Inst.Index,2751 body: []const Zir.Inst.Index,
2751 zir_return_type: Zir.Inst.Ref,2752 zir_return_type: Zir.Inst.Ref,
2752 cc: std.builtin.CallingConvention,2753 cc: std.builtin.CallingConvention,
2754 align_val: Value,
2753 var_args: bool,2755 var_args: bool,
2754 inferred_error_set: bool,2756 inferred_error_set: bool,
2755) InnerError!*Inst {2757) InnerError!*Inst {
...@@ -2762,7 +2764,7 @@ fn funcCommon(...@@ -2762,7 +2764,7 @@ fn funcCommon(
2762 }2764 }
27632765
2764 // Hot path for some common function types.2766 // Hot path for some common function types.
2765 if (zir_param_types.len == 0 and !var_args) {2767 if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) {
2766 if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {2768 if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
2767 return sema.mod.constType(sema.arena, src, Type.initTag(.fn_noreturn_no_args));2769 return sema.mod.constType(sema.arena, src, Type.initTag(.fn_noreturn_no_args));
2768 }2770 }
...@@ -2789,6 +2791,10 @@ fn funcCommon(...@@ -2789,6 +2791,10 @@ fn funcCommon(
2789 param_types[i] = try sema.resolveType(block, src, param_type);2791 param_types[i] = try sema.resolveType(block, src, param_type);
2790 }2792 }
27912793
2794 if (align_val.tag() != .null_value) {
2795 return sema.mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{});
2796 }
2797
2792 const fn_ty = try Type.Tag.function.create(sema.arena, .{2798 const fn_ty = try Type.Tag.function.create(sema.arena, .{
2793 .param_types = param_types,2799 .param_types = param_types,
2794 .return_type = return_type,2800 .return_type = return_type,
...@@ -5432,6 +5438,7 @@ fn zirFuncExtended(...@@ -5432,6 +5438,7 @@ fn zirFuncExtended(
5432 const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand);5438 const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand);
5433 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };5439 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
5434 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = extra.data.src_node };5440 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = extra.data.src_node };
5441 const align_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at align
5435 const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);5442 const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
54365443
5437 var extra_index: usize = extra.end;5444 var extra_index: usize = extra.end;
...@@ -5455,6 +5462,13 @@ fn zirFuncExtended(...@@ -5455,6 +5462,13 @@ fn zirFuncExtended(
5455 break :blk cc;5462 break :blk cc;
5456 } else .Unspecified;5463 } else .Unspecified;
54575464
5465 const align_val: Value = if (small.has_align) blk: {
5466 const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
5467 extra_index += 1;
5468 const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
5469 break :blk align_tv.val;
5470 } else Value.initTag(.null_value);
5471
5458 const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);5472 const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
5459 extra_index += param_types.len;5473 extra_index += param_types.len;
54605474
...@@ -5467,6 +5481,7 @@ fn zirFuncExtended(...@@ -5467,6 +5481,7 @@ fn zirFuncExtended(
5467 body,5481 body,
5468 extra.data.return_type,5482 extra.data.return_type,
5469 cc,5483 cc,
5484 align_val,
5470 small.is_var_args,5485 small.is_var_args,
5471 small.is_inferred_error,5486 small.is_inferred_error,
5472 );5487 );
src/Zir.zig+14-3
...@@ -2189,8 +2189,9 @@ pub const Inst = struct {...@@ -2189,8 +2189,9 @@ pub const Inst = struct {
2189 /// Trailing:2189 /// Trailing:
2190 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set2190 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
2191 /// 1. cc: Ref, // if has_cc is set2191 /// 1. cc: Ref, // if has_cc is set
2192 /// 2. param_type: Ref // for each param_types_len2192 /// 2. align: Ref, // if has_align is set
2193 /// 3. body: Index // for each body_len2193 /// 3. param_type: Ref // for each param_types_len
2194 /// 4. body: Index // for each body_len
2194 pub const ExtendedFunc = struct {2195 pub const ExtendedFunc = struct {
2195 src_node: i32,2196 src_node: i32,
2196 return_type: Ref,2197 return_type: Ref,
...@@ -2202,8 +2203,9 @@ pub const Inst = struct {...@@ -2202,8 +2203,9 @@ pub const Inst = struct {
2202 is_inferred_error: bool,2203 is_inferred_error: bool,
2203 has_lib_name: bool,2204 has_lib_name: bool,
2204 has_cc: bool,2205 has_cc: bool,
2206 has_align: bool,
2205 is_test: bool,2207 is_test: bool,
2206 _: u11 = undefined,2208 _: u10 = undefined,
2207 };2209 };
2208 };2210 };
22092211
...@@ -3966,6 +3968,7 @@ const Writer = struct {...@@ -3966,6 +3968,7 @@ const Writer = struct {
3966 inferred_error_set,3968 inferred_error_set,
3967 false,3969 false,
3968 .none,3970 .none,
3971 .none,
3969 body,3972 body,
3970 src,3973 src,
3971 );3974 );
...@@ -3988,6 +3991,11 @@ const Writer = struct {...@@ -3988,6 +3991,11 @@ const Writer = struct {
3988 extra_index += 1;3991 extra_index += 1;
3989 break :blk cc;3992 break :blk cc;
3990 };3993 };
3994 const align_inst: Inst.Ref = if (!small.has_align) .none else blk: {
3995 const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
3996 extra_index += 1;
3997 break :blk align_inst;
3998 };
39913999
3992 const param_types = self.code.refSlice(extra_index, extra.data.param_types_len);4000 const param_types = self.code.refSlice(extra_index, extra.data.param_types_len);
3993 extra_index += param_types.len;4001 extra_index += param_types.len;
...@@ -4001,6 +4009,7 @@ const Writer = struct {...@@ -4001,6 +4009,7 @@ const Writer = struct {
4001 small.is_inferred_error,4009 small.is_inferred_error,
4002 small.is_var_args,4010 small.is_var_args,
4003 cc,4011 cc,
4012 align_inst,
4004 body,4013 body,
4005 src,4014 src,
4006 );4015 );
...@@ -4053,6 +4062,7 @@ const Writer = struct {...@@ -4053,6 +4062,7 @@ const Writer = struct {
4053 inferred_error_set: bool,4062 inferred_error_set: bool,
4054 var_args: bool,4063 var_args: bool,
4055 cc: Inst.Ref,4064 cc: Inst.Ref,
4065 align_inst: Inst.Ref,
4056 body: []const Inst.Index,4066 body: []const Inst.Index,
4057 src: LazySrcLoc,4067 src: LazySrcLoc,
4058 ) !void {4068 ) !void {
...@@ -4064,6 +4074,7 @@ const Writer = struct {...@@ -4064,6 +4074,7 @@ const Writer = struct {
4064 try stream.writeAll("], ");4074 try stream.writeAll("], ");
4065 try self.writeInstRef(stream, ret_ty);4075 try self.writeInstRef(stream, ret_ty);
4066 try self.writeOptionalInstRef(stream, ", cc=", cc);4076 try self.writeOptionalInstRef(stream, ", cc=", cc);
4077 try self.writeOptionalInstRef(stream, ", align=", align_inst);
4067 try self.writeFlag(stream, ", vargs", var_args);4078 try self.writeFlag(stream, ", vargs", var_args);
4068 try self.writeFlag(stream, ", inferror", inferred_error_set);4079 try self.writeFlag(stream, ", inferror", inferred_error_set);
40694080