aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-20 21:45:11 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-20 21:45:11 -0700
commita0e195120dd3dd7919fd249a6ce2201da9395898 (patch)
tree1f06851929602eb29932c60418e774f0cb1cab03 /src/codegen/c.zig
parent3b2e25ed8718d8aee085497886967fa21a9697cc (diff)
downloadzig-a0e195120dd3dd7919fd249a6ce2201da9395898.tar.gz
zig-a0e195120dd3dd7919fd249a6ce2201da9395898.zip
stage2: implement slicing
* New AIR instruction: slice, which constructs a slice out of a pointer and a length. * AstGen: use `coerced_ty` for start and end expressions, use `none` for the sentinel, and don't try to load the result of the slice operation because it returns a by-value result. * Sema: pointer arithmetic is extracted into analyzePointerArithmetic and it is used by the implementation of slice. - Also I implemented comptime pointer addition. * Sema: extract logic into analyzeSlicePtr, analyzeSliceLen and use them inside the slice semantic analysis. - The approach in stage2 is much cleaner than stage1 because it uses more granular analysis calls for obtaining the slice pointer, doing arithmetic on it, and checking if the length is comptime-known. * Sema: use the slice Value Tag for slices when doing coercion from pointer-to-array. * LLVM backend: detect when emitting a GEP instruction into a pointer-to-array and add the extra index that is required. * Type: ptrAlignment for c_void returns 0. * Implement Value.hash and Value.eql for slices. * Remove accidentally duplicated behavior test.
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 1bb337743d..6e03de1cca 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -992,6 +992,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.min => try airMinMax(f, inst, "<"),
.max => try airMinMax(f, inst, ">"),
+ .slice => try airSlice(f, inst),
+
.cmp_eq => try airBinOp(f, inst, " == "),
.cmp_gt => try airBinOp(f, inst, " > "),
.cmp_gte => try airBinOp(f, inst, " >= "),
@@ -1104,8 +1106,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
}
fn airSliceField(f: *Function, inst: Air.Inst.Index, suffix: []const u8) !CValue {
- if (f.liveness.isUnused(inst))
- return CValue.none;
+ if (f.liveness.isUnused(inst)) return CValue.none;
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const operand = try f.resolveInst(ty_op.operand);
@@ -1641,6 +1642,26 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValu
return local;
}
+fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
+ if (f.liveness.isUnused(inst)) return CValue.none;
+
+ const bin_op = f.air.instructions.items(.data)[inst].bin_op;
+ const ptr = try f.resolveInst(bin_op.lhs);
+ const len = try f.resolveInst(bin_op.rhs);
+
+ const writer = f.object.writer();
+ const inst_ty = f.air.typeOfIndex(inst);
+ const local = try f.allocLocal(inst_ty, .Const);
+
+ try writer.writeAll(" = {");
+ try f.writeCValue(writer, ptr);
+ try writer.writeAll(", ");
+ try f.writeCValue(writer, len);
+ try writer.writeAll("};\n");
+
+ return local;
+}
+
fn airCall(f: *Function, inst: Air.Inst.Index) !CValue {
const pl_op = f.air.instructions.items(.data)[inst].pl_op;
const extra = f.air.extraData(Air.Call, pl_op.payload);