aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-09-13 21:37:11 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-09-13 21:37:11 -0700
commit97d69e3352ab50f88580c383b5f375b0edadacfd (patch)
tree8245d3d55b3304c19ca18238a01d6532031e1ff8 /src/codegen
parenta9a21c59888905e060915dee818633110cc54cfa (diff)
downloadzig-97d69e3352ab50f88580c383b5f375b0edadacfd.tar.gz
zig-97d69e3352ab50f88580c383b5f375b0edadacfd.zip
stage2: add array_to_slice AIR instruction
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig18
-rw-r--r--src/codegen/llvm.zig63
-rw-r--r--src/codegen/llvm/bindings.zig9
3 files changed, 68 insertions, 22 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index fd964f2829..84bc6ceeb0 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -910,6 +910,7 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
.switch_br => try airSwitchBr(o, inst),
.wrap_optional => try airWrapOptional(o, inst),
.struct_field_ptr => try airStructFieldPtr(o, inst),
+ .array_to_slice => try airArrayToSlice(o, inst),
.struct_field_ptr_index_0 => try airStructFieldPtrIndex(o, inst, 0),
.struct_field_ptr_index_1 => try airStructFieldPtrIndex(o, inst, 1),
@@ -1860,6 +1861,23 @@ fn airIsErr(
return local;
}
+fn airArrayToSlice(o: *Object, inst: Air.Inst.Index) !CValue {
+ if (o.liveness.isUnused(inst))
+ return CValue.none;
+
+ const inst_ty = o.air.typeOfIndex(inst);
+ const local = try o.allocLocal(inst_ty, .Const);
+ const ty_op = o.air.instructions.items(.data)[inst].ty_op;
+ const writer = o.writer();
+ const operand = try o.resolveInst(ty_op.operand);
+ const array_len = o.air.typeOf(ty_op.operand).elemType().arrayLen();
+
+ try writer.writeAll(" = { .ptr = ");
+ try o.writeCValue(writer, operand);
+ try writer.print(", .len = {d} }};\n", .{array_len});
+ return local;
+}
+
fn IndentWriter(comptime UnderlyingWriter: type) type {
return struct {
const Self = @This();
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 8b7fd5dc54..d39262d62e 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1006,28 +1006,29 @@ pub const FuncGen = struct {
.is_err => try self.airIsErr(inst, .NE, false),
.is_err_ptr => try self.airIsErr(inst, .NE, true),
- .alloc => try self.airAlloc(inst),
- .arg => try self.airArg(inst),
- .bitcast => try self.airBitCast(inst),
- .bool_to_int=> try self.airBoolToInt(inst),
- .block => try self.airBlock(inst),
- .br => try self.airBr(inst),
- .switch_br => try self.airSwitchBr(inst),
- .breakpoint => try self.airBreakpoint(inst),
- .call => try self.airCall(inst),
- .cond_br => try self.airCondBr(inst),
- .intcast => try self.airIntCast(inst),
- .trunc => try self.airTrunc(inst),
- .floatcast => try self.airFloatCast(inst),
- .ptrtoint => try self.airPtrToInt(inst),
- .load => try self.airLoad(inst),
- .loop => try self.airLoop(inst),
- .not => try self.airNot(inst),
- .ret => try self.airRet(inst),
- .store => try self.airStore(inst),
- .assembly => try self.airAssembly(inst),
- .slice_ptr => try self.airSliceField(inst, 0),
- .slice_len => try self.airSliceField(inst, 1),
+ .alloc => try self.airAlloc(inst),
+ .arg => try self.airArg(inst),
+ .bitcast => try self.airBitCast(inst),
+ .bool_to_int => try self.airBoolToInt(inst),
+ .block => try self.airBlock(inst),
+ .br => try self.airBr(inst),
+ .switch_br => try self.airSwitchBr(inst),
+ .breakpoint => try self.airBreakpoint(inst),
+ .call => try self.airCall(inst),
+ .cond_br => try self.airCondBr(inst),
+ .intcast => try self.airIntCast(inst),
+ .trunc => try self.airTrunc(inst),
+ .floatcast => try self.airFloatCast(inst),
+ .ptrtoint => try self.airPtrToInt(inst),
+ .load => try self.airLoad(inst),
+ .loop => try self.airLoop(inst),
+ .not => try self.airNot(inst),
+ .ret => try self.airRet(inst),
+ .store => try self.airStore(inst),
+ .assembly => try self.airAssembly(inst),
+ .slice_ptr => try self.airSliceField(inst, 0),
+ .slice_len => try self.airSliceField(inst, 1),
+ .array_to_slice => try self.airArrayToSlice(inst),
.struct_field_ptr => try self.airStructFieldPtr(inst),
.struct_field_val => try self.airStructFieldVal(inst),
@@ -1246,6 +1247,24 @@ pub const FuncGen = struct {
return null;
}
+ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const operand = try self.resolveInst(ty_op.operand);
+ const array_len = self.air.typeOf(ty_op.operand).elemType().arrayLen();
+ const usize_llvm_ty = try self.dg.llvmType(Type.initTag(.usize));
+ const len = usize_llvm_ty.constInt(array_len, .False);
+ const slice_llvm_ty = try self.dg.llvmType(self.air.typeOfIndex(inst));
+ const indices: [2]*const llvm.Value = .{
+ usize_llvm_ty.constNull(), usize_llvm_ty.constNull(),
+ };
+ const ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, "");
+ const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, "");
+ return self.builder.buildInsertValue(partial, len, 1, "");
+ }
+
fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index a10002b5d6..e0283be236 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -484,6 +484,15 @@ pub const Builder = opaque {
DestTy: *const Type,
Name: [*:0]const u8,
) *const Value;
+
+ pub const buildInsertValue = LLVMBuildInsertValue;
+ extern fn LLVMBuildInsertValue(
+ *const Builder,
+ AggVal: *const Value,
+ EltVal: *const Value,
+ Index: c_uint,
+ Name: [*:0]const u8,
+ ) *const Value;
};
pub const IntPredicate = enum(c_uint) {