diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-09-13 21:37:11 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-09-13 21:37:11 -0700 |
| commit | 97d69e3352ab50f88580c383b5f375b0edadacfd (patch) | |
| tree | 8245d3d55b3304c19ca18238a01d6532031e1ff8 /src/codegen | |
| parent | a9a21c59888905e060915dee818633110cc54cfa (diff) | |
| download | zig-97d69e3352ab50f88580c383b5f375b0edadacfd.tar.gz zig-97d69e3352ab50f88580c383b5f375b0edadacfd.zip | |
stage2: add array_to_slice AIR instruction
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 18 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 63 | ||||
| -rw-r--r-- | src/codegen/llvm/bindings.zig | 9 |
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) { |
