aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Module.zig35
-rw-r--r--src/type.zig4
-rw-r--r--src/zir.zig9
-rw-r--r--src/zir_sema.zig32
4 files changed, 38 insertions, 42 deletions
diff --git a/src/Module.zig b/src/Module.zig
index a90998a386..322f190673 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -1087,14 +1087,23 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
if (fn_proto.getSectionExpr()) |sect_expr| {
return self.failNode(&fn_type_scope.base, sect_expr, "TODO implement function section expression", .{});
}
- if (fn_proto.getCallconvExpr()) |callconv_expr| {
- return self.failNode(
- &fn_type_scope.base,
- callconv_expr,
- "TODO implement function calling convention expression",
- .{},
- );
- }
+
+ const enum_literal_type = try astgen.addZIRInstConst(self, &fn_type_scope.base, fn_src, .{
+ .ty = Type.initTag(.type),
+ .val = Value.initTag(.enum_literal_type),
+ });
+ const enum_literal_type_rl: astgen.ResultLoc = .{ .ty = enum_literal_type };
+ const cc = if (fn_proto.getCallconvExpr()) |callconv_expr|
+ try astgen.expr(self, &fn_type_scope.base, enum_literal_type_rl, callconv_expr)
+ else
+ try astgen.addZIRInstConst(self, &fn_type_scope.base, fn_src, .{
+ .ty = Type.initTag(.enum_literal),
+ .val = try Value.Tag.enum_literal.create(
+ &fn_type_scope_arena.allocator,
+ try fn_type_scope_arena.allocator.dupe(u8, "Unspecified"),
+ ),
+ });
+
const return_type_expr = switch (fn_proto.return_type) {
.Explicit => |node| node,
.InferErrorSet => |node| return self.failNode(&fn_type_scope.base, node, "TODO implement inferred error sets", .{}),
@@ -1105,6 +1114,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
const fn_type_inst = try astgen.addZIRInst(self, &fn_type_scope.base, fn_src, zir.Inst.FnType, .{
.return_type = return_type_inst,
.param_types = param_types,
+ .cc = cc,
}, .{});
if (std.builtin.mode == .Debug and self.comp.verbose_ir) {
@@ -1230,14 +1240,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
};
};
- const is_inline = blk: {
- if (fn_proto.getExternExportInlineToken()) |maybe_inline_token| {
- if (tree.token_ids[maybe_inline_token] == .Keyword_inline) {
- break :blk true;
- }
- }
- break :blk false;
- };
+ const is_inline = fn_type.fnCallingConvention() == .Inline;
const anal_state = ([2]Fn.Analysis{ .queued, .inline_only })[@boolToInt(is_inline)];
new_func.* = .{
diff --git a/src/type.zig b/src/type.zig
index 837e1ad29a..e1006e554c 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -552,7 +552,9 @@ pub const Type = extern union {
if (i != 0) try out_stream.writeAll(", ");
try param_type.format("", .{}, out_stream);
}
- try out_stream.writeAll(") ");
+ try out_stream.writeAll(") callconv(.");
+ try out_stream.writeAll(@tagName(payload.cc));
+ try out_stream.writeAll(")");
ty = payload.return_type;
continue;
},
diff --git a/src/zir.zig b/src/zir.zig
index 30bfeead9b..eefded0c6f 100644
--- a/src/zir.zig
+++ b/src/zir.zig
@@ -863,9 +863,7 @@ pub const Inst = struct {
fn_type: *Inst,
body: Body,
},
- kw_args: struct {
- is_inline: bool = false,
- },
+ kw_args: struct {},
};
pub const FnType = struct {
@@ -875,10 +873,9 @@ pub const Inst = struct {
positionals: struct {
param_types: []*Inst,
return_type: *Inst,
+ cc: *Inst,
},
- kw_args: struct {
- cc: std.builtin.CallingConvention = .Unspecified,
- },
+ kw_args: struct {},
};
pub const IntType = struct {
diff --git a/src/zir_sema.zig b/src/zir_sema.zig
index a8120108a4..480e0b4c33 100644
--- a/src/zir_sema.zig
+++ b/src/zir_sema.zig
@@ -980,18 +980,8 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
const b = try mod.requireFunctionBlock(scope, inst.base.src);
const is_comptime_call = b.is_comptime or inst.kw_args.modifier == .compile_time;
- const is_inline_call = is_comptime_call or inst.kw_args.modifier == .always_inline or blk: {
- // This logic will get simplified by
- // https://github.com/ziglang/zig/issues/6429
- if (try mod.resolveDefinedValue(scope, func)) |func_val| {
- const module_fn = switch (func_val.tag()) {
- .function => func_val.castTag(.function).?.data,
- else => break :blk false,
- };
- break :blk module_fn.state == .inline_only;
- }
- break :blk false;
- };
+ const is_inline_call = is_comptime_call or inst.kw_args.modifier == .always_inline or
+ func.ty.fnCallingConvention() == .Inline;
if (is_inline_call) {
const func_val = try mod.resolveConstValue(scope, func);
const module_fn = switch (func_val.tag()) {
@@ -1075,7 +1065,7 @@ fn zirFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {
const fn_type = try resolveType(mod, scope, fn_inst.positionals.fn_type);
const new_func = try scope.arena().create(Module.Fn);
new_func.* = .{
- .state = if (fn_inst.kw_args.is_inline) .inline_only else .queued,
+ .state = if (fn_type.fnCallingConvention() == .Inline) .inline_only else .queued,
.zir = fn_inst.positionals.body,
.body = undefined,
.owner_decl = scope.ownerDecl().?,
@@ -1305,22 +1295,26 @@ fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*
const tracy = trace(@src());
defer tracy.end();
const return_type = try resolveType(mod, scope, fntype.positionals.return_type);
+ const cc_tv = try resolveInstConst(mod, scope, fntype.positionals.cc);
+ const cc_str = cc_tv.val.castTag(.enum_literal).?.data;
+ const cc = std.meta.stringToEnum(std.builtin.CallingConvention, cc_str) orelse
+ return mod.fail(scope, fntype.positionals.cc.src, "Unknown calling convention {s}", .{cc_str});
// Hot path for some common function types.
if (fntype.positionals.param_types.len == 0) {
- if (return_type.zigTypeTag() == .NoReturn and fntype.kw_args.cc == .Unspecified) {
+ if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
return mod.constType(scope, fntype.base.src, Type.initTag(.fn_noreturn_no_args));
}
- if (return_type.zigTypeTag() == .Void and fntype.kw_args.cc == .Unspecified) {
+ if (return_type.zigTypeTag() == .Void and cc == .Unspecified) {
return mod.constType(scope, fntype.base.src, Type.initTag(.fn_void_no_args));
}
- if (return_type.zigTypeTag() == .NoReturn and fntype.kw_args.cc == .Naked) {
+ if (return_type.zigTypeTag() == .NoReturn and cc == .Naked) {
return mod.constType(scope, fntype.base.src, Type.initTag(.fn_naked_noreturn_no_args));
}
- if (return_type.zigTypeTag() == .Void and fntype.kw_args.cc == .C) {
+ if (return_type.zigTypeTag() == .Void and cc == .C) {
return mod.constType(scope, fntype.base.src, Type.initTag(.fn_ccc_void_no_args));
}
}
@@ -1337,9 +1331,9 @@ fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*
}
const fn_ty = try Type.Tag.function.create(arena, .{
- .cc = fntype.kw_args.cc,
- .return_type = return_type,
.param_types = param_types,
+ .return_type = return_type,
+ .cc = cc,
});
return mod.constType(scope, fntype.base.src, fn_ty);
}