mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 22:09:49 +00:00
parseh understands macros which alias global fn ptr vars
This commit is contained in:
parent
6b2e29c6ac
commit
b3459f64e7
@ -29,6 +29,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
|
||||
static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
|
||||
static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn);
|
||||
static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node);
|
||||
static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node);
|
||||
|
||||
static AstNode *first_executing_node(AstNode *node) {
|
||||
switch (node->type) {
|
||||
@ -1251,6 +1252,7 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
|
||||
child_import->importers.append({parent_import, node});
|
||||
|
||||
detect_top_level_decl_deps(g, child_import, child_import->root);
|
||||
analyze_top_level_decls_root(g, child_import, child_import->root);
|
||||
}
|
||||
|
||||
static void satisfy_dep(CodeGen *g, AstNode *node) {
|
||||
|
||||
@ -582,15 +582,34 @@ static void render_node(AstRender *ar, AstNode *node) {
|
||||
break;
|
||||
}
|
||||
case NodeTypeFnDef:
|
||||
zig_panic("TODO");
|
||||
for (int i = 0; i < node->data.fn_def.fn_proto->data.fn_proto.directives->length; i += 1) {
|
||||
render_node(ar, node->data.fn_def.fn_proto->data.fn_proto.directives->at(i));
|
||||
}
|
||||
render_node(ar, node->data.fn_def.fn_proto);
|
||||
fprintf(ar->f, " ");
|
||||
render_node(ar, node->data.fn_def.body);
|
||||
break;
|
||||
case NodeTypeFnDecl:
|
||||
zig_panic("TODO");
|
||||
case NodeTypeParamDecl:
|
||||
zig_panic("TODO");
|
||||
case NodeTypeBlock:
|
||||
zig_panic("TODO");
|
||||
fprintf(ar->f, "{\n");
|
||||
ar->indent += ar->indent_size;
|
||||
for (int i = 0; i < node->data.block.statements.length; i += 1) {
|
||||
AstNode *statement = node->data.block.statements.at(i);
|
||||
print_indent(ar);
|
||||
render_node(ar, statement);
|
||||
}
|
||||
ar->indent -= ar->indent_size;
|
||||
fprintf(ar->f, "\n");
|
||||
print_indent(ar);
|
||||
fprintf(ar->f, "}");
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
zig_panic("TODO");
|
||||
fprintf(ar->f, "#%s(\"%s\")\n", buf_ptr(&node->data.directive.name),
|
||||
buf_ptr(&node->data.directive.param));
|
||||
break;
|
||||
case NodeTypeReturnExpr:
|
||||
zig_panic("TODO");
|
||||
case NodeTypeVariableDeclaration:
|
||||
@ -621,7 +640,12 @@ static void render_node(AstRender *ar, AstNode *node) {
|
||||
case NodeTypeErrorValueDecl:
|
||||
zig_panic("TODO");
|
||||
case NodeTypeBinOpExpr:
|
||||
zig_panic("TODO");
|
||||
fprintf(ar->f, "(");
|
||||
render_node(ar, node->data.bin_op_expr.op1);
|
||||
fprintf(ar->f, " %s ", bin_op_str(node->data.bin_op_expr.bin_op));
|
||||
render_node(ar, node->data.bin_op_expr.op2);
|
||||
fprintf(ar->f, ")");
|
||||
break;
|
||||
case NodeTypeUnwrapErrorExpr:
|
||||
zig_panic("TODO");
|
||||
case NodeTypeNumberLiteral:
|
||||
@ -635,7 +659,11 @@ static void render_node(AstRender *ar, AstNode *node) {
|
||||
}
|
||||
break;
|
||||
case NodeTypeStringLiteral:
|
||||
zig_panic("TODO");
|
||||
if (node->data.string_literal.c) {
|
||||
fprintf(ar->f, "c");
|
||||
}
|
||||
fprintf(ar->f, "\"%s\"", buf_ptr(&node->data.string_literal.buf));
|
||||
break;
|
||||
case NodeTypeCharLiteral:
|
||||
{
|
||||
uint8_t c = node->data.char_literal.value;
|
||||
@ -665,7 +693,20 @@ static void render_node(AstRender *ar, AstNode *node) {
|
||||
break;
|
||||
}
|
||||
case NodeTypeFnCallExpr:
|
||||
zig_panic("TODO");
|
||||
if (node->data.fn_call_expr.is_builtin) {
|
||||
fprintf(ar->f, "@");
|
||||
}
|
||||
render_node(ar, node->data.fn_call_expr.fn_ref_expr);
|
||||
fprintf(ar->f, "(");
|
||||
for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
|
||||
AstNode *param = node->data.fn_call_expr.params.at(i);
|
||||
if (i != 0) {
|
||||
fprintf(ar->f, ", ");
|
||||
}
|
||||
render_node(ar, param);
|
||||
}
|
||||
fprintf(ar->f, ")");
|
||||
break;
|
||||
case NodeTypeArrayAccessExpr:
|
||||
zig_panic("TODO");
|
||||
case NodeTypeSliceExpr:
|
||||
@ -739,7 +780,12 @@ static void render_node(AstRender *ar, AstNode *node) {
|
||||
case NodeTypeStructField:
|
||||
zig_panic("TODO");
|
||||
case NodeTypeContainerInitExpr:
|
||||
zig_panic("TODO");
|
||||
fprintf(ar->f, "(");
|
||||
render_node(ar, node->data.container_init_expr.type);
|
||||
fprintf(ar->f, "){");
|
||||
assert(node->data.container_init_expr.entries.length == 0);
|
||||
fprintf(ar->f, "}");
|
||||
break;
|
||||
case NodeTypeStructValueField:
|
||||
zig_panic("TODO");
|
||||
case NodeTypeArrayType:
|
||||
|
||||
@ -612,6 +612,8 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
|
||||
return LLVMBuildUnreachable(g->builder);
|
||||
} else if (first_arg_ret) {
|
||||
return node->data.fn_call_expr.tmp_ptr;
|
||||
} else if (src_return_type->size_in_bits == 0) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
@ -2767,6 +2769,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
}
|
||||
|
||||
VariableTableEntry *variable = param_decl->data.param_decl.variable;
|
||||
assert(variable);
|
||||
|
||||
LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(param_decl->line + 1, param_decl->column + 1,
|
||||
fn_def_node->data.fn_def.block_context->di_scope);
|
||||
|
||||
@ -51,6 +51,7 @@ struct Context {
|
||||
AstNode *source_node;
|
||||
|
||||
CodeGen *codegen;
|
||||
bool transform_extern_fn_ptr;
|
||||
};
|
||||
|
||||
static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl,
|
||||
@ -196,6 +197,13 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {
|
||||
return create_prefix_node(c, PrefixOpNegation, num_lit_node);
|
||||
}
|
||||
|
||||
static AstNode *create_directive_node(Context *c, const char *name, const char *value) {
|
||||
AstNode *node = create_node(c, NodeTypeDirective);
|
||||
buf_init_from_str(&node->data.directive.name, name);
|
||||
buf_init_from_str(&node->data.directive.param, value);
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *child_type_node) {
|
||||
AstNode *node = create_node(c, NodeTypeTypeDecl);
|
||||
buf_init_from_str(&node->data.type_decl.symbol, name);
|
||||
@ -213,6 +221,80 @@ static AstNode *make_type_node(Context *c, TypeTableEntry *type_entry) {
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *create_fn_proto_node(Context *c, Buf *name, TypeTableEntry *fn_type) {
|
||||
assert(fn_type->id == TypeTableEntryIdFn);
|
||||
AstNode *node = create_node(c, NodeTypeFnProto);
|
||||
node->data.fn_proto.directives = create_empty_directives(c);
|
||||
node->data.fn_proto.directives->append(create_directive_node(c, "attribute", "inline"));
|
||||
node->data.fn_proto.visib_mod = c->visib_mod;
|
||||
buf_init_from_buf(&node->data.fn_proto.name, name);
|
||||
node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type);
|
||||
|
||||
for (int i = 0; i < fn_type->data.fn.fn_type_id.param_count; i += 1) {
|
||||
FnTypeParamInfo *info = &fn_type->data.fn.fn_type_id.param_info[i];
|
||||
Buf *name = buf_sprintf("arg_%d", i);
|
||||
node->data.fn_proto.params.append(create_param_decl_node(c, buf_ptr(name),
|
||||
make_type_node(c, info->type), info->is_noalias));
|
||||
}
|
||||
|
||||
normalize_parent_ptrs(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *create_one_statement_block(Context *c, AstNode *statement) {
|
||||
AstNode *node = create_node(c, NodeTypeBlock);
|
||||
node->data.block.statements.append(statement);
|
||||
|
||||
normalize_parent_ptrs(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *create_container_init_node(Context *c, AstNode *type_node) {
|
||||
AstNode *node = create_node(c, NodeTypeContainerInitExpr);
|
||||
node->data.container_init_expr.kind = ContainerInitKindArray;
|
||||
node->data.container_init_expr.type = type_node;
|
||||
|
||||
normalize_parent_ptrs(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *create_bin_op_node(Context *c, AstNode *lhs, BinOpType op, AstNode *rhs) {
|
||||
AstNode *node = create_node(c, NodeTypeBinOpExpr);
|
||||
node->data.bin_op_expr.op1 = lhs;
|
||||
node->data.bin_op_expr.bin_op = op;
|
||||
node->data.bin_op_expr.op2 = rhs;
|
||||
|
||||
normalize_parent_ptrs(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *create_inline_fn_node(Context *c, Buf *fn_name, Buf *var_name, TypeTableEntry *fn_type) {
|
||||
AstNode *node = create_node(c, NodeTypeFnDef);
|
||||
node->data.fn_def.fn_proto = create_fn_proto_node(c, fn_name, fn_type);
|
||||
|
||||
AstNode *unreach_type_node = make_type_node(c, c->codegen->builtin_types.entry_unreachable);
|
||||
AstNode *unreach_node = create_container_init_node(c, unreach_type_node);
|
||||
AstNode *unwrap_node = create_bin_op_node(c, create_symbol_node(c, buf_ptr(var_name)),
|
||||
BinOpTypeUnwrapMaybe, unreach_node);
|
||||
|
||||
AstNode *fn_call_node = create_node(c, NodeTypeFnCallExpr);
|
||||
fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node;
|
||||
for (int i = 0; i < fn_type->data.fn.fn_type_id.param_count; i += 1) {
|
||||
AstNode *decl_node = node->data.fn_def.fn_proto->data.fn_proto.params.at(i);
|
||||
Buf *param_name = &decl_node->data.param_decl.name;
|
||||
fn_call_node->data.fn_call_expr.params.append(create_symbol_node(c, buf_ptr(param_name)));
|
||||
}
|
||||
|
||||
normalize_parent_ptrs(fn_call_node);
|
||||
|
||||
node->data.fn_def.body = create_one_statement_block(c, fn_call_node);
|
||||
|
||||
normalize_parent_ptrs(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *decl_name(const Decl *decl) {
|
||||
const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
|
||||
return (const char *)named_decl->getName().bytes_begin();
|
||||
@ -1257,6 +1339,17 @@ static void process_symbol_macros(Context *c) {
|
||||
AstNode *var_node = create_var_decl_node(c, buf_ptr(ms.name),
|
||||
create_symbol_node(c, buf_ptr(ms.value)));
|
||||
c->macro_table.put(ms.name, var_node);
|
||||
} else if (c->transform_extern_fn_ptr || true) { // TODO take off the || true
|
||||
if (auto entry = c->global_value_table.maybe_get(ms.value)) {
|
||||
TypeTableEntry *maybe_type = entry->value.type;
|
||||
if (maybe_type->id == TypeTableEntryIdMaybe) {
|
||||
TypeTableEntry *fn_type = maybe_type->data.maybe.child_type;
|
||||
if (fn_type->id == TypeTableEntryIdFn) {
|
||||
AstNode *fn_node = create_inline_fn_node(c, ms.name, ms.value, fn_type);
|
||||
c->macro_table.put(ms.name, fn_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2109,18 +2109,15 @@ Foo fun(Foo *a);
|
||||
"pub const Foo = c_void;",
|
||||
"pub extern fn fun(a: ?&c_void);");
|
||||
|
||||
add_parseh_case("ignore #define for non-const", R"SOURCE(
|
||||
struct Foo {
|
||||
int x;
|
||||
};
|
||||
add_parseh_case("generate inline func for #define global extern fn", R"SOURCE(
|
||||
extern void (*fn_ptr)(void);
|
||||
#define Foo fn_ptr
|
||||
)SOURCE", 3,
|
||||
"pub type c_void = u8;",
|
||||
"pub const Foo = struct_Foo;",
|
||||
R"OUTPUT(export struct struct_Foo {
|
||||
x: c_int,
|
||||
})OUTPUT");
|
||||
#define foo fn_ptr
|
||||
)SOURCE", 2,
|
||||
"pub extern var fn_ptr: ?extern fn();",
|
||||
R"SOURCE(#attribute("inline")
|
||||
pub fn foo() {
|
||||
(fn_ptr ?? (unreachable){})()
|
||||
})SOURCE");
|
||||
}
|
||||
|
||||
static void print_compiler_invocation(TestCase *test_case) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user