From fa1ea6062b172e75674353ee19857db9046ec9ee Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Jan 2016 03:11:51 -0700 Subject: [PATCH] parseh works for simple functions --- src/main.cpp | 39 +++++++--- src/parseh.cpp | 199 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 222 insertions(+), 16 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e3094cba7..23a637c77 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -170,9 +170,19 @@ static void print_indent(ParseHPrint *p) { } } -static const char *type_node_to_name(AstNode *type_node) { - assert(type_node->type == NodeTypeSymbol); - return buf_ptr(&type_node->data.symbol_expr.symbol); +static Buf *type_node_to_name(AstNode *type_node) { + if (type_node->type == NodeTypeSymbol) { + return &type_node->data.symbol_expr.symbol; + } else if (type_node->type == NodeTypePrefixOpExpr) { + PrefixOp op = type_node->data.prefix_op_expr.prefix_op; + if (op == PrefixOpAddressOf) { + return buf_sprintf("&%s", buf_ptr(type_node_to_name(type_node->data.prefix_op_expr.primary_expr))); + } else { + zig_unreachable(); + } + } else { + zig_unreachable(); + } } static int parseh(const char *arg0, int argc, char **argv) { @@ -208,6 +218,11 @@ static int parseh(const char *arg0, int argc, char **argv) { clang_argv.append(in_file); + Buf *libc_include_path = buf_alloc(); + os_path_join(buf_create_from_str(ZIG_LIBC_DIR), buf_create_from_str("include"), libc_include_path); + clang_argv.append("-isystem"); + clang_argv.append(buf_ptr(libc_include_path)); + ParseHPrint parse_h_print = {{{0}}}; ParseHPrint *p = &parse_h_print; p->f = stdout; @@ -235,9 +250,9 @@ static int parseh(const char *arg0, int argc, char **argv) { AstNode *field_node = struct_decl->data.struct_decl.fields.at(field_i); assert(field_node->type == NodeTypeStructField); const char *field_name = buf_ptr(&field_node->data.struct_field.name); - const char *type_name = type_node_to_name(field_node->data.struct_field.type); + Buf *type_name = type_node_to_name(field_node->data.struct_field.type); print_indent(p); - fprintf(p->f, "%s: %s,\n", field_name, type_name); + fprintf(p->f, "%s: %s,\n", field_name, buf_ptr(type_name)); } p->cur_indent -= indent_size; @@ -249,15 +264,17 @@ static int parseh(const char *arg0, int argc, char **argv) { assert(fn_proto->type == NodeTypeFnProto); print_indent(p); const char *fn_name = buf_ptr(&fn_proto->data.fn_proto.name); - fprintf(p->f, "extern fn %s(", fn_name); + const char *pub_str = (fn_proto->data.fn_proto.visib_mod == VisibModPub) ? "pub " : ""; + fprintf(p->f, "%sextern fn %s(", pub_str, fn_name); int arg_count = fn_proto->data.fn_proto.params.length; bool is_var_args = fn_proto->data.fn_proto.is_var_args; for (int arg_i = 0; arg_i < arg_count; arg_i += 1) { AstNode *param_decl = fn_proto->data.fn_proto.params.at(arg_i); assert(param_decl->type == NodeTypeParamDecl); const char *arg_name = buf_ptr(¶m_decl->data.param_decl.name); - const char *arg_type = type_node_to_name(param_decl->data.param_decl.type); - fprintf(p->f, "%s: %s", arg_name, arg_type); + Buf *arg_type = type_node_to_name(param_decl->data.param_decl.type); + const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : ""; + fprintf(p->f, "%s%s: %s", noalias_str, arg_name, buf_ptr(arg_type)); if (arg_i + 1 < arg_count || is_var_args) { fprintf(p->f, ", "); } @@ -266,9 +283,9 @@ static int parseh(const char *arg0, int argc, char **argv) { fprintf(p->f, "..."); } fprintf(p->f, ")"); - const char *return_type_name = type_node_to_name(fn_proto->data.fn_proto.return_type); - if (strcmp(return_type_name, "void") != 0) { - fprintf(p->f, " -> %s", return_type_name); + Buf *return_type_name = type_node_to_name(fn_proto->data.fn_proto.return_type); + if (!buf_eql_str(return_type_name, "void")) { + fprintf(p->f, " -> %s", buf_ptr(return_type_name)); } fprintf(p->f, ";\n"); } diff --git a/src/parseh.cpp b/src/parseh.cpp index ee7d50ede..445822be4 100644 --- a/src/parseh.cpp +++ b/src/parseh.cpp @@ -19,12 +19,202 @@ using namespace clang; struct Context { ParseH *parse_h; + bool warnings_on; + bool pub; }; -static bool decl_visitor(void *context, const Decl *decl) { - //Context *c = (Context*)context; +static AstNode *type_node_from_qual_type(Context *c, QualType qt); - fprintf(stderr, "got top level decl\n"); +static AstNode *create_node(Context *c, NodeType type) { + AstNode *node = allocate(1); + node->type = type; + return node; +} + +static AstNode *simple_type_node(Context *c, const char *type_name) { + AstNode *node = create_node(c, NodeTypeSymbol); + buf_init_from_str(&node->data.symbol_expr.symbol, type_name); + return node; +} + +static const char *decl_name(const Decl *decl) { + const NamedDecl *named_decl = static_cast(decl); + return (const char *)named_decl->getName().bytes_begin(); +} + +static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { + AstNode *node = create_node(c, NodeTypePrefixOpExpr); + node->data.prefix_op_expr.prefix_op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf; + node->data.prefix_op_expr.primary_expr = type_node; + return node; +} + +static AstNode *type_node(Context *c, const Type *ty, bool is_const) { + switch (ty->getTypeClass()) { + case Type::Builtin: + { + const BuiltinType *builtin_ty = static_cast(ty); + switch (builtin_ty->getKind()) { + case BuiltinType::Void: + return simple_type_node(c, "void"); + case BuiltinType::Bool: + return simple_type_node(c, "bool"); + case BuiltinType::Char_U: + case BuiltinType::UChar: + return simple_type_node(c, "u8"); + case BuiltinType::Char_S: + case BuiltinType::SChar: + return simple_type_node(c, "i8"); + case BuiltinType::UShort: + return simple_type_node(c, "c_ushort"); + case BuiltinType::UInt: + return simple_type_node(c, "c_uint"); + case BuiltinType::ULong: + return simple_type_node(c, "c_ulong"); + case BuiltinType::ULongLong: + return simple_type_node(c, "c_ulonglong"); + case BuiltinType::Short: + return simple_type_node(c, "c_short"); + case BuiltinType::Int: + return simple_type_node(c, "c_int"); + case BuiltinType::Long: + return simple_type_node(c, "c_long"); + case BuiltinType::LongLong: + return simple_type_node(c, "c_longlong"); + case BuiltinType::Float: + return simple_type_node(c, "f32"); + case BuiltinType::Double: + return simple_type_node(c, "f64"); + case BuiltinType::LongDouble: + return simple_type_node(c, "f128"); + case BuiltinType::WChar_U: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::UInt128: + case BuiltinType::WChar_S: + case BuiltinType::Int128: + case BuiltinType::Half: + case BuiltinType::NullPtr: + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + case BuiltinType::OCLImage1d: + case BuiltinType::OCLImage1dArray: + case BuiltinType::OCLImage1dBuffer: + case BuiltinType::OCLImage2d: + case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage3d: + case BuiltinType::OCLSampler: + case BuiltinType::OCLEvent: + case BuiltinType::Dependent: + case BuiltinType::Overload: + case BuiltinType::BoundMember: + case BuiltinType::PseudoObject: + case BuiltinType::UnknownAny: + case BuiltinType::BuiltinFn: + case BuiltinType::ARCUnbridgedCast: + zig_panic("TODO - make error for these types"); + } + break; + } + case Type::Pointer: + { + const PointerType *pointer_ty = static_cast(ty); + AstNode *type_node = type_node_from_qual_type(c, pointer_ty->getPointeeType()); + return pointer_to_type(c, type_node, is_const); + } + case Type::Typedef: + case Type::FunctionProto: + case Type::Record: + case Type::Enum: + case Type::BlockPointer: + case Type::LValueReference: + case Type::RValueReference: + case Type::MemberPointer: + case Type::ConstantArray: + 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::Paren: + case Type::Adjusted: + case Type::Decayed: + case Type::TypeOfExpr: + case Type::TypeOf: + case Type::Decltype: + case Type::UnaryTransform: + case Type::Elaborated: + case Type::Attributed: + 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: + zig_panic("TODO - make error for type: %s", ty->getTypeClassName()); + } +} + +static AstNode *type_node_from_qual_type(Context *c, QualType qt) { + bool is_const = qt.isConstQualified(); + return type_node(c, qt.getTypePtr(), is_const); +} + +static bool decl_visitor(void *context, const Decl *decl) { + Context *c = (Context*)context; + + switch (decl->getKind()) { + case Decl::Function: + { + const FunctionDecl *fn_decl = static_cast(decl); + AstNode *node = create_node(c, NodeTypeFnProto); + node->data.fn_proto.is_extern = true; + node->data.fn_proto.visib_mod = c->pub ? VisibModPub : VisibModPrivate; + node->data.fn_proto.is_var_args = fn_decl->isVariadic(); + buf_init_from_str(&node->data.fn_proto.name, decl_name(decl)); + + int arg_count = fn_decl->getNumParams(); + for (int i = 0; i < arg_count; i += 1) { + const ParmVarDecl *param = fn_decl->getParamDecl(i); + AstNode *param_decl_node = create_node(c, NodeTypeParamDecl); + const char *name = decl_name(param); + if (strlen(name) == 0) { + name = buf_ptr(buf_sprintf("arg%d", i)); + } + buf_init_from_str(¶m_decl_node->data.param_decl.name, name); + QualType qt = param->getOriginalType(); + param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified(); + param_decl_node->data.param_decl.type = type_node_from_qual_type(c, qt); + node->data.fn_proto.params.append(param_decl_node); + } + + if (fn_decl->isNoReturn()) { + node->data.fn_proto.return_type = simple_type_node(c, "unreachable"); + } else { + node->data.fn_proto.return_type = type_node_from_qual_type(c, fn_decl->getReturnType()); + } + + c->parse_h->fn_list.append(node); + + break; + } + default: + if (c->warnings_on) { + fprintf(stderr, "ignoring %s\n", decl->getDeclKindName()); + } + } return true; } @@ -46,7 +236,6 @@ int parse_h_buf(ParseH *parse_h, Buf *source, const char *libc_include_path) { os_delete_file(&tmp_file_path); return err; - // write to temp file, parse it, delete it } int parse_h_file(ParseH *parse_h, ZigList *clang_argv) { @@ -124,7 +313,7 @@ int parse_h_file(ParseH *parse_h, ZigList *clang_argv) { } StringRef msg_str_ref = it->getMessage(); FullSourceLoc fsl = it->getLocation(); - FileID file_id = fsl.getManager().getFileID(fsl); + FileID file_id = fsl.getFileID(); StringRef filename = fsl.getManager().getFilename(fsl); unsigned line = fsl.getSpellingLineNumber() - 1; unsigned column = fsl.getSpellingColumnNumber() - 1;