| ... | ... | @@ -328,6 +328,16 @@ pub const Context = struct { |
| 328 | 328 | |
| 329 | 329 | pattern_list: PatternList, |
| 330 | 330 | |
| 331 | /// This is used to emit different code depending on whether |
| 332 | /// the output zig source code is intended to be compiled with stage1 or stage2. |
| 333 | /// Ideally we will have stage1 and stage2 support the exact same Zig language, |
| 334 | /// but for now they diverge because I would rather focus on finishing and shipping |
| 335 | /// stage2 than implementing the features in stage1. |
| 336 | /// The list of differences are currently: |
| 337 | /// * function pointers in stage1 are e.g. `fn()void` |
| 338 | /// but in stage2 they are `*const fn()void`. |
| 339 | zig_is_stage1: bool, |
| 340 | |
| 331 | 341 | fn getMangle(c: *Context) u32 { |
| 332 | 342 | c.mangle_count += 1; |
| 333 | 343 | return c.mangle_count; |
| ... | ... | @@ -356,6 +366,7 @@ pub fn translate( |
| 356 | 366 | args_end: [*]?[*]const u8, |
| 357 | 367 | errors: *[]ClangErrMsg, |
| 358 | 368 | resources_path: [*:0]const u8, |
| 369 | zig_is_stage1: bool, |
| 359 | 370 | ) !std.zig.Ast { |
| 360 | 371 | const ast_unit = clang.LoadFromCommandLine( |
| 361 | 372 | args_begin, |
| ... | ... | @@ -383,6 +394,7 @@ pub fn translate( |
| 383 | 394 | .global_scope = try arena_allocator.create(Scope.Root), |
| 384 | 395 | .clang_context = ast_unit.getASTContext(), |
| 385 | 396 | .pattern_list = try PatternList.init(gpa), |
| 397 | .zig_is_stage1 = zig_is_stage1, |
| 386 | 398 | }; |
| 387 | 399 | context.global_scope.* = Scope.Root.init(&context); |
| 388 | 400 | defer { |
| ... | ... | @@ -3630,7 +3642,7 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat |
| 3630 | 3642 | else |
| 3631 | 3643 | return transCreatePreCrement(c, scope, stmt, .sub_assign, used), |
| 3632 | 3644 | .AddrOf => { |
| 3633 | | if (cIsFunctionDeclRef(op_expr)) { |
| 3645 | if (c.zig_is_stage1 and cIsFunctionDeclRef(op_expr)) { |
| 3634 | 3646 | return transExpr(c, scope, op_expr, used); |
| 3635 | 3647 | } |
| 3636 | 3648 | return Tag.address_of.create(c.arena, try transExpr(c, scope, op_expr, used)); |
| ... | ... | @@ -4656,18 +4668,27 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan |
| 4656 | 4668 | }, |
| 4657 | 4669 | .Pointer => { |
| 4658 | 4670 | const child_qt = ty.getPointeeType(); |
| 4659 | | if (qualTypeChildIsFnProto(child_qt)) { |
| 4671 | const is_fn_proto = qualTypeChildIsFnProto(child_qt); |
| 4672 | if (c.zig_is_stage1 and is_fn_proto) { |
| 4660 | 4673 | return Tag.optional_type.create(c.arena, try transQualType(c, scope, child_qt, source_loc)); |
| 4661 | 4674 | } |
| 4662 | | const is_const = child_qt.isConstQualified(); |
| 4675 | const is_const = is_fn_proto or child_qt.isConstQualified(); |
| 4663 | 4676 | const is_volatile = child_qt.isVolatileQualified(); |
| 4664 | 4677 | const elem_type = try transQualType(c, scope, child_qt, source_loc); |
| 4665 | | if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) { |
| 4666 | | const ptr = try Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type }); |
| 4678 | const ptr_info = .{ |
| 4679 | .is_const = is_const, |
| 4680 | .is_volatile = is_volatile, |
| 4681 | .elem_type = elem_type, |
| 4682 | }; |
| 4683 | if (is_fn_proto or |
| 4684 | typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or |
| 4685 | qualTypeWasDemotedToOpaque(c, child_qt)) |
| 4686 | { |
| 4687 | const ptr = try Tag.single_pointer.create(c.arena, ptr_info); |
| 4667 | 4688 | return Tag.optional_type.create(c.arena, ptr); |
| 4668 | 4689 | } |
| 4669 | 4690 | |
| 4670 | | return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type }); |
| 4691 | return Tag.c_pointer.create(c.arena, ptr_info); |
| 4671 | 4692 | }, |
| 4672 | 4693 | .ConstantArray => { |
| 4673 | 4694 | const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty); |
| ... | ... | @@ -6517,8 +6538,16 @@ fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func { |
| 6517 | 6538 | return null; |
| 6518 | 6539 | if (getContainerTypeOf(c, init)) |ty_node| { |
| 6519 | 6540 | if (ty_node.castTag(.optional_type)) |prefix| { |
| 6520 | | if (prefix.data.castTag(.func)) |fn_proto| { |
| 6521 | | return fn_proto; |
| 6541 | if (c.zig_is_stage1) { |
| 6542 | if (prefix.data.castTag(.func)) |fn_proto| { |
| 6543 | return fn_proto; |
| 6544 | } |
| 6545 | } else { |
| 6546 | if (prefix.data.castTag(.single_pointer)) |sp| { |
| 6547 | if (sp.data.elem_type.castTag(.func)) |fn_proto| { |
| 6548 | return fn_proto; |
| 6549 | } |
| 6550 | } |
| 6522 | 6551 | } |
| 6523 | 6552 | } |
| 6524 | 6553 | } |