diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 242 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 119 | ||||
| -rw-r--r-- | src/codegen/spirv.zig | 11 |
3 files changed, 206 insertions, 166 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index e6ec461e43..cd3974bc91 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1045,8 +1045,8 @@ pub const DeclGen = struct { if (!empty) try writer.writeByte(')'); return; }, - .Pointer => switch (val.tag()) { - .null_value, .zero => if (ty.isSlice(mod)) { + .Pointer => switch (val.ip_index) { + .null_value => if (ty.isSlice(mod)) { var slice_pl = Value.Payload.Slice{ .base = .{ .tag = .slice }, .data = .{ .ptr = val, .len = Value.undef }, @@ -1059,46 +1059,63 @@ pub const DeclGen = struct { try dg.renderType(writer, ty); try writer.writeAll(")NULL)"); }, - .variable => { - const decl = val.castTag(.variable).?.data.owner_decl; - return dg.renderDeclValue(writer, ty, val, decl, location); - }, - .slice => { - if (!location.isInitializer()) { - try writer.writeByte('('); + .none => switch (val.tag()) { + .zero => if (ty.isSlice(mod)) { + 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.renderType(writer, ty); - try writer.writeByte(')'); - } + try writer.writeAll(")NULL)"); + }, + .variable => { + const decl = val.castTag(.variable).?.data.owner_decl; + return dg.renderDeclValue(writer, ty, val, decl, location); + }, + .slice => { + if (!location.isInitializer()) { + try writer.writeByte('('); + try dg.renderType(writer, ty); + try writer.writeByte(')'); + } - const slice = val.castTag(.slice).?.data; - var buf: Type.SlicePtrFieldTypeBuffer = undefined; + const slice = val.castTag(.slice).?.data; + var buf: Type.SlicePtrFieldTypeBuffer = undefined; - try writer.writeByte('{'); - try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, initializer_type); - try writer.writeAll(", "); - try dg.renderValue(writer, Type.usize, slice.len, initializer_type); - try writer.writeByte('}'); - }, - .function => { - const func = val.castTag(.function).?.data; - try dg.renderDeclName(writer, func.owner_decl, 0); - }, - .extern_fn => { - const extern_fn = val.castTag(.extern_fn).?.data; - try dg.renderDeclName(writer, extern_fn.owner_decl, 0); - }, - .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { - try writer.writeAll("(("); - try dg.renderType(writer, ty); - return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); + try writer.writeByte('{'); + try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, initializer_type); + try writer.writeAll(", "); + try dg.renderValue(writer, Type.usize, slice.len, initializer_type); + try writer.writeByte('}'); + }, + .function => { + const func = val.castTag(.function).?.data; + try dg.renderDeclName(writer, func.owner_decl, 0); + }, + .extern_fn => { + const extern_fn = val.castTag(.extern_fn).?.data; + try dg.renderDeclName(writer, extern_fn.owner_decl, 0); + }, + .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { + try writer.writeAll("(("); + try dg.renderType(writer, ty); + return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); + }, + .field_ptr, + .elem_ptr, + .opt_payload_ptr, + .eu_payload_ptr, + .decl_ref_mut, + .decl_ref, + => try dg.renderParentPtr(writer, val, ty, location), + + else => unreachable, }, - .field_ptr, - .elem_ptr, - .opt_payload_ptr, - .eu_payload_ptr, - .decl_ref_mut, - .decl_ref, - => try dg.renderParentPtr(writer, val, ty, location), else => unreachable, }, .Array, .Vector => { @@ -1109,8 +1126,8 @@ pub const DeclGen = struct { } // First try specific tag representations for more efficiency. - switch (val.tag()) { - .undef, .empty_struct_value, .empty_array => { + switch (val.ip_index) { + .undef => { const ai = ty.arrayInfo(mod); try writer.writeByte('{'); if (ai.sentinel) |s| { @@ -1119,76 +1136,91 @@ pub const DeclGen = struct { try writer.writeByte('0'); } try writer.writeByte('}'); + return; }, - .bytes, .str_lit => |t| { - const bytes = switch (t) { - .bytes => val.castTag(.bytes).?.data, - .str_lit => bytes: { - const str_lit = val.castTag(.str_lit).?.data; - break :bytes dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; - }, - else => unreachable, - }; - const sentinel = if (ty.sentinel(mod)) |sentinel| @intCast(u8, sentinel.toUnsignedInt(mod)) else null; - try writer.print("{s}", .{ - fmtStringLiteral(bytes[0..@intCast(usize, ty.arrayLen(mod))], sentinel), - }); - }, - else => { - // Fall back to generic implementation. - var arena = std.heap.ArenaAllocator.init(dg.gpa); - defer arena.deinit(); - const arena_allocator = arena.allocator(); - - // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal - const max_string_initializer_len = 65535; - - const ai = ty.arrayInfo(mod); - if (ai.elem_type.eql(Type.u8, dg.module)) { - if (ai.len <= max_string_initializer_len) { - var literal = stringLiteral(writer); - try literal.start(); - var index: usize = 0; - while (index < ai.len) : (index += 1) { - const elem_val = try val.elemValue(dg.module, arena_allocator, index); - const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); - try literal.writeChar(elem_val_u8); - } - if (ai.sentinel) |s| { - const s_u8 = @intCast(u8, s.toUnsignedInt(mod)); - if (s_u8 != 0) try literal.writeChar(s_u8); - } - try literal.end(); - } else { - try writer.writeByte('{'); - var index: usize = 0; - while (index < ai.len) : (index += 1) { - if (index != 0) try writer.writeByte(','); - const elem_val = try val.elemValue(dg.module, arena_allocator, index); - const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); - try writer.print("'\\x{x}'", .{elem_val_u8}); - } - if (ai.sentinel) |s| { - if (index != 0) try writer.writeByte(','); - try dg.renderValue(writer, ai.elem_type, s, initializer_type); - } - try writer.writeByte('}'); - } - } else { + .none => switch (val.tag()) { + .empty_struct_value, .empty_array => { + const ai = ty.arrayInfo(mod); try writer.writeByte('{'); - var index: usize = 0; - while (index < ai.len) : (index += 1) { - if (index != 0) try writer.writeByte(','); - const elem_val = try val.elemValue(dg.module, arena_allocator, index); - try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type); - } if (ai.sentinel) |s| { - if (index != 0) try writer.writeByte(','); try dg.renderValue(writer, ai.elem_type, s, initializer_type); + } else { + try writer.writeByte('0'); } try writer.writeByte('}'); - } + return; + }, + .bytes, .str_lit => |t| { + const bytes = switch (t) { + .bytes => val.castTag(.bytes).?.data, + .str_lit => bytes: { + const str_lit = val.castTag(.str_lit).?.data; + break :bytes dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; + }, + else => unreachable, + }; + const sentinel = if (ty.sentinel(mod)) |sentinel| @intCast(u8, sentinel.toUnsignedInt(mod)) else null; + try writer.print("{s}", .{ + fmtStringLiteral(bytes[0..@intCast(usize, ty.arrayLen(mod))], sentinel), + }); + return; + }, + else => {}, }, + else => {}, + } + // Fall back to generic implementation. + var arena = std.heap.ArenaAllocator.init(dg.gpa); + defer arena.deinit(); + const arena_allocator = arena.allocator(); + + // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal + const max_string_initializer_len = 65535; + + const ai = ty.arrayInfo(mod); + if (ai.elem_type.eql(Type.u8, dg.module)) { + if (ai.len <= max_string_initializer_len) { + var literal = stringLiteral(writer); + try literal.start(); + var index: usize = 0; + while (index < ai.len) : (index += 1) { + const elem_val = try val.elemValue(dg.module, arena_allocator, index); + const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); + try literal.writeChar(elem_val_u8); + } + if (ai.sentinel) |s| { + const s_u8 = @intCast(u8, s.toUnsignedInt(mod)); + if (s_u8 != 0) try literal.writeChar(s_u8); + } + try literal.end(); + } else { + try writer.writeByte('{'); + var index: usize = 0; + while (index < ai.len) : (index += 1) { + if (index != 0) try writer.writeByte(','); + const elem_val = try val.elemValue(dg.module, arena_allocator, index); + const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); + try writer.print("'\\x{x}'", .{elem_val_u8}); + } + if (ai.sentinel) |s| { + if (index != 0) try writer.writeByte(','); + try dg.renderValue(writer, ai.elem_type, s, initializer_type); + } + try writer.writeByte('}'); + } + } else { + try writer.writeByte('{'); + var index: usize = 0; + while (index < ai.len) : (index += 1) { + if (index != 0) try writer.writeByte(','); + const elem_val = try val.elemValue(dg.module, arena_allocator, index); + try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type); + } + if (ai.sentinel) |s| { + if (index != 0) try writer.writeByte(','); + try dg.renderValue(writer, ai.elem_type, s, initializer_type); + } + try writer.writeByte('}'); } }, .Bool => { @@ -1201,7 +1233,7 @@ pub const DeclGen = struct { .Optional => { const payload_ty = ty.optionalChild(mod); - const is_null_val = Value.makeBool(val.tag() == .null_value); + const is_null_val = Value.makeBool(val.ip_index == .null_value); if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return dg.renderValue(writer, Type.bool, is_null_val, location); @@ -7765,7 +7797,7 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *const Module) T if (lowersToArray(ret_ty, mod)) { buffer.names = [1][]const u8{"array"}; buffer.types = [1]Type{ret_ty}; - buffer.values = [1]Value{Value.initTag(.unreachable_value)}; + buffer.values = [1]Value{Value.@"unreachable"}; buffer.payload = .{ .data = .{ .names = &buffer.names, .types = &buffer.types, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index f45a63df72..558534a651 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2028,7 +2028,7 @@ pub const Object = struct { for (tuple.types, 0..) |field_ty, i| { const field_val = tuple.values[i]; - if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; + if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; const field_size = field_ty.abiSize(mod); const field_align = field_ty.abiAlignment(mod); @@ -2498,7 +2498,7 @@ pub const DeclGen = struct { global.setGlobalConstant(.True); break :init_val decl.val; }; - if (init_val.tag() != .unreachable_value) { + if (init_val.ip_index != .unreachable_value) { const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val }); if (global.globalGetValueType() == llvm_init.typeOf()) { global.setInitializer(llvm_init); @@ -2954,7 +2954,7 @@ pub const DeclGen = struct { for (tuple.types, 0..) |field_ty, i| { const field_val = tuple.values[i]; - if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; + if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; const field_align = field_ty.abiAlignment(mod); big_align = @max(big_align, field_align); @@ -3359,58 +3359,65 @@ pub const DeclGen = struct { else => unreachable, } }, - .Pointer => switch (tv.val.tag()) { - .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index), - .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), - .variable => { - const decl_index = tv.val.castTag(.variable).?.data.owner_decl; - const decl = dg.module.declPtr(decl_index); - dg.module.markDeclAlive(decl); - - const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); - const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); - - const val = try dg.resolveGlobalDecl(decl_index); - const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace) - val.constAddrSpaceCast(dg.context.pointerType(llvm_wanted_addrspace)) - else - val; - return addrspace_casted_ptr; - }, - .slice => { - const slice = tv.val.castTag(.slice).?.data; - var buf: Type.SlicePtrFieldTypeBuffer = undefined; - const fields: [2]*llvm.Value = .{ - try dg.lowerValue(.{ - .ty = tv.ty.slicePtrFieldType(&buf), - .val = slice.ptr, - }), - try dg.lowerValue(.{ - .ty = Type.usize, - .val = slice.len, - }), - }; - return dg.context.constStruct(&fields, fields.len, .False); - }, - .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { - const llvm_usize = try dg.lowerType(Type.usize); - const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(mod), .False); - return llvm_int.constIntToPtr(try dg.lowerType(tv.ty)); - }, - .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => { - return dg.lowerParentPtr(tv.val, tv.ty.ptrInfo(mod).bit_offset % 8 == 0); - }, - .null_value, .zero => { + .Pointer => switch (tv.val.ip_index) { + .null_value => { const llvm_type = try dg.lowerType(tv.ty); return llvm_type.constNull(); }, - .opt_payload => { - const payload = tv.val.castTag(.opt_payload).?.data; - return dg.lowerParentPtr(payload, tv.ty.ptrInfo(mod).bit_offset % 8 == 0); + .none => switch (tv.val.tag()) { + .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index), + .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), + .variable => { + const decl_index = tv.val.castTag(.variable).?.data.owner_decl; + const decl = dg.module.declPtr(decl_index); + dg.module.markDeclAlive(decl); + + const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); + const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); + + const val = try dg.resolveGlobalDecl(decl_index); + const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace) + val.constAddrSpaceCast(dg.context.pointerType(llvm_wanted_addrspace)) + else + val; + return addrspace_casted_ptr; + }, + .slice => { + const slice = tv.val.castTag(.slice).?.data; + var buf: Type.SlicePtrFieldTypeBuffer = undefined; + const fields: [2]*llvm.Value = .{ + try dg.lowerValue(.{ + .ty = tv.ty.slicePtrFieldType(&buf), + .val = slice.ptr, + }), + try dg.lowerValue(.{ + .ty = Type.usize, + .val = slice.len, + }), + }; + return dg.context.constStruct(&fields, fields.len, .False); + }, + .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { + const llvm_usize = try dg.lowerType(Type.usize); + const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(mod), .False); + return llvm_int.constIntToPtr(try dg.lowerType(tv.ty)); + }, + .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => { + return dg.lowerParentPtr(tv.val, tv.ty.ptrInfo(mod).bit_offset % 8 == 0); + }, + .zero => { + const llvm_type = try dg.lowerType(tv.ty); + return llvm_type.constNull(); + }, + .opt_payload => { + const payload = tv.val.castTag(.opt_payload).?.data; + return dg.lowerParentPtr(payload, tv.ty.ptrInfo(mod).bit_offset % 8 == 0); + }, + else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ + tv.ty.fmtDebug(), tag, + }), }, - else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ - tv.ty.fmtDebug(), tag, - }), + else => unreachable, }, .Array => switch (tv.val.tag()) { .bytes => { @@ -3555,7 +3562,7 @@ pub const DeclGen = struct { var fields_buf: [3]*llvm.Value = undefined; fields_buf[0] = try dg.lowerValue(.{ .ty = payload_ty, - .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef), + .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.undef, }); fields_buf[1] = non_null_bit; if (llvm_field_count > 2) { @@ -3606,7 +3613,7 @@ pub const DeclGen = struct { }); const llvm_payload_value = try dg.lowerValue(.{ .ty = payload_type, - .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef), + .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.undef, }); var fields_buf: [3]*llvm.Value = undefined; @@ -3645,7 +3652,7 @@ pub const DeclGen = struct { var need_unnamed = false; for (tuple.types, 0..) |field_ty, i| { - if (tuple.values[i].tag() != .unreachable_value) continue; + if (tuple.values[i].ip_index != .unreachable_value) continue; if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; const field_align = field_ty.abiAlignment(mod); @@ -10501,7 +10508,7 @@ fn llvmFieldIndex( const tuple = ty.tupleFields(); var llvm_field_index: c_uint = 0; for (tuple.types, 0..) |field_ty, i| { - if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; + if (tuple.values[i].ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; const field_align = field_ty.abiAlignment(mod); big_align = @max(big_align, field_align); @@ -11117,7 +11124,7 @@ fn isByRef(ty: Type, mod: *const Module) bool { const tuple = ty.tupleFields(); var count: usize = 0; for (tuple.values, 0..) |field_val, i| { - if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits(mod)) continue; + if (field_val.ip_index != .unreachable_value or !tuple.types[i].hasRuntimeBits(mod)) continue; count += 1; if (count > max_fields_byval) return true; diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 9de2c03142..5fa81d19ff 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -674,7 +674,7 @@ pub const DeclGen = struct { try self.lower(ptr_ty, slice.ptr); try self.addInt(Type.usize, slice.len); }, - .null_value, .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)), + .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)), .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { try self.addInt(Type.usize, val); }, @@ -813,7 +813,8 @@ pub const DeclGen = struct { const error_size = Type.anyerror.abiAlignment(mod); const ty_size = ty.abiSize(mod); const padding = ty_size - payload_size - error_size; - const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); + + const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef; if (eu_layout.error_first) { try self.lower(Type.anyerror, error_val); @@ -1021,7 +1022,7 @@ pub const DeclGen = struct { return try self.constant(Type.anyerror, error_val, repr); } - const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); + const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef; var members: [2]IdRef = undefined; if (eu_layout.error_first) { @@ -1292,7 +1293,7 @@ pub const DeclGen = struct { var member_index: usize = 0; for (tuple.types, 0..) |field_ty, i| { const field_val = tuple.values[i]; - if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; + if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; member_types[member_index] = try self.resolveType(field_ty, .indirect); member_index += 1; @@ -1596,7 +1597,7 @@ pub const DeclGen = struct { else decl.val; - if (init_val.tag() == .unreachable_value) { + if (init_val.ip_index == .unreachable_value) { return self.todo("importing extern variables", .{}); } |
