aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-03-02 20:04:53 +0100
committerGitHub <noreply@github.com>2022-03-02 20:04:53 +0100
commitaa867c7dbe6576f61f957667fef769030aff7c69 (patch)
tree1afb2b62fbefe367a329ead59c266428ead66738 /src/codegen.zig
parent7cfc3f0cfa626abe25c8318a7852977cbc1c723b (diff)
parent77072d1a1785f389c3c9918c6d7c6179ac2e43f4 (diff)
downloadzig-aa867c7dbe6576f61f957667fef769030aff7c69.tar.gz
zig-aa867c7dbe6576f61f957667fef769030aff7c69.zip
Merge pull request #11036 from ziglang/x64-optionals
x64: handle more optional types
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig100
1 files changed, 87 insertions, 13 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 6220970003..f0cf8da3b3 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -140,6 +140,16 @@ pub fn generateFunction(
}
}
+fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian, code: []u8) void {
+ _ = target;
+ const Int = @Type(.{ .Int = .{
+ .signedness = .unsigned,
+ .bits = @typeInfo(F).Float.bits,
+ } });
+ const int = @bitCast(Int, f);
+ mem.writeInt(Int, code[0..@sizeOf(Int)], int, endian);
+}
+
pub fn generateSymbol(
bin_file: *link.File,
src_loc: Module.SrcLoc,
@@ -151,10 +161,12 @@ pub fn generateSymbol(
const tracy = trace(@src());
defer tracy.end();
+ const target = bin_file.options.target;
+ const endian = target.cpu.arch.endian();
+
log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val });
if (typed_value.val.isUndefDeep()) {
- const target = bin_file.options.target;
const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
try code.appendNTimes(0xaa, abi_size);
return Result{ .appended = {} };
@@ -171,6 +183,25 @@ pub fn generateSymbol(
),
};
},
+ .Float => {
+ const float_bits = typed_value.ty.floatBits(target);
+ switch (float_bits) {
+ 16 => writeFloat(f16, typed_value.val.toFloat(f16), target, endian, try code.addManyAsArray(2)),
+ 32 => writeFloat(f32, typed_value.val.toFloat(f32), target, endian, try code.addManyAsArray(4)),
+ 64 => writeFloat(f64, typed_value.val.toFloat(f64), target, endian, try code.addManyAsArray(8)),
+ 80 => return Result{
+ .fail = try ErrorMsg.create(
+ bin_file.allocator,
+ src_loc,
+ "TODO handle f80 in generateSymbol",
+ .{},
+ ),
+ },
+ 128 => writeFloat(f128, typed_value.val.toFloat(f128), target, endian, try code.addManyAsArray(16)),
+ else => unreachable,
+ }
+ return Result{ .appended = {} };
+ },
.Array => switch (typed_value.val.tag()) {
.bytes => {
// TODO populate .debug_info for the array
@@ -311,7 +342,6 @@ pub fn generateSymbol(
return Result{ .appended = {} };
},
.field_ptr => {
- const target = bin_file.options.target;
const field_ptr = typed_value.val.castTag(.field_ptr).?.data;
const container_ptr = field_ptr.container_ptr;
@@ -373,7 +403,6 @@ pub fn generateSymbol(
},
.Int => {
// TODO populate .debug_info for the integer
- const endian = bin_file.options.target.cpu.arch.endian();
const info = typed_value.ty.intInfo(bin_file.options.target);
if (info.bits <= 8) {
const x = @intCast(u8, typed_value.val.toUnsignedInt());
@@ -423,7 +452,6 @@ pub fn generateSymbol(
var int_buffer: Value.Payload.U64 = undefined;
const int_val = typed_value.enumToInt(&int_buffer);
- const target = bin_file.options.target;
const info = typed_value.ty.intInfo(target);
if (info.bits <= 8) {
const x = @intCast(u8, int_val.toUnsignedInt());
@@ -440,7 +468,6 @@ pub fn generateSymbol(
),
};
}
- const endian = target.cpu.arch.endian();
switch (info.signedness) {
.unsigned => {
if (info.bits <= 16) {
@@ -506,7 +533,6 @@ pub fn generateSymbol(
const unpadded_field_end = code.items.len - struct_begin;
// Pad struct members if required
- const target = bin_file.options.target;
const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target);
const padding = try math.cast(usize, padded_field_end - unpadded_field_end);
@@ -519,7 +545,6 @@ pub fn generateSymbol(
},
.Union => {
// TODO generate debug info for unions
- const target = bin_file.options.target;
const union_obj = typed_value.val.castTag(.@"union").?.data;
const layout = typed_value.ty.unionGetLayout(target);
@@ -590,19 +615,69 @@ pub fn generateSymbol(
return Result{ .appended = {} };
},
.Optional => {
- // TODO generateSymbol for optionals
- const target = bin_file.options.target;
+ // TODO generate debug info for optionals
+ var opt_buf: Type.Payload.ElemType = undefined;
+ const payload_type = typed_value.ty.optionalChild(&opt_buf);
+ const is_pl = !typed_value.val.isNull();
const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
- try code.writer().writeByteNTimes(0xaa, abi_size);
+ const offset = abi_size - try math.cast(usize, payload_type.abiSize(target));
+
+ if (!payload_type.hasRuntimeBits()) {
+ try code.writer().writeByteNTimes(@boolToInt(is_pl), abi_size);
+ return Result{ .appended = {} };
+ }
+
+ if (typed_value.ty.isPtrLikeOptional()) {
+ if (typed_value.val.castTag(.opt_payload)) |payload| {
+ switch (try generateSymbol(bin_file, src_loc, .{
+ .ty = payload_type,
+ .val = payload.data,
+ }, code, debug_output, reloc_info)) {
+ .appended => {},
+ .externally_managed => |external_slice| {
+ code.appendSliceAssumeCapacity(external_slice);
+ },
+ .fail => |em| return Result{ .fail = em },
+ }
+ } else if (!typed_value.val.isNull()) {
+ switch (try generateSymbol(bin_file, src_loc, .{
+ .ty = payload_type,
+ .val = typed_value.val,
+ }, code, debug_output, reloc_info)) {
+ .appended => {},
+ .externally_managed => |external_slice| {
+ code.appendSliceAssumeCapacity(external_slice);
+ },
+ .fail => |em| return Result{ .fail = em },
+ }
+ } else {
+ try code.writer().writeByteNTimes(0, abi_size);
+ }
+
+ return Result{ .appended = {} };
+ }
+
+ const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef);
+ try code.writer().writeByteNTimes(@boolToInt(is_pl), offset);
+ switch (try generateSymbol(bin_file, src_loc, .{
+ .ty = payload_type,
+ .val = value,
+ }, code, debug_output, reloc_info)) {
+ .appended => {},
+ .externally_managed => |external_slice| {
+ code.appendSliceAssumeCapacity(external_slice);
+ },
+ .fail => |em| return Result{ .fail = em },
+ }
return Result{ .appended = {} };
},
.ErrorUnion => {
+ // TODO generate debug info for error unions
const error_ty = typed_value.ty.errorUnionSet();
const payload_ty = typed_value.ty.errorUnionPayload();
const is_payload = typed_value.val.errorUnionIsPayload();
- const target = bin_file.options.target;
const abi_align = typed_value.ty.abiAlignment(target);
const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
@@ -643,12 +718,11 @@ pub fn generateSymbol(
return Result{ .appended = {} };
},
.ErrorSet => {
- const target = bin_file.options.target;
+ // TODO generate debug info for error sets
switch (typed_value.val.tag()) {
.@"error" => {
const name = typed_value.val.getError().?;
const kv = try bin_file.options.module.?.getErrorValue(name);
- const endian = target.cpu.arch.endian();
try code.writer().writeInt(u32, kv.value, endian);
},
else => {