| ... | @@ -22,9 +22,10 @@ struct Context { | ... | @@ -22,9 +22,10 @@ struct Context { |
| 22 | bool warnings_on; | 22 | bool warnings_on; |
| 23 | VisibMod visib_mod; | 23 | VisibMod visib_mod; |
| 24 | AstNode *c_void_decl_node; | 24 | AstNode *c_void_decl_node; |
| | 25 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table; |
| 25 | }; | 26 | }; |
| 26 | | 27 | |
| 27 | static AstNode *type_node_from_qual_type(Context *c, QualType qt); | 28 | static AstNode *make_qual_type_node(Context *c, QualType qt); |
| 28 | | 29 | |
| 29 | static AstNode *create_node(Context *c, NodeType type) { | 30 | static AstNode *create_node(Context *c, NodeType type) { |
| 30 | AstNode *node = allocate<AstNode>(1); | 31 | AstNode *node = allocate<AstNode>(1); |
| ... | @@ -43,12 +44,16 @@ static const char *decl_name(const Decl *decl) { | ... | @@ -43,12 +44,16 @@ static const char *decl_name(const Decl *decl) { |
| 43 | return (const char *)named_decl->getName().bytes_begin(); | 44 | return (const char *)named_decl->getName().bytes_begin(); |
| 44 | } | 45 | } |
| 45 | | 46 | |
| 46 | static AstNode *create_typedef_node(Context *c, const char *new_name, const char *target_name) { | 47 | static AstNode *create_typedef_node(Context *c, Buf *new_name, AstNode *target_node) { |
| | 48 | if (!target_node) { |
| | 49 | return nullptr; |
| | 50 | } |
| 47 | AstNode *node = create_node(c, NodeTypeVariableDeclaration); | 51 | AstNode *node = create_node(c, NodeTypeVariableDeclaration); |
| 48 | buf_init_from_str(&node->data.variable_declaration.symbol, new_name); | 52 | buf_init_from_buf(&node->data.variable_declaration.symbol, new_name); |
| 49 | node->data.variable_declaration.is_const = true; | 53 | node->data.variable_declaration.is_const = true; |
| 50 | node->data.variable_declaration.visib_mod = c->visib_mod; | 54 | node->data.variable_declaration.visib_mod = c->visib_mod; |
| 51 | node->data.variable_declaration.expr = simple_type_node(c, target_name); | 55 | node->data.variable_declaration.expr = target_node; |
| | 56 | c->parse_h->var_list.append(node); |
| 52 | return node; | 57 | return node; |
| 53 | } | 58 | } |
| 54 | | 59 | |
| ... | @@ -57,8 +62,9 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) { | ... | @@ -57,8 +62,9 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) { |
| 57 | buf_eql_str(&type_node->data.symbol_expr.symbol, "void")) | 62 | buf_eql_str(&type_node->data.symbol_expr.symbol, "void")) |
| 58 | { | 63 | { |
| 59 | if (!c->c_void_decl_node) { | 64 | if (!c->c_void_decl_node) { |
| 60 | c->c_void_decl_node = create_typedef_node(c, "c_void", "u8"); | 65 | c->c_void_decl_node = create_typedef_node(c, buf_create_from_str("c_void"), |
| 61 | c->parse_h->var_list.append(c->c_void_decl_node); | 66 | simple_type_node(c, "u8")); |
| | 67 | assert(c->c_void_decl_node); |
| 62 | } | 68 | } |
| 63 | return simple_type_node(c, "c_void"); | 69 | return simple_type_node(c, "c_void"); |
| 64 | } else { | 70 | } else { |
| ... | @@ -67,13 +73,16 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) { | ... | @@ -67,13 +73,16 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) { |
| 67 | } | 73 | } |
| 68 | | 74 | |
| 69 | static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { | 75 | static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { |
| | 76 | if (!type_node) { |
| | 77 | return nullptr; |
| | 78 | } |
| 70 | AstNode *node = create_node(c, NodeTypePrefixOpExpr); | 79 | AstNode *node = create_node(c, NodeTypePrefixOpExpr); |
| 71 | node->data.prefix_op_expr.prefix_op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf; | 80 | node->data.prefix_op_expr.prefix_op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf; |
| 72 | node->data.prefix_op_expr.primary_expr = convert_to_c_void(c, type_node); | 81 | node->data.prefix_op_expr.primary_expr = convert_to_c_void(c, type_node); |
| 73 | return node; | 82 | return node; |
| 74 | } | 83 | } |
| 75 | | 84 | |
| 76 | static AstNode *type_node(Context *c, const Type *ty) { | 85 | static AstNode *make_type_node(Context *c, const Type *ty) { |
| 77 | switch (ty->getTypeClass()) { | 86 | switch (ty->getTypeClass()) { |
| 78 | case Type::Builtin: | 87 | case Type::Builtin: |
| 79 | { | 88 | { |
| ... | @@ -110,7 +119,6 @@ static AstNode *type_node(Context *c, const Type *ty) { | ... | @@ -110,7 +119,6 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 110 | case BuiltinType::Double: | 119 | case BuiltinType::Double: |
| 111 | return simple_type_node(c, "f64"); | 120 | return simple_type_node(c, "f64"); |
| 112 | case BuiltinType::LongDouble: | 121 | case BuiltinType::LongDouble: |
| 113 | return simple_type_node(c, "f128"); | | |
| 114 | case BuiltinType::WChar_U: | 122 | case BuiltinType::WChar_U: |
| 115 | case BuiltinType::Char16: | 123 | case BuiltinType::Char16: |
| 116 | case BuiltinType::Char32: | 124 | case BuiltinType::Char32: |
| ... | @@ -137,7 +145,10 @@ static AstNode *type_node(Context *c, const Type *ty) { | ... | @@ -137,7 +145,10 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 137 | case BuiltinType::UnknownAny: | 145 | case BuiltinType::UnknownAny: |
| 138 | case BuiltinType::BuiltinFn: | 146 | case BuiltinType::BuiltinFn: |
| 139 | case BuiltinType::ARCUnbridgedCast: | 147 | case BuiltinType::ARCUnbridgedCast: |
| 140 | zig_panic("TODO - make error for these types"); | 148 | if (c->warnings_on) { |
| | 149 | fprintf(stderr, "missed a builtin type\n"); |
| | 150 | } |
| | 151 | return nullptr; |
| 141 | } | 152 | } |
| 142 | break; | 153 | break; |
| 143 | } | 154 | } |
| ... | @@ -145,17 +156,53 @@ static AstNode *type_node(Context *c, const Type *ty) { | ... | @@ -145,17 +156,53 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 145 | { | 156 | { |
| 146 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | 157 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); |
| 147 | QualType child_qt = pointer_ty->getPointeeType(); | 158 | QualType child_qt = pointer_ty->getPointeeType(); |
| 148 | AstNode *type_node = type_node_from_qual_type(c, child_qt); | 159 | AstNode *type_node = make_qual_type_node(c, child_qt); |
| 149 | return pointer_to_type(c, type_node, child_qt.isConstQualified()); | 160 | return pointer_to_type(c, type_node, child_qt.isConstQualified()); |
| 150 | } | 161 | } |
| 151 | case Type::Typedef: | 162 | case Type::Typedef: |
| 152 | { | 163 | { |
| 153 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | 164 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); |
| 154 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | 165 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); |
| 155 | const char *type_name = buf_ptr(buf_create_from_str(decl_name(typedef_decl))); | 166 | Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); |
| 156 | return simple_type_node(c, type_name); | 167 | if (buf_eql_str(type_name, "uint8_t")) { |
| | 168 | return simple_type_node(c, "u8"); |
| | 169 | } else if (buf_eql_str(type_name, "int8_t")) { |
| | 170 | return simple_type_node(c, "i8"); |
| | 171 | } else if (buf_eql_str(type_name, "uint16_t")) { |
| | 172 | return simple_type_node(c, "u16"); |
| | 173 | } else if (buf_eql_str(type_name, "int16_t")) { |
| | 174 | return simple_type_node(c, "i16"); |
| | 175 | } else if (buf_eql_str(type_name, "uint32_t")) { |
| | 176 | return simple_type_node(c, "u32"); |
| | 177 | } else if (buf_eql_str(type_name, "int32_t")) { |
| | 178 | return simple_type_node(c, "i32"); |
| | 179 | } else if (buf_eql_str(type_name, "uint64_t")) { |
| | 180 | return simple_type_node(c, "u64"); |
| | 181 | } else if (buf_eql_str(type_name, "int64_t")) { |
| | 182 | return simple_type_node(c, "i64"); |
| | 183 | } else if (buf_eql_str(type_name, "intptr_t")) { |
| | 184 | return simple_type_node(c, "isize"); |
| | 185 | } else if (buf_eql_str(type_name, "uintptr_t")) { |
| | 186 | return simple_type_node(c, "usize"); |
| | 187 | } else { |
| | 188 | auto entry = c->type_table.maybe_get(type_name); |
| | 189 | if (entry) { |
| | 190 | return simple_type_node(c, buf_ptr(type_name)); |
| | 191 | } else { |
| | 192 | return nullptr; |
| | 193 | } |
| | 194 | } |
| 157 | } | 195 | } |
| | 196 | case Type::Elaborated: |
| | 197 | if (c->warnings_on) { |
| | 198 | fprintf(stderr, "ignoring elaborated type\n"); |
| | 199 | } |
| | 200 | return nullptr; |
| 158 | case Type::FunctionProto: | 201 | case Type::FunctionProto: |
| | 202 | if (c->warnings_on) { |
| | 203 | fprintf(stderr, "ignoring function type\n"); |
| | 204 | } |
| | 205 | return nullptr; |
| 159 | case Type::Record: | 206 | case Type::Record: |
| 160 | case Type::Enum: | 207 | case Type::Enum: |
| 161 | case Type::BlockPointer: | 208 | case Type::BlockPointer: |
| ... | @@ -178,7 +225,6 @@ static AstNode *type_node(Context *c, const Type *ty) { | ... | @@ -178,7 +225,6 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 178 | case Type::TypeOf: | 225 | case Type::TypeOf: |
| 179 | case Type::Decltype: | 226 | case Type::Decltype: |
| 180 | case Type::UnaryTransform: | 227 | case Type::UnaryTransform: |
| 181 | case Type::Elaborated: | | |
| 182 | case Type::Attributed: | 228 | case Type::Attributed: |
| 183 | case Type::TemplateTypeParm: | 229 | case Type::TemplateTypeParm: |
| 184 | case Type::SubstTemplateTypeParm: | 230 | case Type::SubstTemplateTypeParm: |
| ... | @@ -194,12 +240,90 @@ static AstNode *type_node(Context *c, const Type *ty) { | ... | @@ -194,12 +240,90 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 194 | case Type::Complex: | 240 | case Type::Complex: |
| 195 | case Type::ObjCObjectPointer: | 241 | case Type::ObjCObjectPointer: |
| 196 | case Type::Atomic: | 242 | case Type::Atomic: |
| 197 | zig_panic("TODO - make error for type: %s", ty->getTypeClassName()); | 243 | if (c->warnings_on) { |
| | 244 | fprintf(stderr, "missed a '%s' type\n", ty->getTypeClassName()); |
| | 245 | } |
| | 246 | return nullptr; |
| 198 | } | 247 | } |
| 199 | } | 248 | } |
| 200 | | 249 | |
| 201 | static AstNode *type_node_from_qual_type(Context *c, QualType qt) { | 250 | static AstNode *make_qual_type_node(Context *c, QualType qt) { |
| 202 | return type_node(c, qt.getTypePtr()); | 251 | return make_type_node(c, qt.getTypePtr()); |
| | 252 | } |
| | 253 | |
| | 254 | static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| | 255 | AstNode *node = create_node(c, NodeTypeFnProto); |
| | 256 | node->data.fn_proto.is_extern = true; |
| | 257 | node->data.fn_proto.visib_mod = c->visib_mod; |
| | 258 | node->data.fn_proto.is_var_args = fn_decl->isVariadic(); |
| | 259 | buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl)); |
| | 260 | |
| | 261 | int arg_count = fn_decl->getNumParams(); |
| | 262 | bool all_ok = true; |
| | 263 | for (int i = 0; i < arg_count; i += 1) { |
| | 264 | const ParmVarDecl *param = fn_decl->getParamDecl(i); |
| | 265 | AstNode *param_decl_node = create_node(c, NodeTypeParamDecl); |
| | 266 | const char *name = decl_name(param); |
| | 267 | if (strlen(name) == 0) { |
| | 268 | name = buf_ptr(buf_sprintf("arg%d", i)); |
| | 269 | } |
| | 270 | buf_init_from_str(&param_decl_node->data.param_decl.name, name); |
| | 271 | QualType qt = param->getOriginalType(); |
| | 272 | param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified(); |
| | 273 | param_decl_node->data.param_decl.type = make_qual_type_node(c, qt); |
| | 274 | if (!param_decl_node->data.param_decl.type) { |
| | 275 | all_ok = false; |
| | 276 | break; |
| | 277 | } |
| | 278 | |
| | 279 | node->data.fn_proto.params.append(param_decl_node); |
| | 280 | } |
| | 281 | |
| | 282 | if (fn_decl->isNoReturn()) { |
| | 283 | node->data.fn_proto.return_type = simple_type_node(c, "unreachable"); |
| | 284 | } else { |
| | 285 | node->data.fn_proto.return_type = make_qual_type_node(c, fn_decl->getReturnType()); |
| | 286 | } |
| | 287 | |
| | 288 | if (!node->data.fn_proto.return_type) { |
| | 289 | all_ok = false; |
| | 290 | } |
| | 291 | if (!all_ok) { |
| | 292 | // not all the types could be resolved, so we give up on the function decl |
| | 293 | if (c->warnings_on) { |
| | 294 | fprintf(stderr, "skipping function %s", buf_ptr(&node->data.fn_proto.name)); |
| | 295 | } |
| | 296 | return; |
| | 297 | } |
| | 298 | |
| | 299 | c->parse_h->fn_list.append(node); |
| | 300 | |
| | 301 | } |
| | 302 | |
| | 303 | static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) { |
| | 304 | QualType child_qt = typedef_decl->getUnderlyingType(); |
| | 305 | Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); |
| | 306 | |
| | 307 | if (buf_eql_str(type_name, "uint8_t") || |
| | 308 | buf_eql_str(type_name, "int8_t") || |
| | 309 | buf_eql_str(type_name, "uint16_t") || |
| | 310 | buf_eql_str(type_name, "int16_t") || |
| | 311 | buf_eql_str(type_name, "uint32_t") || |
| | 312 | buf_eql_str(type_name, "int32_t") || |
| | 313 | buf_eql_str(type_name, "uint64_t") || |
| | 314 | buf_eql_str(type_name, "int64_t") || |
| | 315 | buf_eql_str(type_name, "intptr_t") || |
| | 316 | buf_eql_str(type_name, "uintptr_t")) |
| | 317 | { |
| | 318 | // special case we can just use the builtin types |
| | 319 | return; |
| | 320 | } |
| | 321 | |
| | 322 | AstNode *node = create_typedef_node(c, type_name, make_qual_type_node(c, child_qt)); |
| | 323 | |
| | 324 | if (node) { |
| | 325 | c->type_table.put(type_name, true); |
| | 326 | } |
| 203 | } | 327 | } |
| 204 | | 328 | |
| 205 | static bool decl_visitor(void *context, const Decl *decl) { | 329 | static bool decl_visitor(void *context, const Decl *decl) { |
| ... | @@ -207,49 +331,11 @@ static bool decl_visitor(void *context, const Decl *decl) { | ... | @@ -207,49 +331,11 @@ static bool decl_visitor(void *context, const Decl *decl) { |
| 207 | | 331 | |
| 208 | switch (decl->getKind()) { | 332 | switch (decl->getKind()) { |
| 209 | case Decl::Function: | 333 | case Decl::Function: |
| 210 | { | 334 | visit_fn_decl(c, static_cast<const FunctionDecl*>(decl)); |
| 211 | const FunctionDecl *fn_decl = static_cast<const FunctionDecl*>(decl); | 335 | break; |
| 212 | AstNode *node = create_node(c, NodeTypeFnProto); | | |
| 213 | node->data.fn_proto.is_extern = true; | | |
| 214 | node->data.fn_proto.visib_mod = c->visib_mod; | | |
| 215 | node->data.fn_proto.is_var_args = fn_decl->isVariadic(); | | |
| 216 | buf_init_from_str(&node->data.fn_proto.name, decl_name(decl)); | | |
| 217 | | | |
| 218 | int arg_count = fn_decl->getNumParams(); | | |
| 219 | for (int i = 0; i < arg_count; i += 1) { | | |
| 220 | const ParmVarDecl *param = fn_decl->getParamDecl(i); | | |
| 221 | AstNode *param_decl_node = create_node(c, NodeTypeParamDecl); | | |
| 222 | const char *name = decl_name(param); | | |
| 223 | if (strlen(name) == 0) { | | |
| 224 | name = buf_ptr(buf_sprintf("arg%d", i)); | | |
| 225 | } | | |
| 226 | buf_init_from_str(&param_decl_node->data.param_decl.name, name); | | |
| 227 | QualType qt = param->getOriginalType(); | | |
| 228 | param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified(); | | |
| 229 | param_decl_node->data.param_decl.type = type_node_from_qual_type(c, qt); | | |
| 230 | node->data.fn_proto.params.append(param_decl_node); | | |
| 231 | } | | |
| 232 | | | |
| 233 | if (fn_decl->isNoReturn()) { | | |
| 234 | node->data.fn_proto.return_type = simple_type_node(c, "unreachable"); | | |
| 235 | } else { | | |
| 236 | node->data.fn_proto.return_type = type_node_from_qual_type(c, fn_decl->getReturnType()); | | |
| 237 | } | | |
| 238 | | | |
| 239 | c->parse_h->fn_list.append(node); | | |
| 240 | | | |
| 241 | break; | | |
| 242 | } | | |
| 243 | /* | | |
| 244 | case Decl::Typedef: | 336 | case Decl::Typedef: |
| 245 | { | 337 | visit_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl)); |
| 246 | AstNode *node = create_node(c, NodeTypeVariableDeclaration); | 338 | break; |
| 247 | node->data.variable_declaration.is_const = true; | | |
| 248 | buf_init_from_str(&node->data.variable_declaration.symbol, decl_name(decl)); | | |
| 249 | | | |
| 250 | break; | | |
| 251 | } | | |
| 252 | */ | | |
| 253 | default: | 339 | default: |
| 254 | if (c->warnings_on) { | 340 | if (c->warnings_on) { |
| 255 | fprintf(stderr, "ignoring %s\n", decl->getDeclKindName()); | 341 | fprintf(stderr, "ignoring %s\n", decl->getDeclKindName()); |
| ... | @@ -282,6 +368,7 @@ int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv) { | ... | @@ -282,6 +368,7 @@ int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv) { |
| 282 | Context context = {0}; | 368 | Context context = {0}; |
| 283 | Context *c = &context; | 369 | Context *c = &context; |
| 284 | c->parse_h = parse_h; | 370 | c->parse_h = parse_h; |
| | 371 | c->type_table.init(64); |
| 285 | | 372 | |
| 286 | char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS"); | 373 | char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS"); |
| 287 | if (ZIG_PARSEH_CFLAGS) { | 374 | if (ZIG_PARSEH_CFLAGS) { |