aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig242
-rw-r--r--src/codegen/llvm.zig119
-rw-r--r--src/codegen/spirv.zig11
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", .{});
}