aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-07-26 19:12:34 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-07-26 19:27:49 -0700
commit31a59c229cb39b9ffd1ee3397a1ce87c36b91477 (patch)
treef4074655750f90c6350a8f3070343da9a724ccfd /src/codegen/c.zig
parentcdeea3b0943b070d49d8d8d0855f9a38843e3ecc (diff)
downloadzig-31a59c229cb39b9ffd1ee3397a1ce87c36b91477.tar.gz
zig-31a59c229cb39b9ffd1ee3397a1ce87c36b91477.zip
stage2: improvements towards `zig test`
* Add AIR instruction: struct_field_val - This is part of an effort to eliminate the AIR instruction `ref`. - It's implemented for C backend and LLVM backend so far. * Rename `resolvePossiblyUndefinedValue` to `resolveMaybeUndefVal` just to save some columns on long lines. * Sema: add `fieldVal` alongside `fieldPtr` (renamed from `namedFieldPtr`). This is part of an effort to eliminate the AIR instruction `ref`. The idea is to avoid unnecessary loads, stores, stack usage, and IR instructions, by paying a DRY cost. LLVM backend improvements: * internal linkage vs exported linkage is implemented, along with aliases. There is an issue with incremental updates due to missing LLVM API for deleting aliases; see the relevant comment in this commit. - `updateDeclExports` is hooked up to the LLVM backend now. * Fix usage of `Type.tag() == .noreturn` rather than calling `isNoReturn()`. * Properly mark global variables as mutable/constant. * Fix llvm type generation of function pointers * Fix codegen for calls of function pointers * Implement llvm type generation of error unions and error sets. * Implement AIR instructions: addwrap, subwrap, mul, mulwrap, div, bit_and, bool_and, bit_or, bool_or, xor, struct_field_ptr, struct_field_val, unwrap_errunion_err, add for floats, sub for floats. After this commit, `zig test` on a file with `test "example" {}` correctly generates and executes a test binary. However the `test_functions` slice is undefined and just happens to be going into the .bss section, causing the length to be 0. The next step towards `zig test` will be replacing the `test_functions` Decl Value with the set of test function pointers, before it is sent to linker/codegen.
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 705c5c2ad1..fa254af293 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -935,6 +935,7 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
.wrap_optional => try airWrapOptional(o, inst),
.ref => try airRef(o, inst),
.struct_field_ptr => try airStructFieldPtr(o, inst),
+ .struct_field_val => try airStructFieldVal(o, inst),
.varptr => try airVarPtr(o, inst),
.slice_ptr => try airSliceField(o, inst, ".ptr;\n"),
.slice_len => try airSliceField(o, inst, ".len;\n"),
@@ -1660,8 +1661,8 @@ fn airStructFieldPtr(o: *Object, inst: Air.Inst.Index) !CValue {
const ty_pl = o.air.instructions.items(.data)[inst].ty_pl;
const extra = o.air.extraData(Air.StructField, ty_pl.payload).data;
const writer = o.writer();
- const struct_ptr = try o.resolveInst(extra.struct_ptr);
- const struct_ptr_ty = o.air.typeOf(extra.struct_ptr);
+ const struct_ptr = try o.resolveInst(extra.struct_operand);
+ const struct_ptr_ty = o.air.typeOf(extra.struct_operand);
const struct_obj = struct_ptr_ty.elemType().castTag(.@"struct").?.data;
const field_name = struct_obj.fields.keys()[extra.field_index];
@@ -1680,6 +1681,26 @@ fn airStructFieldPtr(o: *Object, inst: Air.Inst.Index) !CValue {
return local;
}
+fn airStructFieldVal(o: *Object, inst: Air.Inst.Index) !CValue {
+ if (o.liveness.isUnused(inst))
+ return CValue.none;
+
+ const ty_pl = o.air.instructions.items(.data)[inst].ty_pl;
+ const extra = o.air.extraData(Air.StructField, ty_pl.payload).data;
+ const writer = o.writer();
+ const struct_byval = try o.resolveInst(extra.struct_operand);
+ const struct_ty = o.air.typeOf(extra.struct_operand);
+ const struct_obj = struct_ty.castTag(.@"struct").?.data;
+ const field_name = struct_obj.fields.keys()[extra.field_index];
+
+ const inst_ty = o.air.typeOfIndex(inst);
+ const local = try o.allocLocal(inst_ty, .Const);
+ try writer.writeAll(" = ");
+ try o.writeCValue(writer, struct_byval);
+ try writer.print(".{};\n", .{fmtIdent(field_name)});
+ return local;
+}
+
// *(E!T) -> E NOT *E
fn airUnwrapErrUnionErr(o: *Object, inst: Air.Inst.Index) !CValue {
if (o.liveness.isUnused(inst))