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 * decouple AstGen from Module, Compilation
12 * modify dbg_stmt ZIR instructions to have line/column rather than node indexes
23 * AstGen threadlocal
34 * extern "foo" for vars and for functions
src/AstGen.zig+9-3
......@@ -1048,10 +1048,12 @@ pub fn fnProtoExpr(
10481048 assert(param_type_i == param_count);
10491049 }
10501050
1051 if (fn_proto.ast.align_expr != 0) {
1052 return astgen.failNode(fn_proto.ast.align_expr, "TODO: AstGen: implement function prototypes with alignment expressions", .{});
1051 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
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", .{});
10531056 }
1054 assert(fn_proto.ast.section_expr == 0); // caught by the parser
10551057
10561058 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
10571059 const is_inferred_error = token_tags[maybe_bang] == .bang;
......@@ -1081,6 +1083,7 @@ pub fn fnProtoExpr(
10811083 .param_types = param_types,
10821084 .body = &[0]Zir.Inst.Index{},
10831085 .cc = cc,
1086 .align_inst = align_inst,
10841087 .lib_name = 0,
10851088 .is_var_args = is_var_args,
10861089 .is_inferred_error = false,
......@@ -2794,6 +2797,7 @@ fn fnDecl(
27942797 .param_types = param_types,
27952798 .body = &[0]Zir.Inst.Index{},
27962799 .cc = cc,
2800 .align_inst = .none, // passed in the per-decl data
27972801 .lib_name = lib_name,
27982802 .is_var_args = is_var_args,
27992803 .is_inferred_error = false,
......@@ -2866,6 +2870,7 @@ fn fnDecl(
28662870 .param_types = param_types,
28672871 .body = fn_gz.instructions.items,
28682872 .cc = cc,
2873 .align_inst = .none, // passed in the per-decl data
28692874 .lib_name = lib_name,
28702875 .is_var_args = is_var_args,
28712876 .is_inferred_error = is_inferred_error,
......@@ -3167,6 +3172,7 @@ fn testDecl(
31673172 .param_types = &[0]Zir.Inst.Ref{},
31683173 .body = fn_block.instructions.items,
31693174 .cc = .none,
3175 .align_inst = .none,
31703176 .lib_name = 0,
31713177 .is_var_args = false,
31723178 .is_inferred_error = true,
src/Module.zig+11-3
......@@ -1372,6 +1372,7 @@ pub const Scope = struct {
13721372 body: []const Zir.Inst.Index,
13731373 ret_ty: Zir.Inst.Ref,
13741374 cc: Zir.Inst.Ref,
1375 align_inst: Zir.Inst.Ref,
13751376 lib_name: u32,
13761377 is_var_args: bool,
13771378 is_inferred_error: bool,
......@@ -1385,12 +1386,15 @@ pub const Scope = struct {
13851386 try gz.instructions.ensureUnusedCapacity(gpa, 1);
13861387 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 {
13891392 try astgen.extra.ensureUnusedCapacity(
13901393 gpa,
13911394 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
13921395 args.param_types.len + args.body.len +
13931396 @boolToInt(args.lib_name != 0) +
1397 @boolToInt(args.align_inst != .none) +
13941398 @boolToInt(args.cc != .none),
13951399 );
13961400 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
......@@ -1399,11 +1403,14 @@ pub const Scope = struct {
13991403 .param_types_len = @intCast(u32, args.param_types.len),
14001404 .body_len = @intCast(u32, args.body.len),
14011405 });
1406 if (args.lib_name != 0) {
1407 astgen.extra.appendAssumeCapacity(args.lib_name);
1408 }
14021409 if (args.cc != .none) {
14031410 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));
14041411 }
1405 if (args.lib_name != 0) {
1406 astgen.extra.appendAssumeCapacity(args.lib_name);
1412 if (args.align_inst != .none) {
1413 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
14071414 }
14081415 astgen.appendRefsAssumeCapacity(args.param_types);
14091416 astgen.extra.appendSliceAssumeCapacity(args.body);
......@@ -1418,6 +1425,7 @@ pub const Scope = struct {
14181425 .is_inferred_error = args.is_inferred_error,
14191426 .has_lib_name = args.lib_name != 0,
14201427 .has_cc = args.cc != .none,
1428 .has_align = args.align_inst != .none,
14211429 .is_test = args.is_test,
14221430 }),
14231431 .operand = payload_index,
src/Sema.zig+16-1
......@@ -2737,6 +2737,7 @@ fn zirFunc(
27372737 body,
27382738 extra.data.return_type,
27392739 .Unspecified,
2740 Value.initTag(.null_value),
27402741 false,
27412742 inferred_error_set,
27422743 );
......@@ -2750,6 +2751,7 @@ fn funcCommon(
27502751 body: []const Zir.Inst.Index,
27512752 zir_return_type: Zir.Inst.Ref,
27522753 cc: std.builtin.CallingConvention,
2754 align_val: Value,
27532755 var_args: bool,
27542756 inferred_error_set: bool,
27552757) InnerError!*Inst {
......@@ -2762,7 +2764,7 @@ fn funcCommon(
27622764 }
27632765
27642766 // 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) {
27662768 if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
27672769 return sema.mod.constType(sema.arena, src, Type.initTag(.fn_noreturn_no_args));
27682770 }
......@@ -2789,6 +2791,10 @@ fn funcCommon(
27892791 param_types[i] = try sema.resolveType(block, src, param_type);
27902792 }
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
27922798 const fn_ty = try Type.Tag.function.create(sema.arena, .{
27932799 .param_types = param_types,
27942800 .return_type = return_type,
......@@ -5432,6 +5438,7 @@ fn zirFuncExtended(
54325438 const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand);
54335439 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
54345440 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
54355442 const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
54365443
54375444 var extra_index: usize = extra.end;
......@@ -5455,6 +5462,13 @@ fn zirFuncExtended(
54555462 break :blk cc;
54565463 } 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
54585472 const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
54595473 extra_index += param_types.len;
54605474
......@@ -5467,6 +5481,7 @@ fn zirFuncExtended(
54675481 body,
54685482 extra.data.return_type,
54695483 cc,
5484 align_val,
54705485 small.is_var_args,
54715486 small.is_inferred_error,
54725487 );
src/Zir.zig+14-3
......@@ -2189,8 +2189,9 @@ pub const Inst = struct {
21892189 /// Trailing:
21902190 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
21912191 /// 1. cc: Ref, // if has_cc is set
2192 /// 2. param_type: Ref // for each param_types_len
2193 /// 3. body: Index // for each body_len
2192 /// 2. align: Ref, // if has_align is set
2193 /// 3. param_type: Ref // for each param_types_len
2194 /// 4. body: Index // for each body_len
21942195 pub const ExtendedFunc = struct {
21952196 src_node: i32,
21962197 return_type: Ref,
......@@ -2202,8 +2203,9 @@ pub const Inst = struct {
22022203 is_inferred_error: bool,
22032204 has_lib_name: bool,
22042205 has_cc: bool,
2206 has_align: bool,
22052207 is_test: bool,
2206 _: u11 = undefined,
2208 _: u10 = undefined,
22072209 };
22082210 };
22092211
......@@ -3966,6 +3968,7 @@ const Writer = struct {
39663968 inferred_error_set,
39673969 false,
39683970 .none,
3971 .none,
39693972 body,
39703973 src,
39713974 );
......@@ -3988,6 +3991,11 @@ const Writer = struct {
39883991 extra_index += 1;
39893992 break :blk cc;
39903993 };
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
39924000 const param_types = self.code.refSlice(extra_index, extra.data.param_types_len);
39934001 extra_index += param_types.len;
......@@ -4001,6 +4009,7 @@ const Writer = struct {
40014009 small.is_inferred_error,
40024010 small.is_var_args,
40034011 cc,
4012 align_inst,
40044013 body,
40054014 src,
40064015 );
......@@ -4053,6 +4062,7 @@ const Writer = struct {
40534062 inferred_error_set: bool,
40544063 var_args: bool,
40554064 cc: Inst.Ref,
4065 align_inst: Inst.Ref,
40564066 body: []const Inst.Index,
40574067 src: LazySrcLoc,
40584068 ) !void {
......@@ -4064,6 +4074,7 @@ const Writer = struct {
40644074 try stream.writeAll("], ");
40654075 try self.writeInstRef(stream, ret_ty);
40664076 try self.writeOptionalInstRef(stream, ", cc=", cc);
4077 try self.writeOptionalInstRef(stream, ", align=", align_inst);
40674078 try self.writeFlag(stream, ", vargs", var_args);
40684079 try self.writeFlag(stream, ", inferror", inferred_error_set);
40694080