aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-01-14 00:23:27 -0500
committerGitHub <noreply@github.com>2022-01-14 00:23:27 -0500
commitec58ddf46c4e1ac060333c6d0780955acae22442 (patch)
tree16b1f97c8962817dccdcc90ffbd7169bb8171ef7 /src/codegen/c.zig
parent0d45c72d3e4f38029a453443ae6a34c398f5c530 (diff)
parent336d0c97feabad4c93525ba6ef73a6b6163f49c7 (diff)
downloadzig-ec58ddf46c4e1ac060333c6d0780955acae22442.tar.gz
zig-ec58ddf46c4e1ac060333c6d0780955acae22442.zip
Merge pull request #10582 from ziglang/stage2-arrays
stage2: detection of comptime array literals
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig76
1 files changed, 64 insertions, 12 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 05ec1b1a88..58bf919b1f 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -44,7 +44,7 @@ const BlockData = struct {
result: CValue,
};
-pub const CValueMap = std.AutoHashMap(Air.Inst.Index, CValue);
+pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);
pub const TypedefMap = std.ArrayHashMap(
Type,
struct { name: []const u8, rendered: []u8 },
@@ -110,11 +110,29 @@ pub const Function = struct {
func: *Module.Fn,
fn resolveInst(f: *Function, inst: Air.Inst.Ref) !CValue {
- if (f.air.value(inst)) |_| {
- return CValue{ .constant = inst };
+ const gop = try f.value_map.getOrPut(inst);
+ if (gop.found_existing) return gop.value_ptr.*;
+
+ const val = f.air.value(inst).?;
+ const ty = f.air.typeOf(inst);
+ switch (ty.zigTypeTag()) {
+ .Array => {
+ const writer = f.object.code_header.writer();
+ const decl_c_value = f.allocLocalValue();
+ gop.value_ptr.* = decl_c_value;
+ try writer.writeAll("static ");
+ try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const);
+ try writer.writeAll(" = ");
+ try f.object.dg.renderValue(writer, ty, val);
+ try writer.writeAll(";\n ");
+ return decl_c_value;
+ },
+ else => {
+ const result = CValue{ .constant = inst };
+ gop.value_ptr.* = result;
+ return result;
+ },
}
- const index = Air.refToIndex(inst).?;
- return f.value_map.get(index).?; // Assertion means instruction does not dominate usage.
}
fn allocLocalValue(f: *Function) CValue {
@@ -154,6 +172,8 @@ pub const Function = struct {
pub const Object = struct {
dg: DeclGen,
code: std.ArrayList(u8),
+ /// Goes before code. Initialized and deinitialized in `genFunc`.
+ code_header: std.ArrayList(u8) = undefined,
indent_writer: IndentWriter(std.ArrayList(u8).Writer),
fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer {
@@ -218,12 +238,18 @@ pub const DeclGen = struct {
// Determine if we must pointer cast.
if (ty.eql(decl.ty)) {
try writer.writeByte('&');
- } else {
- try writer.writeAll("(");
- try dg.renderType(writer, ty);
- try writer.writeAll(")&");
+ try dg.renderDeclName(decl, writer);
+ return;
}
+
+ try writer.writeAll("((");
+ try dg.renderType(writer, ty);
+ try writer.writeAll(")&");
+ try dg.renderDeclName(decl, writer);
+ try writer.writeByte(')');
+ return;
}
+
try dg.renderDeclName(decl, writer);
}
@@ -1010,6 +1036,10 @@ pub fn genFunc(f: *Function) !void {
defer tracy.end();
const o = &f.object;
+
+ o.code_header = std.ArrayList(u8).init(f.object.dg.gpa);
+ defer o.code_header.deinit();
+
const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl);
const fwd_decl_writer = o.dg.fwd_decl.writer();
if (is_global) {
@@ -1020,12 +1050,26 @@ pub fn genFunc(f: *Function) !void {
try o.indent_writer.insertNewline();
try o.dg.renderFunctionSignature(o.writer(), is_global);
-
try o.writer().writeByte(' ');
+
+ // In case we need to use the header, populate it with a copy of the function
+ // signature here. We anticipate a brace, newline, and space.
+ try o.code_header.ensureUnusedCapacity(o.code.items.len + 3);
+ o.code_header.appendSliceAssumeCapacity(o.code.items);
+ o.code_header.appendSliceAssumeCapacity("{\n ");
+ const empty_header_len = o.code_header.items.len;
+
const main_body = f.air.getMainBody();
try genBody(f, main_body);
try o.indent_writer.insertNewline();
+
+ // If we have a header to insert, append the body to the header
+ // and then return the result, freeing the body.
+ if (o.code_header.items.len > empty_header_len) {
+ try o.code_header.appendSlice(o.code.items[empty_header_len..]);
+ mem.swap(std.ArrayList(u8), &o.code, &o.code_header);
+ }
}
pub fn genDecl(o: *Object) !void {
@@ -1289,7 +1333,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
};
switch (result_value) {
.none => {},
- else => try f.value_map.putNoClobber(inst, result_value),
+ else => try f.value_map.putNoClobber(Air.indexToRef(inst), result_value),
}
}
@@ -2189,7 +2233,15 @@ fn airCall(f: *Function, inst: Air.Inst.Index) !CValue {
fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
const dbg_stmt = f.air.instructions.items(.data)[inst].dbg_stmt;
const writer = f.object.writer();
- try writer.print("#line {d}\n", .{dbg_stmt.line + 1});
+ // TODO re-evaluate whether to emit these or not. If we naively emit
+ // these directives, the output file will report bogus line numbers because
+ // every newline after the #line directive adds one to the line.
+ // We also don't print the filename yet, so the output is strictly unhelpful.
+ // If we wanted to go this route, we would need to go all the way and not output
+ // newlines until the next dbg_stmt occurs.
+ // Perhaps an additional compilation option is in order?
+ //try writer.print("#line {d}\n", .{dbg_stmt.line + 1});
+ try writer.print("/* file:{d}:{d} */\n", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
return CValue.none;
}