Commit e1d5da20a5
Changed files (11)
src/all_types.hpp
@@ -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 {
src/ast_render.cpp
@@ -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;
- }
- }
-}
-
-
src/ast_render.hpp
@@ -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
src/bigint.cpp
@@ -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);
src/bigint.hpp
@@ -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);
src/codegen.hpp
@@ -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
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;
-}
-
src/ir.hpp
@@ -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
src/main.cpp
@@ -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;
src/parseh.cpp
@@ -15,6 +15,7 @@
#include "parseh.hpp"
#include "parser.hpp"
+
#include <clang/Frontend/ASTUnit.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/AST/Expr.h>
@@ -28,14 +29,9 @@ struct MacroSymbol {
Buf *value;
};
-struct GlobalValue {
- TypeTableEntry *type;
- bool is_const;
-};
-
struct Alias {
Buf *name;
- Tld *tld;
+ AstNode *node;
};
struct Context {
@@ -43,30 +39,26 @@ struct Context {
ZigList<ErrorMsg *> *errors;
bool warnings_on;
VisibMod visib_mod;
-
- HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_type_table;
- HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_type_table2;
-
- HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> struct_type_table;
- HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> enum_type_table;
- HashMap<const void *, TypeTableEntry *, ptr_hash, ptr_eq> decl_table;
- HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> macro_table;
+ AstNode *root;
+ HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_type_table;
+ HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> struct_type_table;
+ HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> enum_type_table;
+ HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
+ HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
SourceManager *source_manager;
ZigList<Alias> aliases;
ZigList<MacroSymbol> macro_symbols;
AstNode *source_node;
- uint32_t next_anon_index;
CodeGen *codegen;
ASTContext *ctx;
};
-static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl,
- HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table);
-
-static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl);
-static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_decl);
-static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
+static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);
+static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
+static AstNode * trans_qual_type_with_table(Context *c, QualType qt, const SourceLocation &source_loc,
+ HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> *type_table);
+static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
__attribute__ ((format (printf, 3, 4)))
@@ -93,522 +85,226 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma
fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
}
-static uint32_t get_next_anon_index(Context *c) {
- uint32_t result = c->next_anon_index;
- c->next_anon_index += 1;
- return result;
-}
-
-static void add_global_alias(Context *c, Buf *name, Tld *tld) {
- c->import->decls_scope->decl_table.put(name, tld);
-}
-
-static void add_global_weak_alias(Context *c, Buf *name, Tld *tld) {
+static void add_global_weak_alias(Context *c, Buf *name, AstNode *node) {
Alias *alias = c->aliases.add_one();
alias->name = name;
- alias->tld = tld;
+ alias->node = node;
}
-static void add_global(Context *c, Tld *tld) {
- return add_global_alias(c, tld->name, tld);
+static AstNode * trans_create_node(Context *c, NodeType id) {
+ AstNode *node = allocate<AstNode>(1);
+ node->type = id;
+ node->owner = c->import;
+ // TODO line/column. mapping to C file??
+ return node;
}
-static Tld *get_global(Context *c, Buf *name) {
- {
- auto entry = c->import->decls_scope->decl_table.maybe_get(name);
- if (entry)
- return entry->value;
- }
- {
- auto entry = c->macro_table.maybe_get(name);
- if (entry)
- return entry->value;
- }
- return nullptr;
+static AstNode *trans_create_node_float_lit(Context *c, double value) {
+ AstNode *node = trans_create_node(c, NodeTypeFloatLiteral);
+ node->data.float_literal.bigfloat = allocate<BigFloat>(1);
+ bigfloat_init_64(node->data.float_literal.bigfloat, value);
+ 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();
+static AstNode *trans_create_node_symbol(Context *c, Buf *name) {
+ AstNode *node = trans_create_node(c, NodeTypeSymbol);
+ node->data.symbol_expr.symbol = name;
+ return node;
}
-static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) {
- init_tld(tld, id, name, c->visib_mod, c->source_node, &c->import->decls_scope->base);
- tld->resolution = TldResolutionOk;
- tld->import = c->import;
+static AstNode *trans_create_node_symbol_str(Context *c, const char *name) {
+ return trans_create_node_symbol(c, buf_create_from_str(name));
}
-static Tld *create_inline_fn_tld(Context *c, Buf *fn_name, TldVar *tld_var) {
- TldFn *tld_fn = allocate<TldFn>(1);
- parseh_init_tld(c, &tld_fn->base, TldIdFn, fn_name);
- tld_fn->fn_entry = ir_create_inline_fn(c->codegen, fn_name, tld_var->var, &c->import->decls_scope->base);
- return &tld_fn->base;
+static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) {
+ AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
+ node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name);
+ node->data.fn_call_expr.is_builtin = true;
+ return node;
}
-static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_value, bool is_const) {
- auto entry = c->import->decls_scope->decl_table.maybe_get(name);
- if (entry) {
- Tld *existing_tld = entry->value;
- assert(existing_tld->id == TldIdVar);
- return (TldVar *)existing_tld;
- }
- TldVar *tld_var = allocate<TldVar>(1);
- parseh_init_tld(c, &tld_var->base, TldIdVar, name);
- tld_var->var = add_variable(c->codegen, c->source_node, &c->import->decls_scope->base,
- name, is_const, var_value, &tld_var->base);
- c->codegen->global_vars.append(tld_var);
- return tld_var;
+static AstNode *trans_create_node_builtin_fn_call_str(Context *c, const char *name) {
+ return trans_create_node_builtin_fn_call(c, buf_create_from_str(name));
}
-static Tld *create_global_str_lit_var(Context *c, Buf *name, Buf *value) {
- TldVar *tld_var = create_global_var(c, name, create_const_c_str_lit(c->codegen, value), true);
- return &tld_var->base;
+static AstNode *trans_create_node_opaque(Context *c) {
+ return trans_create_node_builtin_fn_call_str(c, "opaque");
}
-static Tld *create_global_num_lit_unsigned_negative_type(Context *c, Buf *name, uint64_t x, bool negative, TypeTableEntry *type_entry) {
- ConstExprValue *var_val = create_const_unsigned_negative(type_entry, x, negative);
- TldVar *tld_var = create_global_var(c, name, var_val, true);
- return &tld_var->base;
+static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) {
+ AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr);
+ node->data.field_access_expr.struct_expr = container;
+ node->data.field_access_expr.field_name = field_name;
+ return node;
}
-static Tld *create_global_num_lit_unsigned_negative(Context *c, Buf *name, uint64_t x, bool negative) {
- return create_global_num_lit_unsigned_negative_type(c, name, x, negative, c->codegen->builtin_types.entry_num_lit_int);
+static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) {
+ AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
+ node->data.prefix_op_expr.prefix_op = op;
+ node->data.prefix_op_expr.primary_expr = child_node;
+ return node;
}
-static Tld *create_global_num_lit_float(Context *c, Buf *name, double value) {
- ConstExprValue *var_val = create_const_float(c->codegen->builtin_types.entry_num_lit_float, value);
- TldVar *tld_var = create_global_var(c, name, var_val, true);
- return &tld_var->base;
+static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) {
+ AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr);
+ node->data.addr_of_expr.is_const = is_const;
+ node->data.addr_of_expr.is_volatile = is_volatile;
+ node->data.addr_of_expr.op_expr = child_node;
+ return node;
}
-static ConstExprValue *create_const_int_ap(Context *c, TypeTableEntry *type, const Decl *source_decl,
- const llvm::APSInt &aps_int)
-{
- if (aps_int.isSigned()) {
- if (aps_int > INT64_MAX || aps_int < INT64_MIN) {
- emit_warning(c, source_decl->getLocation(), "integer overflow\n");
- return nullptr;
- } else {
- return create_const_signed(type, aps_int.getExtValue());
- }
- } else {
- if (aps_int > INT64_MAX) {
- emit_warning(c, source_decl->getLocation(), "integer overflow\n");
- return nullptr;
- } else {
- return create_const_unsigned_negative(type, aps_int.getExtValue(), false);
- }
- }
+static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {
+ AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
+ node->data.string_literal.buf = buf;
+ node->data.string_literal.c = true;
+ return node;
}
-static Tld *create_global_num_lit_ap(Context *c, const Decl *source_decl, Buf *name,
- const llvm::APSInt &aps_int)
-{
- ConstExprValue *const_value = create_const_int_ap(c, c->codegen->builtin_types.entry_num_lit_int,
- source_decl, aps_int);
- if (!const_value)
- return nullptr;
- TldVar *tld_var = create_global_var(c, name, const_value, true);
- return &tld_var->base;
+static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) {
+ AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
+ node->data.int_literal.bigint = allocate<BigInt>(1);
+ bigint_init_data(node->data.int_literal.bigint, &x, 1, is_negative);
+ return node;
}
-
-static Tld *add_const_type(Context *c, Buf *name, TypeTableEntry *type_entry) {
- ConstExprValue *var_value = create_const_type(c->codegen, type_entry);
- TldVar *tld_var = create_global_var(c, name, var_value, true);
- add_global(c, &tld_var->base);
-
- c->global_type_table.put(name, type_entry);
- return &tld_var->base;
+static AstNode *trans_create_node_unsigned(Context *c, uint64_t x) {
+ return trans_create_node_unsigned_negative(c, x, false);
}
-static Tld *add_container_tld(Context *c, TypeTableEntry *type_entry) {
- return add_const_type(c, &type_entry->name, type_entry);
+static AstNode *trans_create_node_cast(Context *c, AstNode *dest, AstNode *src) {
+ AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
+ node->data.fn_call_expr.fn_ref_expr = dest;
+ node->data.fn_call_expr.params.resize(1);
+ node->data.fn_call_expr.params.items[0] = src;
+ return node;
}
-static bool is_c_void_type(Context *c, TypeTableEntry *type_entry) {
- return (type_entry == c->codegen->builtin_types.entry_c_void);
+static AstNode *trans_create_node_unsigned_negative_type(Context *c, uint64_t x, bool is_negative,
+ const char *type_name)
+{
+ AstNode *lit_node = trans_create_node_unsigned_negative(c, x, is_negative);
+ return trans_create_node_cast(c, trans_create_node_symbol_str(c, type_name), lit_node);
}
-static bool qual_type_child_is_fn_proto(const QualType &qt) {
- if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
- const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());
- if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
- return true;
- }
- } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {
- const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr());
- return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
- }
- return false;
+static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, AstNode *child_type_node) {
+ AstNode *node = trans_create_node(c, NodeTypeArrayType);
+ node->data.array_type.size = size_node;
+ node->data.array_type.child_type = child_type_node;
+ return node;
}
-static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const Decl *decl,
- HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table)
+static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
+ AstNode *init_node)
{
- switch (ty->getTypeClass()) {
- case Type::Builtin:
- {
- const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
- switch (builtin_ty->getKind()) {
- case BuiltinType::Void:
- return c->codegen->builtin_types.entry_c_void;
- case BuiltinType::Bool:
- return c->codegen->builtin_types.entry_bool;
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- return c->codegen->builtin_types.entry_u8;
- case BuiltinType::SChar:
- return c->codegen->builtin_types.entry_i8;
- case BuiltinType::UShort:
- return get_c_int_type(c->codegen, CIntTypeUShort);
- case BuiltinType::UInt:
- return get_c_int_type(c->codegen, CIntTypeUInt);
- case BuiltinType::ULong:
- return get_c_int_type(c->codegen, CIntTypeULong);
- case BuiltinType::ULongLong:
- return get_c_int_type(c->codegen, CIntTypeULongLong);
- case BuiltinType::Short:
- return get_c_int_type(c->codegen, CIntTypeShort);
- case BuiltinType::Int:
- return get_c_int_type(c->codegen, CIntTypeInt);
- case BuiltinType::Long:
- return get_c_int_type(c->codegen, CIntTypeLong);
- case BuiltinType::LongLong:
- return get_c_int_type(c->codegen, CIntTypeLongLong);
- case BuiltinType::UInt128:
- return c->codegen->builtin_types.entry_u128;
- case BuiltinType::Int128:
- return c->codegen->builtin_types.entry_i128;
- case BuiltinType::Float:
- return c->codegen->builtin_types.entry_f32;
- case BuiltinType::Double:
- return c->codegen->builtin_types.entry_f64;
- case BuiltinType::Float128:
- return c->codegen->builtin_types.entry_f128;
- case BuiltinType::LongDouble:
- return c->codegen->builtin_types.entry_c_longdouble;
- case BuiltinType::WChar_U:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::WChar_S:
- case BuiltinType::Half:
- case BuiltinType::NullPtr:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- case BuiltinType::OMPArraySection:
- case BuiltinType::Dependent:
- case BuiltinType::Overload:
- case BuiltinType::BoundMember:
- case BuiltinType::PseudoObject:
- case BuiltinType::UnknownAny:
- case BuiltinType::BuiltinFn:
- case BuiltinType::ARCUnbridgedCast:
+ AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration);
+ node->data.variable_declaration.visib_mod = c->visib_mod;
+ node->data.variable_declaration.symbol = var_name;
+ node->data.variable_declaration.is_const = is_const;
+ node->data.variable_declaration.type = type_node;
+ node->data.variable_declaration.expr = init_node;
+ return node;
+}
- case BuiltinType::OCLImage1dRO:
- case BuiltinType::OCLImage1dArrayRO:
- case BuiltinType::OCLImage1dBufferRO:
- case BuiltinType::OCLImage2dRO:
- case BuiltinType::OCLImage2dArrayRO:
- case BuiltinType::OCLImage2dDepthRO:
- case BuiltinType::OCLImage2dArrayDepthRO:
- case BuiltinType::OCLImage2dMSAARO:
- case BuiltinType::OCLImage2dArrayMSAARO:
- case BuiltinType::OCLImage2dMSAADepthRO:
- case BuiltinType::OCLImage2dArrayMSAADepthRO:
- case BuiltinType::OCLImage3dRO:
- case BuiltinType::OCLImage1dWO:
- case BuiltinType::OCLImage1dArrayWO:
- case BuiltinType::OCLImage1dBufferWO:
- case BuiltinType::OCLImage2dWO:
- case BuiltinType::OCLImage2dArrayWO:
- case BuiltinType::OCLImage2dDepthWO:
- case BuiltinType::OCLImage2dArrayDepthWO:
- case BuiltinType::OCLImage2dMSAAWO:
- case BuiltinType::OCLImage2dArrayMSAAWO:
- case BuiltinType::OCLImage2dMSAADepthWO:
- case BuiltinType::OCLImage2dArrayMSAADepthWO:
- case BuiltinType::OCLImage3dWO:
- case BuiltinType::OCLImage1dRW:
- case BuiltinType::OCLImage1dArrayRW:
- case BuiltinType::OCLImage1dBufferRW:
- case BuiltinType::OCLImage2dRW:
- case BuiltinType::OCLImage2dArrayRW:
- case BuiltinType::OCLImage2dDepthRW:
- case BuiltinType::OCLImage2dArrayDepthRW:
- case BuiltinType::OCLImage2dMSAARW:
- case BuiltinType::OCLImage2dArrayMSAARW:
- case BuiltinType::OCLImage2dMSAADepthRW:
- case BuiltinType::OCLImage2dArrayMSAADepthRW:
- case BuiltinType::OCLImage3dRW:
- case BuiltinType::OCLSampler:
- case BuiltinType::OCLEvent:
- case BuiltinType::OCLClkEvent:
- case BuiltinType::OCLQueue:
- case BuiltinType::OCLReserveID:
- emit_warning(c, decl->getLocation(), "missed a builtin type");
- return c->codegen->builtin_types.entry_invalid;
- }
- break;
- }
- case Type::Pointer:
- {
- const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
- QualType child_qt = pointer_ty->getPointeeType();
- TypeTableEntry *child_type = resolve_qual_type(c, child_qt, decl);
- if (type_is_invalid(child_type)) {
- emit_warning(c, decl->getLocation(), "pointer to unresolved type");
- return c->codegen->builtin_types.entry_invalid;
- }
- if (qual_type_child_is_fn_proto(child_qt)) {
- return get_maybe_type(c->codegen, child_type);
- }
- bool is_const = child_qt.isConstQualified();
+static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) {
+ AstNode *fn_def = trans_create_node(c, NodeTypeFnDef);
+ AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
+ fn_proto->data.fn_proto.visib_mod = c->visib_mod;;
+ fn_proto->data.fn_proto.name = fn_name;
+ fn_proto->data.fn_proto.is_inline = true;
+ fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias?
- TypeTableEntry *non_null_pointer_type = get_pointer_to_type(c->codegen, child_type, is_const);
- return get_maybe_type(c->codegen, non_null_pointer_type);
- }
- case Type::Typedef:
- {
- const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
- const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
- Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
- if (buf_eql_str(type_name, "uint8_t")) {
- return c->codegen->builtin_types.entry_u8;
- } else if (buf_eql_str(type_name, "int8_t")) {
- return c->codegen->builtin_types.entry_i8;
- } else if (buf_eql_str(type_name, "uint16_t")) {
- return c->codegen->builtin_types.entry_u16;
- } else if (buf_eql_str(type_name, "int16_t")) {
- return c->codegen->builtin_types.entry_i16;
- } else if (buf_eql_str(type_name, "uint32_t")) {
- return c->codegen->builtin_types.entry_u32;
- } else if (buf_eql_str(type_name, "int32_t")) {
- return c->codegen->builtin_types.entry_i32;
- } else if (buf_eql_str(type_name, "uint64_t")) {
- return c->codegen->builtin_types.entry_u64;
- } else if (buf_eql_str(type_name, "int64_t")) {
- return c->codegen->builtin_types.entry_i64;
- } else if (buf_eql_str(type_name, "intptr_t")) {
- return c->codegen->builtin_types.entry_isize;
- } else if (buf_eql_str(type_name, "uintptr_t")) {
- return c->codegen->builtin_types.entry_usize;
- } else {
- auto entry = type_table->maybe_get(type_name);
- if (entry) {
- if (type_is_invalid(entry->value)) {
- return c->codegen->builtin_types.entry_invalid;
- } else {
- return entry->value;
- }
- } else {
- return c->codegen->builtin_types.entry_invalid;
- }
- }
- }
- case Type::Elaborated:
- {
- const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
- switch (elaborated_ty->getKeyword()) {
- case ETK_Struct:
- return resolve_qual_type_with_table(c, elaborated_ty->getNamedType(),
- decl, &c->struct_type_table);
- case ETK_Enum:
- return resolve_qual_type_with_table(c, elaborated_ty->getNamedType(),
- decl, &c->enum_type_table);
- case ETK_Interface:
- case ETK_Union:
- case ETK_Class:
- case ETK_Typename:
- case ETK_None:
- emit_warning(c, decl->getLocation(), "unsupported elaborated type");
- return c->codegen->builtin_types.entry_invalid;
- }
- }
- case Type::FunctionProto:
- {
- const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);
+ fn_def->data.fn_def.fn_proto = fn_proto;
+ fn_proto->data.fn_proto.fn_def_node = fn_def;
- switch (fn_proto_ty->getCallConv()) {
- case CC_C: // __attribute__((cdecl))
- break;
- case CC_X86StdCall: // __attribute__((stdcall))
- emit_warning(c, decl->getLocation(), "function type has x86 stdcall calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_X86FastCall: // __attribute__((fastcall))
- emit_warning(c, decl->getLocation(), "function type has x86 fastcall calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_X86ThisCall: // __attribute__((thiscall))
- emit_warning(c, decl->getLocation(), "function type has x86 thiscall calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_X86VectorCall: // __attribute__((vectorcall))
- emit_warning(c, decl->getLocation(), "function type has x86 vectorcall calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_X86Pascal: // __attribute__((pascal))
- emit_warning(c, decl->getLocation(), "function type has x86 pascal calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_Win64: // __attribute__((ms_abi))
- emit_warning(c, decl->getLocation(), "function type has win64 calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_X86_64SysV: // __attribute__((sysv_abi))
- emit_warning(c, decl->getLocation(), "function type has x86 64sysv calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_X86RegCall:
- emit_warning(c, decl->getLocation(), "function type has x86 reg calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_AAPCS: // __attribute__((pcs("aapcs")))
- emit_warning(c, decl->getLocation(), "function type has aapcs calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
- emit_warning(c, decl->getLocation(), "function type has aapcs-vfp calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
- emit_warning(c, decl->getLocation(), "function type has intel_ocl_bicc calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_SpirFunction: // default for OpenCL functions on SPIR target
- emit_warning(c, decl->getLocation(), "function type has SPIR function calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_OpenCLKernel:
- emit_warning(c, decl->getLocation(), "function type has OpenCLKernel calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_Swift:
- emit_warning(c, decl->getLocation(), "function type has Swift calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_PreserveMost:
- emit_warning(c, decl->getLocation(), "function type has PreserveMost calling convention");
- return c->codegen->builtin_types.entry_invalid;
- case CC_PreserveAll:
- emit_warning(c, decl->getLocation(), "function type has PreserveAll calling convention");
- return c->codegen->builtin_types.entry_invalid;
- }
+ AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, trans_create_node_symbol(c, var_name));
+ AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr);
+ fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node;
- FnTypeId fn_type_id = {0};
- fn_type_id.cc = CallingConventionC;
- fn_type_id.is_var_args = fn_proto_ty->isVariadic();
- fn_type_id.param_count = fn_proto_ty->getNumParams();
+ for (size_t i = 0; i < src_proto_node->data.fn_proto.params.length; i += 1) {
+ AstNode *src_param_node = src_proto_node->data.fn_proto.params.at(i);
+ Buf *param_name = src_param_node->data.param_decl.name;
+ AstNode *dest_param_node = trans_create_node(c, NodeTypeParamDecl);
+ dest_param_node->data.param_decl.name = param_name;
+ dest_param_node->data.param_decl.type = src_param_node->data.param_decl.type;
+ dest_param_node->data.param_decl.is_noalias = src_param_node->data.param_decl.is_noalias;
+ fn_proto->data.fn_proto.params.append(dest_param_node);
- if (fn_proto_ty->getNoReturnAttr()) {
- fn_type_id.return_type = c->codegen->builtin_types.entry_unreachable;
- } else {
- fn_type_id.return_type = resolve_qual_type(c, fn_proto_ty->getReturnType(), decl);
- if (type_is_invalid(fn_type_id.return_type)) {
- emit_warning(c, decl->getLocation(), "unresolved function proto return type");
- return c->codegen->builtin_types.entry_invalid;
- }
- // convert c_void to actual void (only for return type)
- if (is_c_void_type(c, fn_type_id.return_type)) {
- fn_type_id.return_type = c->codegen->builtin_types.entry_void;
- }
- }
+ fn_call_node->data.fn_call_expr.params.append(trans_create_node_symbol(c, param_name));
- fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count);
- for (size_t i = 0; i < fn_type_id.param_count; i += 1) {
- QualType qt = fn_proto_ty->getParamType(i);
- TypeTableEntry *param_type = resolve_qual_type(c, qt, decl);
+ }
- if (type_is_invalid(param_type)) {
- emit_warning(c, decl->getLocation(), "unresolved function proto parameter type");
- return c->codegen->builtin_types.entry_invalid;
- }
+ AstNode *block = trans_create_node(c, NodeTypeBlock);
+ block->data.block.statements.resize(1);
+ block->data.block.statements.items[0] = fn_call_node;
- FnTypeParamInfo *param_info = &fn_type_id.param_info[i];
- param_info->type = param_type;
- param_info->is_noalias = qt.isRestrictQualified();
- }
+ fn_def->data.fn_def.body = block;
+ return fn_def;
+}
- return get_fn_type(c->codegen, &fn_type_id);
- }
- case Type::Record:
- {
- const RecordType *record_ty = static_cast<const RecordType*>(ty);
- return resolve_record_decl(c, record_ty->getDecl());
- }
- case Type::Enum:
- {
- const EnumType *enum_ty = static_cast<const EnumType*>(ty);
- return resolve_enum_decl(c, enum_ty->getDecl());
+static AstNode *get_global(Context *c, Buf *name) {
+ for (size_t i = 0; i < c->root->data.root.top_level_decls.length; i += 1) {
+ AstNode *decl_node = c->root->data.root.top_level_decls.items[i];
+ if (decl_node->type == NodeTypeVariableDeclaration) {
+ if (buf_eql_buf(decl_node->data.variable_declaration.symbol, name)) {
+ return decl_node;
}
- case Type::ConstantArray:
- {
- const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);
- TypeTableEntry *child_type = resolve_qual_type(c, const_arr_ty->getElementType(), decl);
- if (child_type->id == TypeTableEntryIdInvalid) {
- emit_warning(c, decl->getLocation(), "unresolved array element type");
- return child_type;
- }
- uint64_t size = const_arr_ty->getSize().getLimitedValue();
- return get_array_type(c->codegen, child_type, size);
+ } else if (decl_node->type == NodeTypeFnDef) {
+ if (buf_eql_buf(decl_node->data.fn_def.fn_proto->data.fn_proto.name, name)) {
+ return decl_node;
}
- case Type::Paren:
- {
- const ParenType *paren_ty = static_cast<const ParenType *>(ty);
- return resolve_qual_type(c, paren_ty->getInnerType(), decl);
+ } else if (decl_node->type == NodeTypeFnProto) {
+ if (buf_eql_buf(decl_node->data.fn_proto.name, name)) {
+ return decl_node;
}
- case Type::Decayed:
- {
- const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty);
- return resolve_qual_type(c, decayed_ty->getDecayedType(), decl);
- }
- case Type::Attributed:
- {
- const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty);
- return resolve_qual_type(c, attributed_ty->getEquivalentType(), decl);
- }
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::IncompleteArray:
- case Type::VariableArray:
- case Type::DependentSizedArray:
- case Type::DependentSizedExtVector:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionNoProto:
- case Type::UnresolvedUsing:
- case Type::Adjusted:
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::UnaryTransform:
- case Type::TemplateTypeParm:
- case Type::SubstTemplateTypeParm:
- case Type::SubstTemplateTypeParmPack:
- case Type::TemplateSpecialization:
- case Type::Auto:
- case Type::InjectedClassName:
- case Type::DependentName:
- case Type::DependentTemplateSpecialization:
- case Type::PackExpansion:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- case Type::Complex:
- case Type::ObjCObjectPointer:
- case Type::Atomic:
- case Type::Pipe:
- case Type::ObjCTypeParam:
- case Type::DeducedTemplateSpecialization:
- emit_warning(c, decl->getLocation(), "missed a '%s' type", ty->getTypeClassName());
- return c->codegen->builtin_types.entry_invalid;
+ }
}
- zig_unreachable();
+ {
+ auto entry = c->macro_table.maybe_get(name);
+ if (entry)
+ return entry->value;
+ }
+ return nullptr;
+}
+
+static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) {
+ bool is_const = true;
+ AstNode *type_node = nullptr;
+ AstNode *node = trans_create_node_var_decl(c, is_const, var_name, type_node, value_node);
+ c->root->data.root.top_level_decls.append(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();
}
-static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl,
- HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table)
-{
- return resolve_type_with_table(c, qt.getTypePtr(), decl, type_table);
+static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
+ AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
+ node->data.int_literal.bigint = allocate<BigInt>(1);
+ bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), aps_int.isNegative());
+ return node;
+
}
-static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl) {
- return resolve_qual_type_with_table(c, qt, decl, &c->global_type_table);
+static bool is_c_void_type(AstNode *node) {
+ return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
}
-#include "ast_render.hpp"
+static bool qual_type_child_is_fn_proto(const QualType &qt) {
+ if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
+ const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());
+ if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
+ return true;
+ }
+ } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {
+ const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr());
+ return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
+ }
+ return false;
+}
static bool c_is_signed_integer(Context *c, QualType qt) {
const Type *c_type = qt.getTypePtr();
@@ -668,19 +364,12 @@ static bool c_is_float(Context *c, QualType qt) {
}
static AstNode * trans_stmt(Context *c, AstNode *block, Stmt *stmt);
-static AstNode * trans_create_node(Context *c, NodeType id);
static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
static AstNode * trans_expr(Context *c, AstNode *block, Expr *expr) {
return trans_stmt(c, block, expr);
}
-static AstNode *trans_create_symbol_node(Context *c, const char * name) {
- AstNode *node = trans_create_node(c, NodeTypeSymbol);
- node->data.symbol_expr.symbol = buf_create_from_str(name);
- return node;
-}
-
static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLocation &source_loc,
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> *type_table)
{
@@ -690,43 +379,43 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo
const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
switch (builtin_ty->getKind()) {
case BuiltinType::Void:
- return trans_create_symbol_node(c, "c_void");
+ return trans_create_node_symbol_str(c, "c_void");
case BuiltinType::Bool:
- return trans_create_symbol_node(c, "bool");
+ return trans_create_node_symbol_str(c, "bool");
case BuiltinType::Char_U:
case BuiltinType::UChar:
case BuiltinType::Char_S:
- return trans_create_symbol_node(c, "u8");
+ return trans_create_node_symbol_str(c, "u8");
case BuiltinType::SChar:
- return trans_create_symbol_node(c, "i8");
+ return trans_create_node_symbol_str(c, "i8");
case BuiltinType::UShort:
- return trans_create_symbol_node(c, "c_ushort");
+ return trans_create_node_symbol_str(c, "c_ushort");
case BuiltinType::UInt:
- return trans_create_symbol_node(c, "c_uint");
+ return trans_create_node_symbol_str(c, "c_uint");
case BuiltinType::ULong:
- return trans_create_symbol_node(c, "c_ulong");
+ return trans_create_node_symbol_str(c, "c_ulong");
case BuiltinType::ULongLong:
- return trans_create_symbol_node(c, "c_ulonglong");
+ return trans_create_node_symbol_str(c, "c_ulonglong");
case BuiltinType::Short:
- return trans_create_symbol_node(c, "c_short");
+ return trans_create_node_symbol_str(c, "c_short");
case BuiltinType::Int:
- return trans_create_symbol_node(c, "c_int");
+ return trans_create_node_symbol_str(c, "c_int");
case BuiltinType::Long:
- return trans_create_symbol_node(c, "c_long");
+ return trans_create_node_symbol_str(c, "c_long");
case BuiltinType::LongLong:
- return trans_create_symbol_node(c, "c_longlong");
+ return trans_create_node_symbol_str(c, "c_longlong");
case BuiltinType::UInt128:
- return trans_create_symbol_node(c, "u128");
+ return trans_create_node_symbol_str(c, "u128");
case BuiltinType::Int128:
- return trans_create_symbol_node(c, "i128");
+ return trans_create_node_symbol_str(c, "i128");
case BuiltinType::Float:
- return trans_create_symbol_node(c, "f32");
+ return trans_create_node_symbol_str(c, "f32");
case BuiltinType::Double:
- return trans_create_symbol_node(c, "f64");
+ return trans_create_node_symbol_str(c, "f64");
case BuiltinType::Float128:
- return trans_create_symbol_node(c, "f128");
+ return trans_create_node_symbol_str(c, "f128");
case BuiltinType::LongDouble:
- return trans_create_symbol_node(c, "c_longdouble");
+ return trans_create_node_symbol_str(c, "c_longdouble");
case BuiltinType::WChar_U:
case BuiltinType::Char16:
case BuiltinType::Char32:
@@ -786,7 +475,8 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
case BuiltinType::OCLReserveID:
- zig_panic("TODO more c type");
+ emit_warning(c, source_loc, "unsupported builtin type");
+ return nullptr;
}
break;
}
@@ -795,40 +485,218 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo
const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
QualType child_qt = pointer_ty->getPointeeType();
AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
- if (child_node == nullptr) return nullptr;
+ if (child_node == nullptr) {
+ emit_warning(c, source_loc, "pointer to unsupported type");
+ return nullptr;
+ }
if (qual_type_child_is_fn_proto(child_qt)) {
- zig_panic("TODO pointer to function proto");
+ return trans_create_node_prefix_op(c, PrefixOpMaybe, child_node);
}
- AstNode *pointer_node = trans_create_node(c, NodeTypeAddrOfExpr);
- pointer_node->data.addr_of_expr.is_const = child_qt.isConstQualified();
- pointer_node->data.addr_of_expr.is_volatile = child_qt.isVolatileQualified();
- pointer_node->data.addr_of_expr.op_expr = child_node;
-
- AstNode *maybe_node = trans_create_node(c, NodeTypePrefixOpExpr);
- maybe_node->data.prefix_op_expr.prefix_op = PrefixOpMaybe;
- maybe_node->data.prefix_op_expr.primary_expr = pointer_node;
- return maybe_node;
+ AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(),
+ child_qt.isVolatileQualified(), child_node);
+ return trans_create_node_prefix_op(c, PrefixOpMaybe, pointer_node);
}
case Type::Typedef:
- zig_panic("TODO typedef");
+ {
+ const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
+ const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
+ if (buf_eql_str(type_name, "uint8_t")) {
+ return trans_create_node_symbol_str(c, "u8");
+ } else if (buf_eql_str(type_name, "int8_t")) {
+ return trans_create_node_symbol_str(c, "i8");
+ } else if (buf_eql_str(type_name, "uint16_t")) {
+ return trans_create_node_symbol_str(c, "u16");
+ } else if (buf_eql_str(type_name, "int16_t")) {
+ return trans_create_node_symbol_str(c, "i16");
+ } else if (buf_eql_str(type_name, "uint32_t")) {
+ return trans_create_node_symbol_str(c, "u32");
+ } else if (buf_eql_str(type_name, "int32_t")) {
+ return trans_create_node_symbol_str(c, "i32");
+ } else if (buf_eql_str(type_name, "uint64_t")) {
+ return trans_create_node_symbol_str(c, "u64");
+ } else if (buf_eql_str(type_name, "int64_t")) {
+ return trans_create_node_symbol_str(c, "i64");
+ } else if (buf_eql_str(type_name, "intptr_t")) {
+ return trans_create_node_symbol_str(c, "isize");
+ } else if (buf_eql_str(type_name, "uintptr_t")) {
+ return trans_create_node_symbol_str(c, "usize");
+ } else {
+ auto entry = type_table->maybe_get(type_name);
+ if (entry == nullptr || entry->value == nullptr) {
+ return nullptr;
+ } else {
+ return entry->value;
+ }
+ }
+ }
case Type::Elaborated:
- zig_panic("TODO elaborated");
+ {
+ const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
+ switch (elaborated_ty->getKeyword()) {
+ case ETK_Struct:
+ return trans_qual_type_with_table(c, elaborated_ty->getNamedType(),
+ source_loc, &c->struct_type_table);
+ case ETK_Enum:
+ return trans_qual_type_with_table(c, elaborated_ty->getNamedType(),
+ source_loc, &c->enum_type_table);
+ case ETK_Interface:
+ case ETK_Union:
+ case ETK_Class:
+ case ETK_Typename:
+ case ETK_None:
+ emit_warning(c, source_loc, "unsupported elaborated type");
+ return nullptr;
+ }
+ }
case Type::FunctionProto:
- zig_panic("TODO FunctionProto");
+ {
+ const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);
+
+ AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
+ switch (fn_proto_ty->getCallConv()) {
+ case CC_C: // __attribute__((cdecl))
+ proto_node->data.fn_proto.cc = CallingConventionC;
+ break;
+ case CC_X86StdCall: // __attribute__((stdcall))
+ proto_node->data.fn_proto.cc = CallingConventionStdcall;
+ break;
+ case CC_X86FastCall: // __attribute__((fastcall))
+ emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
+ return nullptr;
+ case CC_X86ThisCall: // __attribute__((thiscall))
+ emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
+ return nullptr;
+ case CC_X86VectorCall: // __attribute__((vectorcall))
+ emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
+ return nullptr;
+ case CC_X86Pascal: // __attribute__((pascal))
+ emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
+ return nullptr;
+ case CC_Win64: // __attribute__((ms_abi))
+ emit_warning(c, source_loc, "unsupported calling convention: win64");
+ return nullptr;
+ case CC_X86_64SysV: // __attribute__((sysv_abi))
+ emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
+ return nullptr;
+ case CC_X86RegCall:
+ emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
+ return nullptr;
+ case CC_AAPCS: // __attribute__((pcs("aapcs")))
+ emit_warning(c, source_loc, "unsupported calling convention: aapcs");
+ return nullptr;
+ case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
+ emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
+ return nullptr;
+ case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
+ emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
+ return nullptr;
+ case CC_SpirFunction: // default for OpenCL functions on SPIR target
+ emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
+ return nullptr;
+ case CC_OpenCLKernel:
+ emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
+ return nullptr;
+ case CC_Swift:
+ emit_warning(c, source_loc, "unsupported calling convention: Swift");
+ return nullptr;
+ case CC_PreserveMost:
+ emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
+ return nullptr;
+ case CC_PreserveAll:
+ emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
+ return nullptr;
+ }
+
+ proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
+ size_t param_count = fn_proto_ty->getNumParams();
+
+ if (fn_proto_ty->getNoReturnAttr()) {
+ proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
+ } else {
+ proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_proto_ty->getReturnType(),
+ source_loc);
+ if (proto_node->data.fn_proto.return_type == nullptr) {
+ emit_warning(c, source_loc, "unsupported function proto return type");
+ return nullptr;
+ }
+ // convert c_void to actual void (only for return type)
+ if (is_c_void_type(proto_node->data.fn_proto.return_type)) {
+ proto_node->data.fn_proto.return_type = nullptr;
+ }
+ }
+
+ //emit_warning(c, source_loc, "TODO figure out fn prototype fn name");
+ const char *fn_name = nullptr;
+ if (fn_name != nullptr) {
+ proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
+ }
+
+ for (size_t i = 0; i < param_count; i += 1) {
+ QualType qt = fn_proto_ty->getParamType(i);
+ AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
+
+ if (param_type_node == nullptr) {
+ emit_warning(c, source_loc, "unresolved function proto parameter type");
+ return nullptr;
+ }
+
+ AstNode *param_node = trans_create_node(c, NodeTypeParamDecl);
+ //emit_warning(c, source_loc, "TODO figure out fn prototype param name");
+ const char *param_name = nullptr;
+ if (param_name == nullptr) {
+ param_node->data.param_decl.name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
+ } else {
+ param_node->data.param_decl.name = buf_create_from_str(param_name);
+ }
+ param_node->data.param_decl.is_noalias = qt.isRestrictQualified();
+ param_node->data.param_decl.type = param_type_node;
+ proto_node->data.fn_proto.params.append(param_node);
+ }
+ // TODO check for always_inline attribute
+ // TODO check for align attribute
+
+ return proto_node;
+ }
case Type::Record:
- zig_panic("TODO Record");
+ {
+ const RecordType *record_ty = static_cast<const RecordType*>(ty);
+ return resolve_record_decl(c, record_ty->getDecl());
+ }
case Type::Enum:
- zig_panic("TODO Enum");
+ {
+ const EnumType *enum_ty = static_cast<const EnumType*>(ty);
+ return resolve_enum_decl(c, enum_ty->getDecl());
+ }
case Type::ConstantArray:
- zig_panic("TODO ConstantArray");
+ {
+ const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);
+ AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
+ if (child_type_node == nullptr) {
+ emit_warning(c, source_loc, "unresolved array element type");
+ return nullptr;
+ }
+ uint64_t size = const_arr_ty->getSize().getLimitedValue();
+ AstNode *size_node = trans_create_node_unsigned(c, size);
+ return trans_create_node_array_type(c, size_node, child_type_node);
+ }
case Type::Paren:
- zig_panic("TODO Paren");
+ {
+ const ParenType *paren_ty = static_cast<const ParenType *>(ty);
+ return trans_qual_type(c, paren_ty->getInnerType(), source_loc);
+ }
case Type::Decayed:
- zig_panic("TODO Decayed");
+ {
+ const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty);
+ return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);
+ }
case Type::Attributed:
- zig_panic("TODO Attributed");
+ {
+ const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty);
+ return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
+ }
case Type::BlockPointer:
case Type::LValueReference:
case Type::RValueReference:
@@ -863,7 +731,8 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo
case Type::Pipe:
case Type::ObjCTypeParam:
case Type::DeducedTemplateSpecialization:
- zig_panic("TODO more c type aoeu");
+ emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
+ return nullptr;
}
zig_unreachable();
}
@@ -875,15 +744,7 @@ static AstNode * trans_qual_type_with_table(Context *c, QualType qt, const Sourc
}
static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) {
- return trans_qual_type_with_table(c, qt, source_loc, &c->global_type_table2);
-}
-
-static AstNode * trans_create_node(Context *c, NodeType id) {
- AstNode *node = allocate<AstNode>(1);
- node->type = id;
- node->owner = c->import;
- // TODO line/column. mapping to C file??
- return node;
+ return trans_qual_type_with_table(c, qt, source_loc, &c->global_type_table);
}
static AstNode * trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) {
@@ -907,35 +768,15 @@ static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt)
}
}
-static void aps_int_to_bigint(Context *c, const llvm::APSInt &aps_int, BigInt *bigint) {
- // TODO respect actually big integers
- if (aps_int.isSigned()) {
- if (aps_int > INT64_MAX || aps_int < INT64_MIN) {
- zig_panic("TODO actually bigint in C");
- } else {
- bigint_init_signed(bigint, aps_int.getExtValue());
- }
- } else {
- if (aps_int > INT64_MAX) {
- zig_panic("TODO actually bigint in C");
- } else {
- bigint_init_unsigned(bigint, aps_int.getExtValue());
- }
- }
-}
-
-static AstNode * trans_integer_literal(Context *c, IntegerLiteral *stmt) {
- AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
+static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) {
llvm::APSInt result;
if (!stmt->EvaluateAsInt(result, *c->ctx)) {
- fprintf(stderr, "TODO unable to convert integer literal to zig\n");
+ zig_panic("TODO handle libclang unable to evaluate C integer literal");
}
- node->data.int_literal.bigint = allocate<BigInt>(1);
- aps_int_to_bigint(c, result, node->data.int_literal.bigint);
- return node;
+ return trans_create_node_apint(c, result);
}
-static AstNode * trans_conditional_operator(Context *c, AstNode *block, ConditionalOperator *stmt) {
+static AstNode *trans_conditional_operator(Context *c, AstNode *block, ConditionalOperator *stmt) {
AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
Expr *cond_expr = stmt->getCond();
@@ -1034,9 +875,7 @@ static AstNode * trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCa
return trans_expr(c, block, stmt->getSubExpr());
case CK_IntegralCast:
{
- AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
- node->data.fn_call_expr.fn_ref_expr = trans_create_symbol_node(c, "bitCast");
- node->data.fn_call_expr.is_builtin = true;
+ AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast");
node->data.fn_call_expr.params.append(trans_qual_type(c, stmt->getType(), stmt->getExprLoc()));
node->data.fn_call_expr.params.append(trans_expr(c, block, stmt->getSubExpr()));
return node;
@@ -1166,13 +1005,6 @@ static AstNode * trans_decl_ref_expr(Context *c, DeclRefExpr *stmt) {
return node;
}
-static AstNode * trans_create_num_lit_node_unsigned(Context *c, Stmt *stmt, uint64_t x) {
- AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
- node->data.int_literal.bigint = allocate<BigInt>(1);
- bigint_init_unsigned(node->data.int_literal.bigint, x);
- return node;
-}
-
static AstNode * trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) {
switch (stmt->getOpcode()) {
case UO_PostInc:
@@ -1200,7 +1032,7 @@ static AstNode * trans_unary_operator(Context *c, AstNode *block, UnaryOperator
} else if (c_is_unsigned_integer(c, op_expr->getType())) {
// we gotta emit 0 -% x
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
- node->data.bin_op_expr.op1 = trans_create_num_lit_node_unsigned(c, stmt, 0);
+ node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0);
node->data.bin_op_expr.op2 = trans_expr(c, block, op_expr);
node->data.bin_op_expr.bin_op = BinOpTypeSubWrap;
return node;
@@ -1230,19 +1062,14 @@ static AstNode * trans_local_declaration(Context *c, AstNode *block, DeclStmt *s
switch (decl->getKind()) {
case Decl::Var: {
VarDecl *var_decl = (VarDecl *)decl;
- AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration);
- node->data.variable_declaration.symbol = buf_create_from_str(decl_name(var_decl));
QualType qual_type = var_decl->getTypeSourceInfo()->getType();
- node->data.variable_declaration.is_const = qual_type.isConstQualified();
- node->data.variable_declaration.type = trans_qual_type(c, qual_type, stmt->getStartLoc());
- if (var_decl->hasInit()) {
- node->data.variable_declaration.expr = trans_expr(c, block, var_decl->getInit());
- }
-
+ AstNode *init_node = var_decl->hasInit() ? trans_expr(c, block, var_decl->getInit()) : nullptr;
+ AstNode *type_node = trans_qual_type(c, qual_type, stmt->getStartLoc());
+ AstNode *node = trans_create_node_var_decl(c, qual_type.isConstQualified(),
+ buf_create_from_str(decl_name(var_decl)), type_node, init_node);
block->data.block.statements.append(node);
continue;
}
-
case Decl::AccessSpec:
zig_panic("TODO handle decl kind AccessSpec");
case Decl::Block:
@@ -1802,53 +1629,57 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
- if (fn_decl->hasBody()) {
- fprintf(stderr, "fn %s\n", buf_ptr(fn_name));
- Stmt *body = fn_decl->getBody();
- AstNode *body_node = trans_stmt(c, nullptr, body);
- ast_render(c->codegen, stderr, body_node, 4);
- fprintf(stderr, "\n");
- }
-
if (get_global(c, fn_name)) {
// we already saw this function
return;
}
- TypeTableEntry *fn_type = resolve_qual_type(c, fn_decl->getType(), fn_decl);
-
- if (fn_type->id == TypeTableEntryIdInvalid) {
- emit_warning(c, fn_decl->getLocation(), "ignoring function '%s' - unable to resolve type", buf_ptr(fn_name));
+ AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), fn_decl->getLocation());
+ if (proto_node == nullptr) {
+ emit_warning(c, fn_decl->getLocation(), "unable to resolve prototype of function '%s'", buf_ptr(fn_name));
return;
}
- assert(fn_type->id == TypeTableEntryIdFn);
- FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong);
- buf_init_from_buf(&fn_entry->symbol_name, fn_name);
- fn_entry->type_entry = fn_type;
+ proto_node->data.fn_proto.name = fn_name;
+ proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
- assert(fn_type->data.fn.fn_type_id.cc != CallingConventionNaked);
+ StorageClass sc = fn_decl->getStorageClass();
+ if (sc == SC_None) {
+ proto_node->data.fn_proto.visib_mod = fn_decl->hasBody() ? VisibModExport : c->visib_mod;
+ } else if (sc == SC_Extern || sc == SC_Static) {
+ proto_node->data.fn_proto.visib_mod = c->visib_mod;
+ } else if (sc == SC_PrivateExtern) {
+ emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
+ return;
+ } else {
+ emit_warning(c, fn_decl->getLocation(), "unsupported storage class: unknown");
+ return;
+ }
- size_t arg_count = fn_type->data.fn.fn_type_id.param_count;
- fn_entry->param_names = allocate<Buf *>(arg_count);
- Buf *name_buf;
+ const FunctionProtoType *fn_proto_ty = (const FunctionProtoType *) fn_decl->getType().getTypePtr();
+ size_t arg_count = fn_proto_ty->getNumParams();
for (size_t i = 0; i < arg_count; i += 1) {
+ AstNode *param_node = proto_node->data.fn_proto.params.at(i);
const ParmVarDecl *param = fn_decl->getParamDecl(i);
const char *name = decl_name(param);
- if (strlen(name) == 0) {
- name_buf = buf_sprintf("arg%" ZIG_PRI_usize "", i);
- } else {
- name_buf = buf_create_from_str(name);
+ if (strlen(name) != 0) {
+ param_node->data.param_decl.name = buf_create_from_str(name);
}
- fn_entry->param_names[i] = name_buf;
}
- TldFn *tld_fn = allocate<TldFn>(1);
- parseh_init_tld(c, &tld_fn->base, TldIdFn, fn_name);
- tld_fn->fn_entry = fn_entry;
- add_global(c, &tld_fn->base);
+ if (fn_decl->hasBody()) {
+ Stmt *body = fn_decl->getBody();
+
+ AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef);
+ fn_def_node->data.fn_def.fn_proto = proto_node;
+ fn_def_node->data.fn_def.body = trans_stmt(c, nullptr, body);
- c->codegen->fn_protos.append(fn_entry);
+ proto_node->data.fn_proto.fn_def_node = fn_def_node;
+ c->root->data.root.top_level_decls.append(fn_def_node);
+ return;
+ }
+
+ c->root->data.root.top_level_decls.append(proto_node);
}
static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {
@@ -1874,53 +1705,36 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)
// use the name of this typedef
// TODO
- TypeTableEntry *child_type = resolve_qual_type(c, child_qt, typedef_decl);
- if (child_type->id == TypeTableEntryIdInvalid) {
+ AstNode *type_node = trans_qual_type(c, child_qt, typedef_decl->getLocation());
+ if (type_node == nullptr) {
emit_warning(c, typedef_decl->getLocation(), "typedef %s - unresolved child type", buf_ptr(type_name));
return;
}
- add_const_type(c, type_name, child_type);
-}
-
-static void replace_with_fwd_decl(Context *c, TypeTableEntry *struct_type, Buf *full_type_name) {
- unsigned line = c->source_node ? c->source_node->line : 0;
- ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugForwardDeclType(c->codegen->dbuilder,
- ZigLLVMTag_DW_structure_type(), buf_ptr(full_type_name),
- ZigLLVMFileToScope(c->import->di_file), c->import->di_file, line);
-
- ZigLLVMReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type);
- struct_type->di_type = replacement_di_type;
- struct_type->id = TypeTableEntryIdOpaque;
+ add_global_var(c, type_name, type_node);
+ c->global_type_table.put(type_name, type_node);
}
-static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
+static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
auto existing_entry = c->decl_table.maybe_get((void*)enum_decl);
if (existing_entry) {
return existing_entry->value;
}
const char *raw_name = decl_name(enum_decl);
-
- Buf *bare_name;
- if (raw_name[0] == 0) {
- bare_name = buf_sprintf("anon_$%" PRIu32, get_next_anon_index(c));
- } else {
- bare_name = buf_create_from_str(raw_name);
- }
-
- Buf *full_type_name = buf_sprintf("enum_%s", buf_ptr(bare_name));
+ bool is_anonymous = (raw_name[0] == 0);
+ Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
+ Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
const EnumDecl *enum_def = enum_decl->getDefinition();
if (!enum_def) {
- TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
- ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern);
- enum_type->data.enumeration.zero_bits_known = true;
- enum_type->data.enumeration.abi_alignment = 1;
- c->enum_type_table.put(bare_name, enum_type);
- c->decl_table.put(enum_decl, enum_type);
- replace_with_fwd_decl(c, enum_type, full_type_name);
-
- return enum_type;
+ AstNode *opaque_node = trans_create_node_opaque(c);
+ if (!is_anonymous) {
+ c->enum_type_table.put(bare_name, opaque_node);
+ add_global_weak_alias(c, bare_name, opaque_node);
+ add_global_var(c, full_type_name, opaque_node);
+ }
+ c->decl_table.put(enum_decl, opaque_node);
+ return opaque_node;
}
bool pure_enum = true;
@@ -1935,25 +1749,16 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
}
}
- TypeTableEntry *tag_int_type = resolve_qual_type(c, enum_decl->getIntegerType(), enum_decl);
+ AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation());
+ assert(tag_int_type);
if (pure_enum) {
- TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
- ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern);
- TypeTableEntry *tag_type_entry = create_enum_tag_type(c->codegen, enum_type, tag_int_type);
- c->enum_type_table.put(bare_name, enum_type);
- c->decl_table.put(enum_decl, enum_type);
-
- enum_type->data.enumeration.gen_field_count = 0;
- enum_type->data.enumeration.complete = true;
- enum_type->data.enumeration.zero_bits_known = true;
- enum_type->data.enumeration.abi_alignment = 1;
- enum_type->data.enumeration.tag_type = tag_type_entry;
-
- enum_type->data.enumeration.src_field_count = field_count;
- enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
- ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
+ AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);
+ enum_node->data.container_decl.kind = ContainerKindEnum;
+ enum_node->data.container_decl.layout = ContainerLayoutExtern;
+ enum_node->data.container_decl.init_arg_expr = tag_int_type;
+ enum_node->data.container_decl.fields.resize(field_count);
uint32_t i = 0;
for (auto it = enum_def->enumerator_begin(),
it_end = enum_def->enumerator_end();
@@ -1963,92 +1768,63 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
Buf *field_name;
- if (buf_starts_with_buf(enum_val_name, bare_name)) {
+ if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) {
field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
} else {
field_name = enum_val_name;
}
- TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
- type_enum_field->name = field_name;
- type_enum_field->type_entry = c->codegen->builtin_types.entry_void;
- type_enum_field->value = i;
-
- di_enumerators[i] = ZigLLVMCreateDebugEnumerator(c->codegen->dbuilder, buf_ptr(type_enum_field->name), i);
-
+ AstNode *field_node = trans_create_node(c, NodeTypeStructField);
+ field_node->data.struct_field.name = field_name;
+ field_node->data.struct_field.type = nullptr;
+ enum_node->data.container_decl.fields.items[i] = field_node;
// in C each enum value is in the global namespace. so we put them there too.
// at this point we can rely on the enum emitting successfully
- add_global(c, create_global_num_lit_unsigned_negative(c, enum_val_name, i, false));
+ AstNode *field_access_node = trans_create_node_field_access(c,
+ trans_create_node_symbol(c, full_type_name), field_name);
+ add_global_var(c, enum_val_name, field_access_node);
}
- // create llvm type for root struct
- enum_type->type_ref = tag_type_entry->type_ref;
-
- enum_type->data.enumeration.abi_alignment = LLVMABIAlignmentOfType(c->codegen->target_data_ref,
- enum_type->type_ref);
-
- // create debug type for tag
- unsigned line = c->source_node ? (c->source_node->line + 1) : 0;
- uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, enum_type->type_ref);
- uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, enum_type->type_ref);
- ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(c->codegen->dbuilder,
- ZigLLVMFileToScope(c->import->di_file), buf_ptr(bare_name),
- c->import->di_file, line,
- debug_size_in_bits,
- debug_align_in_bits,
- di_enumerators, field_count, tag_type_entry->di_type, "");
-
- ZigLLVMReplaceTemporary(c->codegen->dbuilder, enum_type->di_type, tag_di_type);
- enum_type->di_type = tag_di_type;
-
- return enum_type;
- } else {
- // TODO after issue #305 is solved, make this be an enum with tag_int_type
- // as the integer type and set the custom enum values
- TypeTableEntry *enum_type = tag_int_type;
- c->enum_type_table.put(bare_name, enum_type);
- c->decl_table.put(enum_decl, enum_type);
-
- // add variables for all the values with enum_type
- for (auto it = enum_def->enumerator_begin(),
- it_end = enum_def->enumerator_end();
- it != it_end; ++it)
- {
- const EnumConstantDecl *enum_const = *it;
-
- Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
-
- Tld *tld = create_global_num_lit_ap(c, enum_decl, enum_val_name, enum_const->getInitVal());
- if (!tld)
- return c->codegen->builtin_types.entry_invalid;
-
- add_global(c, tld);
+ if (!is_anonymous) {
+ c->enum_type_table.put(bare_name, enum_node);
+ add_global_weak_alias(c, bare_name, enum_node);
+ add_global_var(c, full_type_name, enum_node);
}
+ c->decl_table.put(enum_decl, enum_node);
- return enum_type;
+ return enum_node;
}
-}
-static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
- TypeTableEntry *enum_type = resolve_enum_decl(c, enum_decl);
+ // TODO after issue #305 is solved, make this be an enum with tag_int_type
+ // as the integer type and set the custom enum values
+ AstNode *enum_node = tag_int_type;
- if (enum_type->id == TypeTableEntryIdInvalid)
- return;
- // make an alias without the "enum_" prefix. this will get emitted at the
- // end if it doesn't conflict with anything else
- bool is_anonymous = (decl_name(enum_decl)[0] == 0);
- if (is_anonymous)
- return;
+ // add variables for all the values with enum_node
+ for (auto it = enum_def->enumerator_begin(),
+ it_end = enum_def->enumerator_end();
+ it != it_end; ++it)
+ {
+ const EnumConstantDecl *enum_const = *it;
+
+ Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
+ AstNode *int_node = trans_create_node_apint(c, enum_const->getInitVal());
+ AstNode *var_node = add_global_var(c, enum_val_name, int_node);
+ var_node->data.variable_declaration.type = tag_int_type;
+ }
- Buf *bare_name = buf_create_from_str(decl_name(enum_decl));
+ if (!is_anonymous) {
+ c->enum_type_table.put(bare_name, enum_node);
+ add_global_weak_alias(c, bare_name, enum_node);
+ add_global_var(c, full_type_name, enum_node);
+ }
+ c->decl_table.put(enum_decl, enum_node);
- Tld *tld = add_container_tld(c, enum_type);
- add_global_weak_alias(c, bare_name, tld);
+ return enum_node;
}
-static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
+static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
auto existing_entry = c->decl_table.maybe_get((void*)record_decl);
if (existing_entry) {
return existing_entry->value;
@@ -2058,35 +1834,26 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
if (!record_decl->isStruct()) {
emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct", raw_name);
- return c->codegen->builtin_types.entry_invalid;
- }
-
- Buf *bare_name;
- if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) {
- bare_name = buf_sprintf("anon_$%" PRIu32, get_next_anon_index(c));
- } else {
- bare_name = buf_create_from_str(raw_name);
+ c->decl_table.put(record_decl, nullptr);
+ return nullptr;
}
- Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name));
-
-
- TypeTableEntry *struct_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
- ContainerKindStruct, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern);
- struct_type->data.structure.zero_bits_known = true;
- struct_type->data.structure.abi_alignment = 1;
-
- c->struct_type_table.put(bare_name, struct_type);
- c->decl_table.put(record_decl, struct_type);
+ bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0;
+ Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
+ Buf *full_type_name = (bare_name == nullptr) ? nullptr : buf_sprintf("struct_%s", buf_ptr(bare_name));
RecordDecl *record_def = record_decl->getDefinition();
- unsigned line = c->source_node ? c->source_node->line : 0;
- if (!record_def) {
- replace_with_fwd_decl(c, struct_type, full_type_name);
- return struct_type;
+ if (record_def == nullptr) {
+ AstNode *opaque_node = trans_create_node_opaque(c);
+ if (!is_anonymous) {
+ c->struct_type_table.put(bare_name, opaque_node);
+ add_global_weak_alias(c, bare_name, opaque_node);
+ add_global_var(c, full_type_name, opaque_node);
+ }
+ c->decl_table.put(record_decl, opaque_node);
+ return opaque_node;
}
-
// count fields and validate
uint32_t field_count = 0;
for (auto it = record_def->field_begin(),
@@ -2096,105 +1863,69 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
const FieldDecl *field_decl = *it;
if (field_decl->isBitField()) {
- emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - has bitfield\n", buf_ptr(bare_name));
- replace_with_fwd_decl(c, struct_type, full_type_name);
- return struct_type;
+ emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - has bitfield",
+ is_anonymous ? "(anon)" : buf_ptr(bare_name));
+
+ AstNode *opaque_node = trans_create_node_opaque(c);
+
+ if (!is_anonymous) {
+ c->struct_type_table.put(bare_name, opaque_node);
+ add_global_weak_alias(c, bare_name, opaque_node);
+ add_global_var(c, full_type_name, opaque_node);
+ }
+ c->decl_table.put(record_decl, opaque_node);
+ return opaque_node;;
}
}
- struct_type->data.structure.src_field_count = field_count;
- struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
- LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count);
- ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(field_count);
+ AstNode *struct_node = trans_create_node(c, NodeTypeContainerDecl);
+ struct_node->data.container_decl.kind = ContainerKindStruct;
+ struct_node->data.container_decl.layout = ContainerLayoutExtern;
- // next, populate element_types as its needed for LLVMStructSetBody which is needed for LLVMOffsetOfElement
- uint32_t i = 0;
- for (auto it = record_def->field_begin(),
- it_end = record_def->field_end();
- it != it_end; ++it, i += 1)
- {
- const FieldDecl *field_decl = *it;
+ // TODO handle attribute packed
- TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
- type_struct_field->name = buf_create_from_str(decl_name(field_decl));
- type_struct_field->src_index = i;
- type_struct_field->gen_index = i;
- TypeTableEntry *field_type = resolve_qual_type(c, field_decl->getType(), field_decl);
- type_struct_field->type_entry = field_type;
-
- if (type_is_invalid(field_type) || !type_is_complete(field_type)) {
- emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - unresolved type\n", buf_ptr(bare_name));
- replace_with_fwd_decl(c, struct_type, full_type_name);
- return struct_type;
- }
+ struct_node->data.container_decl.fields.resize(field_count);
- element_types[i] = field_type->type_ref;
- assert(element_types[i]);
+ // must be before fields in case a circular reference happens
+ if (!is_anonymous) {
+ c->struct_type_table.put(bare_name, struct_node);
+ add_global_weak_alias(c, bare_name, struct_node);
+ add_global_var(c, full_type_name, struct_node);
}
+ c->decl_table.put(record_decl, struct_node);
- LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false);
-
- // finally populate debug info
- i = 0;
+ uint32_t i = 0;
for (auto it = record_def->field_begin(),
it_end = record_def->field_end();
it != it_end; ++it, i += 1)
{
- TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
- TypeTableEntry *field_type = type_struct_field->type_entry;
-
- uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, field_type->type_ref);
- uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, field_type->type_ref);
- uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(c->codegen->target_data_ref, struct_type->type_ref, i);
- di_element_types[i] = ZigLLVMCreateDebugMemberType(c->codegen->dbuilder,
- ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),
- c->import->di_file, line + 1,
- debug_size_in_bits,
- debug_align_in_bits,
- debug_offset_in_bits,
- 0, field_type->di_type);
-
- assert(di_element_types[i]);
+ const FieldDecl *field_decl = *it;
- }
- struct_type->data.structure.embedded_in_current = false;
-
- struct_type->data.structure.gen_field_count = field_count;
- struct_type->data.structure.complete = true;
- struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(c->codegen->target_data_ref,
- struct_type->type_ref);
-
- uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, struct_type->type_ref);
- uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, struct_type->type_ref);
- ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(c->codegen->dbuilder,
- ZigLLVMFileToScope(c->import->di_file),
- buf_ptr(full_type_name), c->import->di_file, line + 1,
- debug_size_in_bits,
- debug_align_in_bits,
- 0,
- nullptr, di_element_types, field_count, 0, nullptr, "");
-
- ZigLLVMReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type);
- struct_type->di_type = replacement_di_type;
-
- return struct_type;
-}
+ AstNode *field_node = trans_create_node(c, NodeTypeStructField);
+ field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));
+ field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation());
-static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
- TypeTableEntry *struct_type = resolve_record_decl(c, record_decl);
+ if (field_node->data.struct_field.type == nullptr) {
+ emit_warning(c, field_decl->getLocation(),
+ "struct %s demoted to opaque type - unresolved type",
+ is_anonymous ? "(anon)" : buf_ptr(bare_name));
- if (struct_type->id == TypeTableEntryIdInvalid) {
- return;
- }
+ AstNode *opaque_node = trans_create_node_opaque(c);
+ if (!is_anonymous) {
+ c->struct_type_table.put(bare_name, opaque_node);
+ add_global_weak_alias(c, bare_name, opaque_node);
+ add_global_var(c, full_type_name, opaque_node);
+ }
+ c->decl_table.put(record_decl, opaque_node);
- bool is_anonymous = (record_decl->isAnonymousStructOrUnion() || decl_name(record_decl)[0] == 0);
- if (is_anonymous)
- return;
+ return opaque_node;
+ }
+
+ struct_node->data.container_decl.fields.items[i] = field_node;
+ }
- Buf *bare_name = buf_create_from_str(decl_name(record_decl));
- Tld *tld = add_container_tld(c, struct_type);
- add_global_weak_alias(c, bare_name, tld);
+ return struct_node;
}
static void visit_var_decl(Context *c, const VarDecl *var_decl) {
@@ -2204,17 +1935,19 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
case VarDecl::TLS_None:
break;
case VarDecl::TLS_Static:
- emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - static thread local storage\n", buf_ptr(name));
+ emit_warning(c, var_decl->getLocation(),
+ "ignoring variable '%s' - static thread local storage", buf_ptr(name));
return;
case VarDecl::TLS_Dynamic:
- emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - dynamic thread local storage\n", buf_ptr(name));
+ emit_warning(c, var_decl->getLocation(),
+ "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
return;
}
QualType qt = var_decl->getType();
- TypeTableEntry *var_type = resolve_qual_type(c, qt, var_decl);
- if (var_type->id == TypeTableEntryIdInvalid) {
- emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type\n", buf_ptr(name));
+ AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
+ if (var_type == nullptr) {
+ emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));
return;
}
@@ -2223,59 +1956,53 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
bool is_const = qt.isConstQualified();
if (is_static && !is_extern) {
- if (!var_decl->hasInit()) {
- emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - no initializer\n", buf_ptr(name));
- return;
- }
- APValue *ap_value = var_decl->evaluateValue();
- if (!ap_value) {
- emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unable to evaluate initializer\n", buf_ptr(name));
- return;
- }
- ConstExprValue *init_value = nullptr;
- switch (ap_value->getKind()) {
- case APValue::Int:
- {
- if (var_type->id != TypeTableEntryIdInt) {
- emit_warning(c, var_decl->getLocation(),
- "ignoring variable '%s' - int initializer for non int type\n", buf_ptr(name));
- return;
- }
- init_value = create_const_int_ap(c, var_type, var_decl, ap_value->getInt());
- if (!init_value)
- return;
-
- break;
- }
- case APValue::Uninitialized:
- case APValue::Float:
- case APValue::ComplexInt:
- case APValue::ComplexFloat:
- case APValue::LValue:
- case APValue::Vector:
- case APValue::Array:
- case APValue::Struct:
- case APValue::Union:
- case APValue::MemberPointer:
- case APValue::AddrLabelDiff:
+ AstNode *init_node;
+ if (var_decl->hasInit()) {
+ APValue *ap_value = var_decl->evaluateValue();
+ if (ap_value == nullptr) {
emit_warning(c, var_decl->getLocation(),
- "ignoring variable '%s' - unrecognized initializer value kind\n", buf_ptr(name));
+ "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
return;
+ }
+ switch (ap_value->getKind()) {
+ case APValue::Int:
+ init_node = trans_create_node_apint(c, ap_value->getInt());
+ break;
+ case APValue::Uninitialized:
+ init_node = trans_create_node_symbol_str(c, "undefined");
+ break;
+ case APValue::Float:
+ case APValue::ComplexInt:
+ case APValue::ComplexFloat:
+ case APValue::LValue:
+ case APValue::Vector:
+ case APValue::Array:
+ case APValue::Struct:
+ case APValue::Union:
+ case APValue::MemberPointer:
+ case APValue::AddrLabelDiff:
+ emit_warning(c, var_decl->getLocation(),
+ "ignoring variable '%s' - unrecognized initializer value kind", buf_ptr(name));
+ return;
+ }
+ } else {
+ init_node = trans_create_node_symbol_str(c, "undefined");
}
- TldVar *tld_var = create_global_var(c, name, init_value, true);
- add_global(c, &tld_var->base);
+ AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, init_node);
+ c->root->data.root.top_level_decls.append(var_node);
return;
}
if (is_extern) {
- TldVar *tld_var = create_global_var(c, name, create_const_runtime(var_type), is_const);
- tld_var->var->linkage = VarLinkageExternal;
- add_global(c, &tld_var->base);
+ AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, nullptr);
+ var_node->data.variable_declaration.is_extern = true;
+ c->root->data.root.top_level_decls.append(var_node);
return;
}
- emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - non-extern, non-static variable\n", buf_ptr(name));
+ emit_warning(c, var_decl->getLocation(),
+ "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name));
return;
}
@@ -2290,25 +2017,22 @@ static bool decl_visitor(void *context, const Decl *decl) {
visit_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));
break;
case Decl::Enum:
- visit_enum_decl(c, static_cast<const EnumDecl *>(decl));
+ resolve_enum_decl(c, static_cast<const EnumDecl *>(decl));
break;
case Decl::Record:
- visit_record_decl(c, static_cast<const RecordDecl *>(decl));
+ resolve_record_decl(c, static_cast<const RecordDecl *>(decl));
break;
case Decl::Var:
visit_var_decl(c, static_cast<const VarDecl *>(decl));
break;
default:
- emit_warning(c, decl->getLocation(), "ignoring %s decl\n", decl->getDeclKindName());
+ emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());
}
return true;
}
static bool name_exists(Context *c, Buf *name) {
- if (c->global_type_table.maybe_get(name)) {
- return true;
- }
if (get_global(c, name)) {
return true;
}
@@ -2324,7 +2048,7 @@ static void render_aliases(Context *c) {
if (name_exists(c, alias->name))
continue;
- add_global_alias(c, alias->name, alias->tld);
+ add_global_var(c, alias->name, alias->node);
}
}
@@ -2335,8 +2059,7 @@ static void render_macros(Context *c) {
if (!entry)
break;
- Tld *var_tld = entry->value;
- add_global(c, var_tld);
+ add_global_var(c, entry->key, entry->value);
}
}
@@ -2355,52 +2078,52 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
switch (tok->id) {
case CTokIdCharLit:
if (is_last && is_first) {
- Tld *tld = create_global_num_lit_unsigned_negative(c, name, tok->data.char_lit, false);
- c->macro_table.put(name, tld);
+ AstNode *node = trans_create_node_unsigned(c, tok->data.char_lit);
+ c->macro_table.put(name, node);
}
return;
case CTokIdStrLit:
if (is_last && is_first) {
- Tld *tld = create_global_str_lit_var(c, name, buf_create_from_buf(&tok->data.str_lit));
- c->macro_table.put(name, tld);
+ AstNode *node = trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit));
+ c->macro_table.put(name, node);
}
return;
case CTokIdNumLitInt:
if (is_last) {
- Tld *tld;
+ AstNode *node;
switch (tok->data.num_lit_int.suffix) {
case CNumLitSuffixNone:
- tld = create_global_num_lit_unsigned_negative(c, name, tok->data.num_lit_int.x, negate);
+ node = trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate);
break;
case CNumLitSuffixL:
- tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate,
- c->codegen->builtin_types.entry_c_int[CIntTypeLong]);
+ node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
+ "c_long");
break;
case CNumLitSuffixU:
- tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate,
- c->codegen->builtin_types.entry_c_int[CIntTypeUInt]);
+ node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
+ "c_uint");
break;
case CNumLitSuffixLU:
- tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate,
- c->codegen->builtin_types.entry_c_int[CIntTypeULong]);
+ node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
+ "c_ulong");
break;
case CNumLitSuffixLL:
- tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate,
- c->codegen->builtin_types.entry_c_int[CIntTypeLongLong]);
+ node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
+ "c_longlong");
break;
case CNumLitSuffixLLU:
- tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate,
- c->codegen->builtin_types.entry_c_int[CIntTypeULongLong]);
+ node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
+ "c_ulonglong");
break;
}
- c->macro_table.put(name, tld);
+ c->macro_table.put(name, node);
}
return;
case CTokIdNumLitFloat:
if (is_last) {
double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float;
- Tld *tld = create_global_num_lit_float(c, name, value);
- c->macro_table.put(name, tld);
+ AstNode *node = trans_create_node_float_lit(c, value);
+ c->macro_table.put(name, node);
}
return;
case CTokIdSymbol:
@@ -2429,29 +2152,29 @@ static void process_symbol_macros(Context *c) {
for (size_t i = 0; i < c->macro_symbols.length; i += 1) {
MacroSymbol ms = c->macro_symbols.at(i);
- // If this macro aliases another top level declaration, we can make that happen by
- // putting another entry in the decl table pointing to the same top level decl.
- Tld *existing_tld = get_global(c, ms.value);
- if (!existing_tld)
+ // Check if this macro aliases another top level declaration
+ AstNode *existing_node = get_global(c, ms.value);
+ if (!existing_node || name_exists(c, ms.name))
continue;
// If a macro aliases a global variable which is a function pointer, we conclude that
// the macro is intended to represent a function that assumes the function pointer
// variable is non-null and calls it.
- if (existing_tld->id == TldIdVar) {
- TldVar *tld_var = (TldVar *)existing_tld;
- TypeTableEntry *var_type = tld_var->var->value->type;
- if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) {
- TypeTableEntry *child_type = var_type->data.maybe.child_type;
- if (child_type->id == TypeTableEntryIdFn) {
- Tld *tld = create_inline_fn_tld(c, ms.name, tld_var);
- c->macro_table.put(ms.name, tld);
+ if (existing_node->type == NodeTypeVariableDeclaration) {
+ AstNode *var_expr = existing_node->data.variable_declaration.expr;
+ if (var_expr != nullptr && var_expr->type == NodeTypePrefixOpExpr &&
+ var_expr->data.prefix_op_expr.prefix_op == PrefixOpMaybe)
+ {
+ AstNode *fn_proto_node = var_expr->data.prefix_op_expr.primary_expr;
+ if (fn_proto_node->type == NodeTypeFnProto) {
+ AstNode *inline_fn_node = trans_create_node_inline_fn(c, ms.name, ms.value, fn_proto_node);
+ c->macro_table.put(ms.name, inline_fn_node);
continue;
}
}
}
- add_global_alias(c, ms.name, existing_tld);
+ add_global_var(c, ms.name, existing_node);
}
}
@@ -2651,15 +2374,17 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
c->ctx = &ast_unit->getASTContext();
c->source_manager = &ast_unit->getSourceManager();
+ c->root = trans_create_node(c, NodeTypeRoot);
ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
process_preprocessor_entities(c, *ast_unit);
- process_symbol_macros(c);
-
render_macros(c);
+ process_symbol_macros(c);
render_aliases(c);
+ import->root = c->root;
+
return 0;
}
test/parseh.zig
@@ -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",