mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
translate-c: create inline fn for always_inline
This commit is contained in:
parent
ed2a5081e1
commit
d949180ab0
6 changed files with 34 additions and 4 deletions
|
|
@ -536,6 +536,9 @@ pub const FunctionDecl = opaque {
|
|||
pub const isInlineSpecified = ZigClangFunctionDecl_isInlineSpecified;
|
||||
extern fn ZigClangFunctionDecl_isInlineSpecified(*const FunctionDecl) bool;
|
||||
|
||||
pub const hasAlwaysInlineAttr = ZigClangFunctionDecl_hasAlwaysInlineAttr;
|
||||
extern fn ZigClangFunctionDecl_hasAlwaysInlineAttr(*const FunctionDecl) bool;
|
||||
|
||||
pub const isDefined = ZigClangFunctionDecl_isDefined;
|
||||
extern fn ZigClangFunctionDecl_isDefined(*const FunctionDecl) bool;
|
||||
|
||||
|
|
|
|||
|
|
@ -575,12 +575,14 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
|
|||
const fn_decl_loc = fn_decl.getLocation();
|
||||
const has_body = fn_decl.hasBody();
|
||||
const storage_class = fn_decl.getStorageClass();
|
||||
const is_always_inline = has_body and fn_decl.hasAlwaysInlineAttr();
|
||||
var decl_ctx = FnDeclContext{
|
||||
.fn_name = fn_name,
|
||||
.has_body = has_body,
|
||||
.storage_class = storage_class,
|
||||
.is_always_inline = is_always_inline,
|
||||
.is_export = switch (storage_class) {
|
||||
.None => has_body and !fn_decl.isInlineSpecified(),
|
||||
.None => has_body and !is_always_inline and !fn_decl.isInlineSpecified(),
|
||||
.Extern, .Static => false,
|
||||
.PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),
|
||||
.Auto => unreachable, // Not legal on functions
|
||||
|
|
@ -615,6 +617,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
|
|||
decl_ctx.has_body = false;
|
||||
decl_ctx.storage_class = .Extern;
|
||||
decl_ctx.is_export = false;
|
||||
decl_ctx.is_always_inline = false;
|
||||
try warn(c, &c.global_scope.base, fn_decl_loc, "TODO unable to translate variadic function, demoted to extern", .{});
|
||||
}
|
||||
break :blk transFnProto(c, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
|
||||
|
|
@ -653,6 +656,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
|
|||
const param_name = param.name orelse {
|
||||
proto_node.data.is_extern = true;
|
||||
proto_node.data.is_export = false;
|
||||
proto_node.data.is_inline = false;
|
||||
try warn(c, &c.global_scope.base, fn_decl_loc, "function {s} parameter has no name, demoted to extern", .{fn_name});
|
||||
return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
|
||||
};
|
||||
|
|
@ -685,6 +689,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
|
|||
=> {
|
||||
proto_node.data.is_extern = true;
|
||||
proto_node.data.is_export = false;
|
||||
proto_node.data.is_inline = false;
|
||||
try warn(c, &c.global_scope.base, fn_decl_loc, "unable to translate function, demoted to extern", .{});
|
||||
return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
|
||||
},
|
||||
|
|
@ -704,6 +709,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
|
|||
=> {
|
||||
proto_node.data.is_extern = true;
|
||||
proto_node.data.is_export = false;
|
||||
proto_node.data.is_inline = false;
|
||||
try warn(c, &c.global_scope.base, fn_decl_loc, "unable to create a return value for function, demoted to extern", .{});
|
||||
return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
|
||||
},
|
||||
|
|
@ -974,6 +980,7 @@ fn buildFlexibleArrayFn(
|
|||
.is_pub = true,
|
||||
.is_extern = false,
|
||||
.is_export = false,
|
||||
.is_inline = false,
|
||||
.is_var_args = false,
|
||||
.name = field_name,
|
||||
.linksection_string = null,
|
||||
|
|
@ -4821,6 +4828,7 @@ const FnDeclContext = struct {
|
|||
fn_name: []const u8,
|
||||
has_body: bool,
|
||||
storage_class: clang.StorageClass,
|
||||
is_always_inline: bool,
|
||||
is_export: bool,
|
||||
};
|
||||
|
||||
|
|
@ -4871,7 +4879,7 @@ fn transFnNoProto(
|
|||
is_pub: bool,
|
||||
) !*ast.Payload.Func {
|
||||
const cc = try transCC(c, fn_ty, source_loc);
|
||||
const is_var_args = if (fn_decl_context) |ctx| (!ctx.is_export and ctx.storage_class != .Static) else true;
|
||||
const is_var_args = if (fn_decl_context) |ctx| (!ctx.is_export and ctx.storage_class != .Static and !ctx.is_always_inline) else true;
|
||||
return finishTransFnProto(c, null, null, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
|
||||
}
|
||||
|
||||
|
|
@ -4888,9 +4896,9 @@ fn finishTransFnProto(
|
|||
) !*ast.Payload.Func {
|
||||
const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
|
||||
const is_extern = if (fn_decl_context) |ctx| !ctx.has_body else false;
|
||||
const is_inline = if (fn_decl_context) |ctx| ctx.is_always_inline else false;
|
||||
const scope = &c.global_scope.base;
|
||||
|
||||
// TODO check for always_inline attribute
|
||||
// TODO check for align attribute
|
||||
|
||||
var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa);
|
||||
|
|
@ -4934,7 +4942,7 @@ fn finishTransFnProto(
|
|||
|
||||
const alignment = if (fn_decl) |decl| zigAlignment(decl.getAlignedAttribute(c.clang_context)) else null;
|
||||
|
||||
const explicit_callconv = if ((is_export or is_extern) and cc == .C) null else cc;
|
||||
const explicit_callconv = if ((is_inline or is_export or is_extern) and cc == .C) null else cc;
|
||||
|
||||
const return_type_node = blk: {
|
||||
if (fn_ty.getNoReturnAttr()) {
|
||||
|
|
@ -4963,6 +4971,7 @@ fn finishTransFnProto(
|
|||
.is_pub = is_pub,
|
||||
.is_extern = is_extern,
|
||||
.is_export = is_export,
|
||||
.is_inline = is_inline,
|
||||
.is_var_args = is_var_args,
|
||||
.name = name,
|
||||
.linksection_string = linksection_string,
|
||||
|
|
|
|||
|
|
@ -540,6 +540,7 @@ pub const Payload = struct {
|
|||
is_pub: bool,
|
||||
is_extern: bool,
|
||||
is_export: bool,
|
||||
is_inline: bool,
|
||||
is_var_args: bool,
|
||||
name: ?[]const u8,
|
||||
linksection_string: ?[]const u8,
|
||||
|
|
@ -2614,6 +2615,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
|
|||
if (payload.is_pub) _ = try c.addToken(.keyword_pub, "pub");
|
||||
if (payload.is_extern) _ = try c.addToken(.keyword_extern, "extern");
|
||||
if (payload.is_export) _ = try c.addToken(.keyword_export, "export");
|
||||
if (payload.is_inline) _ = try c.addToken(.keyword_inline, "inline");
|
||||
const fn_token = try c.addToken(.keyword_fn, "fn");
|
||||
if (payload.name) |some| _ = try c.addIdentifier(some);
|
||||
|
||||
|
|
|
|||
|
|
@ -2120,6 +2120,11 @@ bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *s
|
|||
return casted->isInlineSpecified();
|
||||
}
|
||||
|
||||
bool ZigClangFunctionDecl_hasAlwaysInlineAttr(const struct ZigClangFunctionDecl *self) {
|
||||
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
|
||||
return casted->hasAttr<clang::AlwaysInlineAttr>();
|
||||
}
|
||||
|
||||
const char* ZigClangFunctionDecl_getSectionAttribute(const struct ZigClangFunctionDecl *self, size_t *len) {
|
||||
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
|
||||
if (const clang::SectionAttr *SA = casted->getAttr<clang::SectionAttr>()) {
|
||||
|
|
|
|||
|
|
@ -1111,6 +1111,7 @@ ZIG_EXTERN_C bool ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefi
|
|||
ZIG_EXTERN_C bool ZigClangFunctionDecl_isThisDeclarationADefinition(const struct ZigClangFunctionDecl *);
|
||||
ZIG_EXTERN_C bool ZigClangFunctionDecl_doesThisDeclarationHaveABody(const struct ZigClangFunctionDecl *);
|
||||
ZIG_EXTERN_C bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *);
|
||||
ZIG_EXTERN_C bool ZigClangFunctionDecl_hasAlwaysInlineAttr(const struct ZigClangFunctionDecl *);
|
||||
ZIG_EXTERN_C bool ZigClangFunctionDecl_isDefined(const struct ZigClangFunctionDecl *);
|
||||
ZIG_EXTERN_C const struct ZigClangFunctionDecl* ZigClangFunctionDecl_getDefinition(const struct ZigClangFunctionDecl *);
|
||||
ZIG_EXTERN_C const char* ZigClangFunctionDecl_getSectionAttribute(const struct ZigClangFunctionDecl *, size_t *);
|
||||
|
|
|
|||
|
|
@ -849,6 +849,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||
\\pub extern fn foo() noreturn;
|
||||
});
|
||||
|
||||
cases.add("always_inline attribute",
|
||||
\\__attribute__((always_inline)) int foo() {
|
||||
\\ return 5;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub inline fn foo() c_int {
|
||||
\\ return 5;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("add, sub, mul, div, rem",
|
||||
\\int s() {
|
||||
\\ int a, b, c;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue