diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 81 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 40 |
2 files changed, 75 insertions, 46 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 098424524f..83debd1af3 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -468,13 +468,10 @@ pub const DeclGen = struct { // // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type) error{ OutOfMemory, AnalysisFail }!void { - switch (ptr_ty.ptrSize()) { - .Slice => {}, - .Many, .C, .One => { - try writer.writeByte('('); - try dg.renderTypecast(writer, ptr_ty); - try writer.writeByte(')'); - }, + if (!ptr_ty.isSlice()) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ptr_ty); + try writer.writeByte(')'); } switch (ptr_val.tag()) { .decl_ref_mut, .decl_ref, .variable => { @@ -541,13 +538,13 @@ pub const DeclGen = struct { .name = container_ty.unionFields().keys()[index], .ty = container_ty.unionFields().values()[index].ty, }, - .Pointer => switch (container_ty.ptrSize()) { - .Slice => switch (index) { + .Pointer => field_info: { + assert(container_ty.isSlice()); + break :field_info switch (index) { 0 => FieldInfo{ .name = "ptr", .ty = container_ty.childType() }, 1 => FieldInfo{ .name = "len", .ty = Type.usize }, else => unreachable, - }, - else => unreachable, + }; }, else => unreachable, }; @@ -597,9 +594,13 @@ pub const DeclGen = struct { dg: *DeclGen, writer: anytype, ty: Type, - val: Value, + arg_val: Value, location: ValueRenderLocation, ) error{ OutOfMemory, AnalysisFail }!void { + var val = arg_val; + if (val.castTag(.runtime_value)) |rt| { + val = rt.data; + } const target = dg.module.getTarget(); if (val.isUndefDeep()) { switch (ty.zigTypeTag()) { @@ -622,25 +623,22 @@ pub const DeclGen = struct { } return writer.writeByte(')'); }, - .Pointer => switch (ty.ptrSize()) { - .Slice => { - if (location != .Initializer) { - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeByte(')'); - } - - try writer.writeAll("{("); - var buf: Type.SlicePtrFieldTypeBuffer = undefined; - const ptr_ty = ty.slicePtrFieldType(&buf); - try dg.renderTypecast(writer, ptr_ty); - return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val)}); - }, - .Many, .C, .One => { - try writer.writeAll("(("); + .Pointer => if (ty.isSlice()) { + if (location != .Initializer) { + try writer.writeByte('('); try dg.renderTypecast(writer, ty); - return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); - }, + try writer.writeByte(')'); + } + + try writer.writeAll("{("); + var buf: Type.SlicePtrFieldTypeBuffer = undefined; + const ptr_ty = ty.slicePtrFieldType(&buf); + try dg.renderTypecast(writer, ptr_ty); + return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val)}); + } else { + try writer.writeAll("(("); + try dg.renderTypecast(writer, ty); + return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); }, .Optional => { var opt_buf: Type.Payload.ElemType = undefined; @@ -817,7 +815,15 @@ pub const DeclGen = struct { return writer.writeByte(')'); }, .Pointer => switch (val.tag()) { - .null_value, .zero => { + .null_value, .zero => if (ty.isSlice()) { + var slice_pl = Value.Payload.Slice{ + .base = .{ .tag = .slice }, + .data = .{ .ptr = val, .len = Value.undef }, + }; + const slice_val = Value.initPayload(&slice_pl.base); + + return dg.renderValue(writer, ty, slice_val, location); + } else { try writer.writeAll("(("); try dg.renderTypecast(writer, ty); try writer.writeAll(")NULL)"); @@ -827,15 +833,15 @@ pub const DeclGen = struct { return dg.renderDeclValue(writer, ty, val, decl); }, .slice => { - const slice = val.castTag(.slice).?.data; - var buf: Type.SlicePtrFieldTypeBuffer = undefined; - if (location != .Initializer) { try writer.writeByte('('); try dg.renderTypecast(writer, ty); try writer.writeByte(')'); } + const slice = val.castTag(.slice).?.data; + var buf: Type.SlicePtrFieldTypeBuffer = undefined; + try writer.writeByte('{'); try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, .Initializer); try writer.writeAll(", "); @@ -3923,6 +3929,7 @@ fn airIsNull( const optional_ty = if (is_ptr) operand_ty.childType() else operand_ty; var payload_buf: Type.Payload.ElemType = undefined; const payload_ty = optional_ty.optionalChild(&payload_buf); + var slice_ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime()) TypedValue{ .ty = Type.bool, .val = Value.@"true" } @@ -3931,7 +3938,11 @@ fn airIsNull( TypedValue{ .ty = operand_ty, .val = Value.@"null" } else if (payload_ty.zigTypeTag() == .ErrorSet) TypedValue{ .ty = payload_ty, .val = Value.zero } - else rhs: { + else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload()) rhs: { + try writer.writeAll(".ptr"); + const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf); + break :rhs TypedValue{ .ty = slice_ptr_ty, .val = Value.@"null" }; + } else rhs: { try writer.writeAll(".is_null"); break :rhs TypedValue{ .ty = Type.bool, .val = Value.@"true" }; }; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index ffc19cb6f6..d92a444ea4 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1027,7 +1027,9 @@ pub const Object = struct { dg.addArgAttr(llvm_func, llvm_arg_i, "noalias"); } } - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); + if (param_ty.zigTypeTag() != .Optional) { + dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); + } if (!ptr_info.mutable) { dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); } @@ -1916,7 +1918,7 @@ pub const Object = struct { if (ty.castTag(.@"struct")) |payload| { const struct_obj = payload.data; - if (struct_obj.layout == .Packed) { + if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { const info = struct_obj.backing_int_ty.intInfo(target); const dwarf_encoding: c_uint = switch (info.signedness) { .signed => DW.ATE.signed, @@ -3117,7 +3119,11 @@ pub const DeclGen = struct { .slice => { const param_ty = fn_info.param_types[it.zig_index - 1]; var buf: Type.SlicePtrFieldTypeBuffer = undefined; - const ptr_ty = param_ty.slicePtrFieldType(&buf); + var opt_buf: Type.Payload.ElemType = undefined; + const ptr_ty = if (param_ty.zigTypeTag() == .Optional) + param_ty.optionalChild(&opt_buf).slicePtrFieldType(&buf) + else + param_ty.slicePtrFieldType(&buf); const ptr_llvm_ty = try dg.lowerType(ptr_ty); const len_llvm_ty = try dg.lowerType(Type.usize); @@ -3187,7 +3193,11 @@ pub const DeclGen = struct { return llvm_elem_ty; } - fn lowerValue(dg: *DeclGen, tv: TypedValue) Error!*llvm.Value { + fn lowerValue(dg: *DeclGen, arg_tv: TypedValue) Error!*llvm.Value { + var tv = arg_tv; + if (tv.val.castTag(.runtime_value)) |rt| { + tv.val = rt.data; + } if (tv.val.isUndef()) { const llvm_type = try dg.lowerType(tv.ty); return llvm_type.getUndef(); @@ -5434,10 +5444,11 @@ pub const FuncGen = struct { const llvm_usize = try self.dg.lowerType(Type.usize); const len = llvm_usize.constInt(array_ty.arrayLen(), .False); const slice_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); + const operand = try self.resolveInst(ty_op.operand); if (!array_ty.hasRuntimeBitsIgnoreComptime()) { - return self.builder.buildInsertValue(slice_llvm_ty.getUndef(), len, 1, ""); + const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, ""); + return self.builder.buildInsertValue(partial, len, 1, ""); } - const operand = try self.resolveInst(ty_op.operand); const indices: [2]*llvm.Value = .{ llvm_usize.constNull(), llvm_usize.constNull(), }; @@ -6316,18 +6327,24 @@ pub const FuncGen = struct { const operand_ty = self.air.typeOf(un_op); const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; const optional_llvm_ty = try self.dg.lowerType(optional_ty); + var buf: Type.Payload.ElemType = undefined; + const payload_ty = optional_ty.optionalChild(&buf); if (optional_ty.optionalReprIsPayload()) { const loaded = if (operand_is_ptr) self.builder.buildLoad(optional_llvm_ty, operand, "") else operand; + if (payload_ty.isSlice()) { + const slice_ptr = self.builder.buildExtractValue(loaded, 0, ""); + var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; + const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(&slice_buf)); + return self.builder.buildICmp(pred, slice_ptr, ptr_ty.constNull(), ""); + } return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), ""); } comptime assert(optional_layout_version == 3); - var buf: Type.Payload.ElemType = undefined; - const payload_ty = optional_ty.optionalChild(&buf); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { const loaded = if (operand_is_ptr) self.builder.buildLoad(optional_llvm_ty, operand, "") @@ -10351,7 +10368,8 @@ const ParamTypeIterator = struct { .Unspecified, .Inline => { it.zig_index += 1; it.llvm_index += 1; - if (ty.isSlice()) { + var buf: Type.Payload.ElemType = undefined; + if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) { return .slice; } else if (isByRef(ty)) { return .byref; @@ -10726,8 +10744,8 @@ fn backendSupportsF128(target: std.Target) bool { fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool { return switch (scalar_ty.tag()) { .f16 => backendSupportsF16(target), - .f80 => target.longDoubleIs(f80) and backendSupportsF80(target), - .f128 => target.longDoubleIs(f128) and backendSupportsF128(target), + .f80 => (CType.longdouble.sizeInBits(target) == 80) and backendSupportsF80(target), + .f128 => (CType.longdouble.sizeInBits(target) == 128) and backendSupportsF128(target), else => true, }; } |
