aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Compilation.zig4
-rw-r--r--src/main.zig7
-rw-r--r--src/translate_c.zig45
3 files changed, 46 insertions, 10 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index cffda8f36e..dec98ed781 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -3305,7 +3305,10 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
var man = comp.obtainCObjectCacheManifest();
defer man.deinit();
+ const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;
+
man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
+ man.hash.add(use_stage1);
man.hash.addBytes(c_src);
// If the previous invocation resulted in clang errors, we will see a hit
@@ -3369,6 +3372,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
new_argv.ptr + new_argv.len,
&clang_errors,
c_headers_dir_path_z,
+ use_stage1,
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.ASTUnitFailure => {
diff --git a/src/main.zig b/src/main.zig
index 64a478c813..3f74a64c36 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -2601,7 +2601,8 @@ fn buildOutputType(
return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));
}
if (arg_mode == .translate_c) {
- return cmdTranslateC(comp, arena, have_enable_cache);
+ const stage1_mode = use_stage1 orelse build_options.is_stage1;
+ return cmdTranslateC(comp, arena, have_enable_cache, stage1_mode);
}
const hook: AfterUpdateHook = blk: {
@@ -2997,7 +2998,7 @@ fn freePkgTree(gpa: Allocator, pkg: *Package, free_parent: bool) void {
}
}
-fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool) !void {
+fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool, stage1_mode: bool) !void {
if (!build_options.have_llvm)
fatal("cannot translate-c: compiler built without LLVM extensions", .{});
@@ -3010,6 +3011,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool) !void
defer if (enable_cache) man.deinit();
man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
+ man.hash.add(stage1_mode);
man.hashCSource(c_source_file) catch |err| {
fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });
};
@@ -3061,6 +3063,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool) !void
new_argv.ptr + new_argv.len,
&clang_errors,
c_headers_dir_path_z,
+ stage1_mode,
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.ASTUnitFailure => fatal("clang API returned errors but due to a clang bug, it is not exposing the errors for zig to see. For more details: https://github.com/ziglang/zig/issues/4455", .{}),
diff --git a/src/translate_c.zig b/src/translate_c.zig
index d550f7a7aa..eecbe63102 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -328,6 +328,16 @@ pub const Context = struct {
pattern_list: PatternList,
+ /// This is used to emit different code depending on whether
+ /// the output zig source code is intended to be compiled with stage1 or stage2.
+ /// Ideally we will have stage1 and stage2 support the exact same Zig language,
+ /// but for now they diverge because I would rather focus on finishing and shipping
+ /// stage2 than implementing the features in stage1.
+ /// The list of differences are currently:
+ /// * function pointers in stage1 are e.g. `fn()void`
+ /// but in stage2 they are `*const fn()void`.
+ zig_is_stage1: bool,
+
fn getMangle(c: *Context) u32 {
c.mangle_count += 1;
return c.mangle_count;
@@ -356,6 +366,7 @@ pub fn translate(
args_end: [*]?[*]const u8,
errors: *[]ClangErrMsg,
resources_path: [*:0]const u8,
+ zig_is_stage1: bool,
) !std.zig.Ast {
const ast_unit = clang.LoadFromCommandLine(
args_begin,
@@ -383,6 +394,7 @@ pub fn translate(
.global_scope = try arena_allocator.create(Scope.Root),
.clang_context = ast_unit.getASTContext(),
.pattern_list = try PatternList.init(gpa),
+ .zig_is_stage1 = zig_is_stage1,
};
context.global_scope.* = Scope.Root.init(&context);
defer {
@@ -3630,7 +3642,7 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
else
return transCreatePreCrement(c, scope, stmt, .sub_assign, used),
.AddrOf => {
- if (cIsFunctionDeclRef(op_expr)) {
+ if (c.zig_is_stage1 and cIsFunctionDeclRef(op_expr)) {
return transExpr(c, scope, op_expr, used);
}
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
},
.Pointer => {
const child_qt = ty.getPointeeType();
- if (qualTypeChildIsFnProto(child_qt)) {
+ const is_fn_proto = qualTypeChildIsFnProto(child_qt);
+ if (c.zig_is_stage1 and is_fn_proto) {
return Tag.optional_type.create(c.arena, try transQualType(c, scope, child_qt, source_loc));
}
- const is_const = child_qt.isConstQualified();
+ const is_const = is_fn_proto or child_qt.isConstQualified();
const is_volatile = child_qt.isVolatileQualified();
const elem_type = try transQualType(c, scope, child_qt, source_loc);
- if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) {
- const ptr = try Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
+ const ptr_info = .{
+ .is_const = is_const,
+ .is_volatile = is_volatile,
+ .elem_type = elem_type,
+ };
+ if (is_fn_proto or
+ typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or
+ qualTypeWasDemotedToOpaque(c, child_qt))
+ {
+ const ptr = try Tag.single_pointer.create(c.arena, ptr_info);
return Tag.optional_type.create(c.arena, ptr);
}
- return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
+ return Tag.c_pointer.create(c.arena, ptr_info);
},
.ConstantArray => {
const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);
@@ -6517,8 +6538,16 @@ fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func {
return null;
if (getContainerTypeOf(c, init)) |ty_node| {
if (ty_node.castTag(.optional_type)) |prefix| {
- if (prefix.data.castTag(.func)) |fn_proto| {
- return fn_proto;
+ if (c.zig_is_stage1) {
+ if (prefix.data.castTag(.func)) |fn_proto| {
+ return fn_proto;
+ }
+ } else {
+ if (prefix.data.castTag(.single_pointer)) |sp| {
+ if (sp.data.elem_type.castTag(.func)) |fn_proto| {
+ return fn_proto;
+ }
+ }
}
}
}