mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 15:13:08 +00:00
rewrite parseh to use AST instead of direct types
some tests still failing
This commit is contained in:
parent
0f38955ee5
commit
e1d5da20a5
@ -751,6 +751,7 @@ struct AstNodeContainerDecl {
|
||||
ZigList<AstNode *> fields;
|
||||
ZigList<AstNode *> decls;
|
||||
ContainerLayout layout;
|
||||
AstNode *init_arg_expr; // enum(T) or struct(endianness)
|
||||
};
|
||||
|
||||
struct AstNodeStructField {
|
||||
|
||||
@ -112,16 +112,16 @@ static const char *extern_string(bool is_extern) {
|
||||
return is_extern ? "extern " : "";
|
||||
}
|
||||
|
||||
static const char *calling_convention_string(CallingConvention cc) {
|
||||
switch (cc) {
|
||||
case CallingConventionUnspecified: return "";
|
||||
case CallingConventionC: return "extern ";
|
||||
case CallingConventionCold: return "coldcc ";
|
||||
case CallingConventionNaked: return "nakedcc ";
|
||||
case CallingConventionStdcall: return "stdcallcc ";
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
//static const char *calling_convention_string(CallingConvention cc) {
|
||||
// switch (cc) {
|
||||
// case CallingConventionUnspecified: return "";
|
||||
// case CallingConventionC: return "extern ";
|
||||
// case CallingConventionCold: return "coldcc ";
|
||||
// case CallingConventionNaked: return "nakedcc ";
|
||||
// case CallingConventionStdcall: return "stdcallcc ";
|
||||
// }
|
||||
// zig_unreachable();
|
||||
//}
|
||||
|
||||
static const char *inline_string(bool is_inline) {
|
||||
return is_inline ? "inline " : "";
|
||||
@ -439,8 +439,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
fprintf(ar->f, ")");
|
||||
|
||||
AstNode *return_type_node = node->data.fn_proto.return_type;
|
||||
fprintf(ar->f, " -> ");
|
||||
render_node_grouped(ar, return_type_node);
|
||||
if (return_type_node != nullptr) {
|
||||
fprintf(ar->f, " -> ");
|
||||
render_node_grouped(ar, return_type_node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeTypeFnDef:
|
||||
@ -651,16 +653,19 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
break;
|
||||
case NodeTypeContainerDecl:
|
||||
{
|
||||
const char *layout_str = layout_string(node->data.container_decl.layout);
|
||||
const char *container_str = container_string(node->data.container_decl.kind);
|
||||
fprintf(ar->f, "%s {\n", container_str);
|
||||
fprintf(ar->f, "%s%s {\n", layout_str, container_str);
|
||||
ar->indent += ar->indent_size;
|
||||
for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) {
|
||||
AstNode *field_node = node->data.container_decl.fields.at(field_i);
|
||||
assert(field_node->type == NodeTypeStructField);
|
||||
print_indent(ar);
|
||||
print_symbol(ar, field_node->data.struct_field.name);
|
||||
fprintf(ar->f, ": ");
|
||||
render_node_grouped(ar, field_node->data.struct_field.type);
|
||||
if (field_node->data.struct_field.type != nullptr) {
|
||||
fprintf(ar->f, ": ");
|
||||
render_node_grouped(ar, field_node->data.struct_field.type);
|
||||
}
|
||||
fprintf(ar->f, ",\n");
|
||||
}
|
||||
|
||||
@ -989,146 +994,3 @@ void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size) {
|
||||
|
||||
render_node_grouped(&ar, node);
|
||||
}
|
||||
|
||||
static void ast_render_tld_fn(AstRender *ar, Buf *name, TldFn *tld_fn) {
|
||||
FnTableEntry *fn_entry = tld_fn->fn_entry;
|
||||
FnTypeId *fn_type_id = &fn_entry->type_entry->data.fn.fn_type_id;
|
||||
const char *visib_mod_str = visib_mod_string(tld_fn->base.visib_mod);
|
||||
const char *cc_str = calling_convention_string(fn_type_id->cc);
|
||||
fprintf(ar->f, "%s%sfn %s(", visib_mod_str, cc_str, buf_ptr(&fn_entry->symbol_name));
|
||||
for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
|
||||
FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
|
||||
if (i != 0) {
|
||||
fprintf(ar->f, ", ");
|
||||
}
|
||||
if (param_info->is_noalias) {
|
||||
fprintf(ar->f, "noalias ");
|
||||
}
|
||||
Buf *param_name = tld_fn->fn_entry->param_names ? tld_fn->fn_entry->param_names[i] : buf_sprintf("arg%" ZIG_PRI_usize "", i);
|
||||
fprintf(ar->f, "%s: %s", buf_ptr(param_name), buf_ptr(¶m_info->type->name));
|
||||
}
|
||||
if (fn_type_id->return_type->id == TypeTableEntryIdVoid) {
|
||||
fprintf(ar->f, ");\n");
|
||||
} else {
|
||||
fprintf(ar->f, ") -> %s;\n", buf_ptr(&fn_type_id->return_type->name));
|
||||
}
|
||||
}
|
||||
|
||||
static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {
|
||||
VariableTableEntry *var = tld_var->var;
|
||||
const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod);
|
||||
const char *const_or_var = const_or_var_string(var->src_is_const);
|
||||
const char *extern_str = extern_string(var->linkage == VarLinkageExternal);
|
||||
fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(name));
|
||||
|
||||
if (var->value->type->id == TypeTableEntryIdNumLitFloat ||
|
||||
var->value->type->id == TypeTableEntryIdNumLitInt ||
|
||||
var->value->type->id == TypeTableEntryIdMetaType)
|
||||
{
|
||||
// skip type
|
||||
} else {
|
||||
fprintf(ar->f, ": %s", buf_ptr(&var->value->type->name));
|
||||
}
|
||||
|
||||
if (var->value->special == ConstValSpecialRuntime) {
|
||||
fprintf(ar->f, ";\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(ar->f, " = ");
|
||||
|
||||
if (var->value->special == ConstValSpecialStatic &&
|
||||
var->value->type->id == TypeTableEntryIdMetaType)
|
||||
{
|
||||
TypeTableEntry *type_entry = var->value->data.x_type;
|
||||
if (type_entry->id == TypeTableEntryIdStruct) {
|
||||
const char *layout_str = layout_string(type_entry->data.structure.layout);
|
||||
fprintf(ar->f, "%sstruct {\n", layout_str);
|
||||
if (type_entry->data.structure.complete) {
|
||||
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
|
||||
TypeStructField *field = &type_entry->data.structure.fields[i];
|
||||
fprintf(ar->f, " ");
|
||||
print_symbol(ar, field->name);
|
||||
fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name));
|
||||
}
|
||||
}
|
||||
fprintf(ar->f, "}");
|
||||
} else if (type_entry->id == TypeTableEntryIdEnum) {
|
||||
const char *layout_str = layout_string(type_entry->data.enumeration.layout);
|
||||
fprintf(ar->f, "%senum {\n", layout_str);
|
||||
if (type_entry->data.enumeration.complete) {
|
||||
for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) {
|
||||
TypeEnumField *field = &type_entry->data.enumeration.fields[i];
|
||||
fprintf(ar->f, " ");
|
||||
print_symbol(ar, field->name);
|
||||
if (field->type_entry->id == TypeTableEntryIdVoid) {
|
||||
fprintf(ar->f, ",\n");
|
||||
} else {
|
||||
fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(ar->f, "}");
|
||||
} else if (type_entry->id == TypeTableEntryIdUnion) {
|
||||
fprintf(ar->f, "union {");
|
||||
fprintf(ar->f, "TODO");
|
||||
fprintf(ar->f, "}");
|
||||
} else if (type_entry->id == TypeTableEntryIdOpaque) {
|
||||
if (buf_eql_buf(&type_entry->name, name)) {
|
||||
fprintf(ar->f, "@OpaqueType()");
|
||||
} else {
|
||||
fprintf(ar->f, "%s", buf_ptr(&type_entry->name));
|
||||
}
|
||||
} else {
|
||||
fprintf(ar->f, "%s", buf_ptr(&type_entry->name));
|
||||
}
|
||||
} else {
|
||||
Buf buf = BUF_INIT;
|
||||
buf_resize(&buf, 0);
|
||||
render_const_value(ar->codegen, &buf, var->value);
|
||||
fprintf(ar->f, "%s", buf_ptr(&buf));
|
||||
}
|
||||
|
||||
fprintf(ar->f, ";\n");
|
||||
}
|
||||
|
||||
void ast_render_decls(CodeGen *codegen, FILE *f, int indent_size, ImportTableEntry *import) {
|
||||
AstRender ar = {0};
|
||||
ar.codegen = codegen;
|
||||
ar.f = f;
|
||||
ar.indent_size = indent_size;
|
||||
ar.indent = 0;
|
||||
|
||||
auto it = import->decls_scope->decl_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
Tld *tld = entry->value;
|
||||
|
||||
if (tld->name != nullptr && !buf_eql_buf(entry->key, tld->name)) {
|
||||
fprintf(ar.f, "pub const ");
|
||||
print_symbol(&ar, entry->key);
|
||||
fprintf(ar.f, " = %s;\n", buf_ptr(tld->name));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (tld->id) {
|
||||
case TldIdVar:
|
||||
ast_render_tld_var(&ar, entry->key, (TldVar *)tld);
|
||||
break;
|
||||
case TldIdFn:
|
||||
ast_render_tld_fn(&ar, entry->key, (TldFn *)tld);
|
||||
break;
|
||||
case TldIdContainer:
|
||||
fprintf(stdout, "container\n");
|
||||
break;
|
||||
case TldIdCompTime:
|
||||
fprintf(stdout, "comptime\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -19,7 +19,5 @@ void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
|
||||
|
||||
const char *container_string(ContainerKind kind);
|
||||
|
||||
void ast_render_decls(CodeGen *codegen, FILE *f, int indent_size, ImportTableEntry *import);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -165,6 +165,25 @@ void bigint_init_signed(BigInt *dest, int64_t x) {
|
||||
dest->data.digit = ((uint64_t)(-(x + 1))) + 1;
|
||||
}
|
||||
|
||||
void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative) {
|
||||
if (digit_count == 0) {
|
||||
return bigint_init_unsigned(dest, 0);
|
||||
} else if (digit_count == 1) {
|
||||
dest->digit_count = 1;
|
||||
dest->data.digit = digits[0];
|
||||
dest->is_negative = is_negative;
|
||||
bigint_normalize(dest);
|
||||
return;
|
||||
}
|
||||
|
||||
dest->digit_count = digit_count;
|
||||
dest->is_negative = is_negative;
|
||||
dest->data.digits = allocate_nonzero<uint64_t>(digit_count);
|
||||
memcpy(dest->data.digits, digits, sizeof(uint64_t) * digit_count);
|
||||
|
||||
bigint_normalize(dest);
|
||||
}
|
||||
|
||||
void bigint_init_bigint(BigInt *dest, const BigInt *src) {
|
||||
if (src->digit_count == 0) {
|
||||
return bigint_init_unsigned(dest, 0);
|
||||
|
||||
@ -34,6 +34,7 @@ void bigint_init_u128(BigInt *dest, unsigned __int128 x);
|
||||
void bigint_init_signed(BigInt *dest, int64_t x);
|
||||
void bigint_init_bigint(BigInt *dest, const BigInt *src);
|
||||
void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);
|
||||
void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative);
|
||||
|
||||
// panics if number won't fit
|
||||
uint64_t bigint_as_unsigned(const BigInt *bigint);
|
||||
|
||||
@ -55,7 +55,6 @@ void codegen_add_assembly(CodeGen *g, Buf *path);
|
||||
void codegen_add_object(CodeGen *g, Buf *object_path);
|
||||
|
||||
void codegen_parseh(CodeGen *g, Buf *path);
|
||||
void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
77
src/ir.cpp
77
src/ir.cpp
@ -6114,9 +6114,14 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
IrInstruction *return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope);
|
||||
if (return_type == irb->codegen->invalid_instruction)
|
||||
return irb->codegen->invalid_instruction;
|
||||
IrInstruction *return_type;
|
||||
if (node->data.fn_proto.return_type == nullptr) {
|
||||
return_type = ir_build_const_void(irb, parent_scope, node);
|
||||
} else {
|
||||
return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope);
|
||||
if (return_type == irb->codegen->invalid_instruction)
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args);
|
||||
}
|
||||
@ -13358,9 +13363,11 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc
|
||||
if (ira->codegen->verbose) {
|
||||
fprintf(stderr, "\nC imports:\n");
|
||||
fprintf(stderr, "-----------\n");
|
||||
ast_render_decls(ira->codegen, stderr, 4, child_import);
|
||||
ast_render(ira->codegen, stderr, child_import->root, 4);
|
||||
}
|
||||
|
||||
scan_decls(ira->codegen, child_import->decls_scope, child_import->root);
|
||||
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
|
||||
out_val->data.x_import = child_import;
|
||||
return ira->codegen->builtin_types.entry_namespace;
|
||||
@ -15515,65 +15522,3 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableEntry *var, Scope *parent_scope) {
|
||||
FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdInternal);
|
||||
buf_init_from_buf(&fn_entry->symbol_name, fn_name);
|
||||
|
||||
fn_entry->fndef_scope = create_fndef_scope(nullptr, parent_scope, fn_entry);
|
||||
fn_entry->child_scope = &fn_entry->fndef_scope->base;
|
||||
|
||||
assert(var->value->type->id == TypeTableEntryIdMaybe);
|
||||
TypeTableEntry *src_fn_type = var->value->type->data.maybe.child_type;
|
||||
assert(src_fn_type->id == TypeTableEntryIdFn);
|
||||
|
||||
FnTypeId new_fn_type = src_fn_type->data.fn.fn_type_id;
|
||||
new_fn_type.cc = CallingConventionUnspecified;
|
||||
|
||||
fn_entry->type_entry = get_fn_type(codegen, &new_fn_type);
|
||||
|
||||
IrBuilder ir_builder = {0};
|
||||
IrBuilder *irb = &ir_builder;
|
||||
|
||||
irb->codegen = codegen;
|
||||
irb->exec = &fn_entry->ir_executable;
|
||||
|
||||
AstNode *source_node = parent_scope->source_node;
|
||||
|
||||
size_t arg_count = fn_entry->type_entry->data.fn.fn_type_id.param_count;
|
||||
IrInstruction **args = allocate<IrInstruction *>(arg_count);
|
||||
VariableTableEntry **arg_vars = allocate<VariableTableEntry *>(arg_count);
|
||||
|
||||
define_local_param_variables(codegen, fn_entry, arg_vars);
|
||||
Scope *scope = fn_entry->child_scope;
|
||||
|
||||
irb->current_basic_block = ir_build_basic_block(irb, scope, "Entry");
|
||||
// Entry block gets a reference because we enter it to begin.
|
||||
ir_ref_bb(irb->current_basic_block);
|
||||
|
||||
IrInstruction *maybe_fn_ptr = ir_build_var_ptr(irb, scope, source_node, var, true, false);
|
||||
IrInstruction *unwrapped_fn_ptr = ir_build_unwrap_maybe(irb, scope, source_node, maybe_fn_ptr, true);
|
||||
IrInstruction *fn_ref_instruction = ir_build_load_ptr(irb, scope, source_node, unwrapped_fn_ptr);
|
||||
|
||||
for (size_t i = 0; i < arg_count; i += 1) {
|
||||
IrInstruction *var_ptr_instruction = ir_build_var_ptr(irb, scope, source_node, arg_vars[i], true, false);
|
||||
args[i] = ir_build_load_ptr(irb, scope, source_node, var_ptr_instruction);
|
||||
}
|
||||
|
||||
IrInstruction *call_instruction = ir_build_call(irb, scope, source_node, nullptr, fn_ref_instruction,
|
||||
arg_count, args, false, false);
|
||||
ir_build_return(irb, scope, source_node, call_instruction);
|
||||
|
||||
if (codegen->verbose) {
|
||||
fprintf(stderr, "{\n");
|
||||
ir_print(codegen, stderr, &fn_entry->ir_executable, 4);
|
||||
fprintf(stderr, "}\n");
|
||||
}
|
||||
|
||||
analyze_fn_ir(codegen, fn_entry, nullptr);
|
||||
|
||||
codegen->fn_defs.append(fn_entry);
|
||||
|
||||
return fn_entry;
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +24,4 @@ TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutabl
|
||||
bool ir_has_side_effects(IrInstruction *instruction);
|
||||
ConstExprValue *const_ptr_pointee(CodeGen *codegen, ConstExprValue *const_val);
|
||||
|
||||
FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableEntry *var, Scope *parent_scope);
|
||||
|
||||
#endif
|
||||
|
||||
@ -670,7 +670,7 @@ int main(int argc, char **argv) {
|
||||
return EXIT_SUCCESS;
|
||||
} else if (cmd == CmdParseH) {
|
||||
codegen_parseh(g, in_file_buf);
|
||||
ast_render_decls(g, stdout, 4, g->root_import);
|
||||
ast_render(g, stdout, g->root_import->root, 4);
|
||||
if (timing_info)
|
||||
codegen_print_timing_report(g, stdout);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
1629
src/parseh.cpp
1629
src/parseh.cpp
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,16 @@ pub fn addCases(cases: &tests.ParseHContext) {
|
||||
\\pub extern fn foo() -> noreturn;
|
||||
);
|
||||
|
||||
cases.add("simple function",
|
||||
\\int abs(int a) {
|
||||
\\ return a < 0 ? -a : a;
|
||||
\\}
|
||||
,
|
||||
\\export fn abs(a: c_int) -> c_int {
|
||||
\\ return if (a < 0) -a else a;
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.add("enums",
|
||||
\\enum Foo {
|
||||
\\ FooA,
|
||||
@ -34,13 +44,13 @@ pub fn addCases(cases: &tests.ParseHContext) {
|
||||
\\ @"1",
|
||||
\\};
|
||||
,
|
||||
\\pub const FooA = 0;
|
||||
\\pub const FooA = Foo.A;
|
||||
,
|
||||
\\pub const FooB = 1;
|
||||
\\pub const FooB = Foo.B;
|
||||
,
|
||||
\\pub const Foo1 = 2;
|
||||
\\pub const Foo1 = Foo.1;
|
||||
,
|
||||
\\pub const Foo = enum_Foo
|
||||
\\pub const Foo = enum_Foo;
|
||||
);
|
||||
|
||||
cases.add("restrict -> noalias",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user