| ... | @@ -55,7 +55,7 @@ const BlockData = struct { | ... | @@ -55,7 +55,7 @@ const BlockData = struct { |
| 55 | result: CValue, | 55 | result: CValue, |
| 56 | }; | 56 | }; |
| 57 | | 57 | |
| 58 | pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue); | 58 | pub const CValueMap = std.AutoHashMap(Air.Inst.Index, CValue); |
| 59 | | 59 | |
| 60 | pub const LazyFnKey = union(enum) { | 60 | pub const LazyFnKey = union(enum) { |
| 61 | tag_name: Decl.Index, | 61 | tag_name: Decl.Index, |
| ... | @@ -289,29 +289,31 @@ pub const Function = struct { | ... | @@ -289,29 +289,31 @@ pub const Function = struct { |
| 289 | /// Needed for memory used by the keys of free_locals_map entries. | 289 | /// Needed for memory used by the keys of free_locals_map entries. |
| 290 | arena: std.heap.ArenaAllocator, | 290 | arena: std.heap.ArenaAllocator, |
| 291 | | 291 | |
| 292 | fn resolveInst(f: *Function, inst: Air.Inst.Ref) !CValue { | 292 | fn resolveInst(f: *Function, ref: Air.Inst.Ref) !CValue { |
| 293 | const gop = try f.value_map.getOrPut(inst); | 293 | if (Air.refToIndex(ref)) |inst| { |
| 294 | if (gop.found_existing) return gop.value_ptr.*; | 294 | const gop = try f.value_map.getOrPut(inst); |
| 295 | | 295 | if (gop.found_existing) return gop.value_ptr.*; |
| 296 | const val = f.air.value(inst).?; | | |
| 297 | const ty = f.air.typeOf(inst); | | |
| 298 | | | |
| 299 | const result: CValue = if (lowersToArray(ty, f.object.dg.module.getTarget())) result: { | | |
| 300 | const writer = f.object.code_header.writer(); | | |
| 301 | const alignment = 0; | | |
| 302 | const decl_c_value = try f.allocLocalValue(ty, alignment); | | |
| 303 | const gpa = f.object.dg.gpa; | | |
| 304 | try f.allocs.put(gpa, decl_c_value.new_local, true); | | |
| 305 | try writer.writeAll("static "); | | |
| 306 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete); | | |
| 307 | try writer.writeAll(" = "); | | |
| 308 | try f.object.dg.renderValue(writer, ty, val, .StaticInitializer); | | |
| 309 | try writer.writeAll(";\n "); | | |
| 310 | break :result decl_c_value; | | |
| 311 | } else .{ .constant = inst }; | | |
| 312 | | 296 | |
| 313 | gop.value_ptr.* = result; | 297 | const val = f.air.value(ref).?; |
| 314 | return result; | 298 | const ty = f.air.typeOf(ref); |
| | 299 | |
| | 300 | const result: CValue = if (lowersToArray(ty, f.object.dg.module.getTarget())) result: { |
| | 301 | const writer = f.object.code_header.writer(); |
| | 302 | const alignment = 0; |
| | 303 | const decl_c_value = try f.allocLocalValue(ty, alignment); |
| | 304 | const gpa = f.object.dg.gpa; |
| | 305 | try f.allocs.put(gpa, decl_c_value.new_local, true); |
| | 306 | try writer.writeAll("static "); |
| | 307 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete); |
| | 308 | try writer.writeAll(" = "); |
| | 309 | try f.object.dg.renderValue(writer, ty, val, .StaticInitializer); |
| | 310 | try writer.writeAll(";\n "); |
| | 311 | break :result decl_c_value; |
| | 312 | } else .{ .constant = ref }; |
| | 313 | |
| | 314 | gop.value_ptr.* = result; |
| | 315 | return result; |
| | 316 | } else return .{ .constant = ref }; |
| 315 | } | 317 | } |
| 316 | | 318 | |
| 317 | fn wantSafety(f: *Function) bool { | 319 | fn wantSafety(f: *Function) bool { |
| ... | @@ -2594,6 +2596,7 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2594,6 +2596,7 @@ pub fn genFunc(f: *Function) !void { |
| 2594 | // missing. These are added now to complete the map. Then we can sort by | 2596 | // missing. These are added now to complete the map. Then we can sort by |
| 2595 | // alignment, descending. | 2597 | // alignment, descending. |
| 2596 | const free_locals = &f.free_locals_map; | 2598 | const free_locals = &f.free_locals_map; |
| | 2599 | assert(f.value_map.count() == 0); // there must not be any unfreed locals |
| 2597 | for (f.allocs.keys(), f.allocs.values()) |local_index, value| { | 2600 | for (f.allocs.keys(), f.allocs.values()) |local_index, value| { |
| 2598 | if (value) continue; // static | 2601 | if (value) continue; // static |
| 2599 | const local = f.locals.items[local_index]; | 2602 | const local = f.locals.items[local_index]; |
| ... | @@ -2995,7 +2998,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -2995,7 +2998,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2995 | if (result_value == .new_local) { | 2998 | if (result_value == .new_local) { |
| 2996 | log.debug("map %{d} to t{d}", .{ inst, result_value.new_local }); | 2999 | log.debug("map %{d} to t{d}", .{ inst, result_value.new_local }); |
| 2997 | } | 3000 | } |
| 2998 | try f.value_map.putNoClobber(Air.indexToRef(inst), switch (result_value) { | 3001 | try f.value_map.putNoClobber(inst, switch (result_value) { |
| 2999 | .none => continue, | 3002 | .none => continue, |
| 3000 | .new_local => |i| .{ .local = i }, | 3003 | .new_local => |i| .{ .local = i }, |
| 3001 | else => result_value, | 3004 | else => result_value, |
| ... | @@ -3081,17 +3084,21 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3081,17 +3084,21 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3081 | const child_ty = ptr_ty.childType(); | 3084 | const child_ty = ptr_ty.childType(); |
| 3082 | | 3085 | |
| 3083 | const ptr = try f.resolveInst(bin_op.lhs); | 3086 | const ptr = try f.resolveInst(bin_op.lhs); |
| 3084 | if (!child_ty.hasRuntimeBitsIgnoreComptime()) { | | |
| 3085 | if (f.liveness.operandDies(inst, 1)) try die(f, inst, bin_op.rhs); | | |
| 3086 | return ptr; | | |
| 3087 | } | | |
| 3088 | const index = try f.resolveInst(bin_op.rhs); | 3087 | const index = try f.resolveInst(bin_op.rhs); |
| 3089 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3088 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3090 | | 3089 | |
| 3091 | const writer = f.object.writer(); | 3090 | const writer = f.object.writer(); |
| 3092 | const local = try f.allocLocal(inst, f.air.typeOfIndex(inst)); | 3091 | const local = try f.allocLocal(inst, f.air.typeOfIndex(inst)); |
| 3093 | try f.writeCValue(writer, local, .Other); | 3092 | try f.writeCValue(writer, local, .Other); |
| 3094 | try writer.writeAll(" = ("); | 3093 | try writer.writeAll(" = "); |
| | 3094 | |
| | 3095 | if (!child_ty.hasRuntimeBitsIgnoreComptime()) { |
| | 3096 | try f.writeCValue(writer, ptr, .Initializer); |
| | 3097 | try writer.writeAll(";\n"); |
| | 3098 | return local; |
| | 3099 | } |
| | 3100 | |
| | 3101 | try writer.writeByte('('); |
| 3095 | try f.renderType(writer, inst_ty); | 3102 | try f.renderType(writer, inst_ty); |
| 3096 | try writer.writeAll(")&("); | 3103 | try writer.writeAll(")&("); |
| 3097 | if (ptr_ty.ptrSize() == .One) { | 3104 | if (ptr_ty.ptrSize() == .One) { |
| ... | @@ -3217,12 +3224,11 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3217,12 +3224,11 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3217 | } | 3224 | } |
| 3218 | | 3225 | |
| 3219 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { | 3226 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3220 | const inst_ty = f.air.typeOfIndex(inst); | 3227 | if (f.liveness.isUnused(inst)) return .none; |
| 3221 | | 3228 | |
| | 3229 | const inst_ty = f.air.typeOfIndex(inst); |
| 3222 | const elem_type = inst_ty.elemType(); | 3230 | const elem_type = inst_ty.elemType(); |
| 3223 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) { | 3231 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; |
| 3224 | return .{ .undef = inst_ty }; | | |
| 3225 | } | | |
| 3226 | | 3232 | |
| 3227 | const target = f.object.dg.module.getTarget(); | 3233 | const target = f.object.dg.module.getTarget(); |
| 3228 | const local = try f.allocAlignedLocal( | 3234 | const local = try f.allocAlignedLocal( |
| ... | @@ -3237,12 +3243,11 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3237,12 +3243,11 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3237 | } | 3243 | } |
| 3238 | | 3244 | |
| 3239 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 3245 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3240 | const inst_ty = f.air.typeOfIndex(inst); | 3246 | if (f.liveness.isUnused(inst)) return .none; |
| 3241 | | 3247 | |
| | 3248 | const inst_ty = f.air.typeOfIndex(inst); |
| 3242 | const elem_ty = inst_ty.elemType(); | 3249 | const elem_ty = inst_ty.elemType(); |
| 3243 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) { | 3250 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; |
| 3244 | return .{ .undef = inst_ty }; | | |
| 3245 | } | | |
| 3246 | | 3251 | |
| 3247 | const target = f.object.dg.module.getTarget(); | 3252 | const target = f.object.dg.module.getTarget(); |
| 3248 | const local = try f.allocAlignedLocal( | 3253 | const local = try f.allocAlignedLocal( |
| ... | @@ -3262,10 +3267,22 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3262,10 +3267,22 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3262 | | 3267 | |
| 3263 | const i = f.next_arg_index; | 3268 | const i = f.next_arg_index; |
| 3264 | f.next_arg_index += 1; | 3269 | f.next_arg_index += 1; |
| 3265 | return if (inst_cty != try f.typeToIndex(inst_ty, .complete)) | 3270 | const result: CValue = if (inst_cty != try f.typeToIndex(inst_ty, .complete)) |
| 3266 | .{ .arg_array = i } | 3271 | .{ .arg_array = i } |
| 3267 | else | 3272 | else |
| 3268 | .{ .arg = i }; | 3273 | .{ .arg = i }; |
| | 3274 | |
| | 3275 | if (f.liveness.isUnused(inst)) { |
| | 3276 | const writer = f.object.writer(); |
| | 3277 | try writer.writeByte('('); |
| | 3278 | try f.renderType(writer, Type.void); |
| | 3279 | try writer.writeByte(')'); |
| | 3280 | try f.writeCValue(writer, result, .Other); |
| | 3281 | try writer.writeAll(";\n"); |
| | 3282 | return .none; |
| | 3283 | } |
| | 3284 | |
| | 3285 | return result; |
| 3269 | } | 3286 | } |
| 3270 | | 3287 | |
| 3271 | fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | 3288 | fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| ... | @@ -4179,21 +4196,23 @@ fn airCall( | ... | @@ -4179,21 +4196,23 @@ fn airCall( |
| 4179 | var lowered_ret_buf: LowerFnRetTyBuffer = undefined; | 4196 | var lowered_ret_buf: LowerFnRetTyBuffer = undefined; |
| 4180 | const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target); | 4197 | const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target); |
| 4181 | | 4198 | |
| 4182 | const result_local = if (modifier == .always_tail) r: { | 4199 | const result_local = result: { |
| 4183 | try writer.writeAll("zig_always_tail return "); | 4200 | if (modifier == .always_tail) { |
| 4184 | break :r .none; | 4201 | try writer.writeAll("zig_always_tail return "); |
| 4185 | } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) | 4202 | break :result .none; |
| 4186 | .none | 4203 | } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) { |
| 4187 | else if (f.liveness.isUnused(inst)) r: { | 4204 | break :result .none; |
| 4188 | try writer.writeByte('('); | 4205 | } else if (f.liveness.isUnused(inst)) { |
| 4189 | try f.renderType(writer, Type.void); | 4206 | try writer.writeByte('('); |
| 4190 | try writer.writeByte(')'); | 4207 | try f.renderType(writer, Type.void); |
| 4191 | break :r .none; | 4208 | try writer.writeByte(')'); |
| 4192 | } else r: { | 4209 | break :result .none; |
| 4193 | const local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator())); | 4210 | } else { |
| 4194 | try f.writeCValue(writer, local, .Other); | 4211 | const local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator())); |
| 4195 | try writer.writeAll(" = "); | 4212 | try f.writeCValue(writer, local, .Other); |
| 4196 | break :r local; | 4213 | try writer.writeAll(" = "); |
| | 4214 | break :result local; |
| | 4215 | } |
| 4197 | }; | 4216 | }; |
| 4198 | | 4217 | |
| 4199 | callee: { | 4218 | callee: { |
| ... | @@ -4238,9 +4257,9 @@ fn airCall( | ... | @@ -4238,9 +4257,9 @@ fn airCall( |
| 4238 | } | 4257 | } |
| 4239 | try writer.writeAll(");\n"); | 4258 | try writer.writeAll(");\n"); |
| 4240 | | 4259 | |
| 4241 | const result = r: { | 4260 | const result = result: { |
| 4242 | if (result_local == .none or !lowersToArray(ret_ty, target)) | 4261 | if (result_local == .none or !lowersToArray(ret_ty, target)) |
| 4243 | break :r result_local; | 4262 | break :result result_local; |
| 4244 | | 4263 | |
| 4245 | const array_local = try f.allocLocal(inst, ret_ty); | 4264 | const array_local = try f.allocLocal(inst, ret_ty); |
| 4246 | try writer.writeAll("memcpy("); | 4265 | try writer.writeAll("memcpy("); |
| ... | @@ -4251,7 +4270,7 @@ fn airCall( | ... | @@ -4251,7 +4270,7 @@ fn airCall( |
| 4251 | try f.renderType(writer, ret_ty); | 4270 | try f.renderType(writer, ret_ty); |
| 4252 | try writer.writeAll("));\n"); | 4271 | try writer.writeAll("));\n"); |
| 4253 | try freeLocal(f, inst, result_local.new_local, 0); | 4272 | try freeLocal(f, inst, result_local.new_local, 0); |
| 4254 | break :r array_local; | 4273 | break :result array_local; |
| 4255 | }; | 4274 | }; |
| 4256 | | 4275 | |
| 4257 | return result; | 4276 | return result; |
| ... | @@ -4468,7 +4487,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4468,7 +4487,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4468 | { | 4487 | { |
| 4469 | try f.writeCValue(writer, local, .Other); | 4488 | try f.writeCValue(writer, local, .Other); |
| 4470 | try writer.writeAll(" = "); | 4489 | try writer.writeAll(" = "); |
| 4471 | try f.writeCValue(writer, operand, .Other); | 4490 | try f.writeCValue(writer, operand, .Initializer); |
| 4472 | try writer.writeAll(";\n"); | 4491 | try writer.writeAll(";\n"); |
| 4473 | return local; | 4492 | return local; |
| 4474 | } | 4493 | } |
| ... | @@ -4835,8 +4854,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4835,8 +4854,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4835 | const inputs = @ptrCast([]const Air.Inst.Ref, f.air.extra[extra_i..][0..extra.data.inputs_len]); | 4854 | const inputs = @ptrCast([]const Air.Inst.Ref, f.air.extra[extra_i..][0..extra.data.inputs_len]); |
| 4836 | extra_i += inputs.len; | 4855 | extra_i += inputs.len; |
| 4837 | | 4856 | |
| 4838 | const result = r: { | 4857 | const result = result: { |
| 4839 | if (!is_volatile and f.liveness.isUnused(inst)) break :r .none; | 4858 | if (!is_volatile and f.liveness.isUnused(inst)) break :result .none; |
| 4840 | | 4859 | |
| 4841 | const writer = f.object.writer(); | 4860 | const writer = f.object.writer(); |
| 4842 | const inst_ty = f.air.typeOfIndex(inst); | 4861 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -5064,7 +5083,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5064,7 +5083,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5064 | } | 5083 | } |
| 5065 | } | 5084 | } |
| 5066 | | 5085 | |
| 5067 | break :r local; | 5086 | break :result if (f.liveness.isUnused(inst)) .none else local; |
| 5068 | }; | 5087 | }; |
| 5069 | | 5088 | |
| 5070 | var bt = iterateBigTomb(f, inst); | 5089 | var bt = iterateBigTomb(f, inst); |
| ... | @@ -7036,21 +7055,22 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7036,21 +7055,22 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7036 | | 7055 | |
| 7037 | fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { | 7056 | fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7038 | const prefetch = f.air.instructions.items(.data)[inst].prefetch; | 7057 | const prefetch = f.air.instructions.items(.data)[inst].prefetch; |
| 7039 | switch (prefetch.cache) { | 7058 | |
| 7040 | .data => {}, | | |
| 7041 | // The available prefetch intrinsics do not accept a cache argument; only | | |
| 7042 | // address, rw, and locality. So unless the cache is data, we do not lower | | |
| 7043 | // this instruction. | | |
| 7044 | .instruction => return .none, | | |
| 7045 | } | | |
| 7046 | const ptr = try f.resolveInst(prefetch.ptr); | 7059 | const ptr = try f.resolveInst(prefetch.ptr); |
| 7047 | try reap(f, inst, &.{prefetch.ptr}); | 7060 | try reap(f, inst, &.{prefetch.ptr}); |
| | 7061 | |
| 7048 | const writer = f.object.writer(); | 7062 | const writer = f.object.writer(); |
| 7049 | try writer.writeAll("zig_prefetch("); | 7063 | switch (prefetch.cache) { |
| 7050 | try f.writeCValue(writer, ptr, .FunctionArgument); | 7064 | .data => { |
| 7051 | try writer.print(", {d}, {d});\n", .{ | 7065 | try writer.writeAll("zig_prefetch("); |
| 7052 | @enumToInt(prefetch.rw), prefetch.locality, | 7066 | try f.writeCValue(writer, ptr, .FunctionArgument); |
| 7053 | }); | 7067 | try writer.print(", {d}, {d});\n", .{ @enumToInt(prefetch.rw), prefetch.locality }); |
| | 7068 | }, |
| | 7069 | // The available prefetch intrinsics do not accept a cache argument; only |
| | 7070 | // address, rw, and locality. |
| | 7071 | .instruction => {}, |
| | 7072 | } |
| | 7073 | |
| 7054 | return .none; | 7074 | return .none; |
| 7055 | } | 7075 | } |
| 7056 | | 7076 | |
| ... | @@ -7830,8 +7850,8 @@ fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !voi | ... | @@ -7830,8 +7850,8 @@ fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !voi |
| 7830 | | 7850 | |
| 7831 | fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void { | 7851 | fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void { |
| 7832 | const ref_inst = Air.refToIndex(ref) orelse return; | 7852 | const ref_inst = Air.refToIndex(ref) orelse return; |
| | 7853 | const c_value = (f.value_map.fetchRemove(ref_inst) orelse return).value; |
| 7833 | if (f.air.instructions.items(.tag)[ref_inst] == .constant) return; | 7854 | if (f.air.instructions.items(.tag)[ref_inst] == .constant) return; |
| 7834 | const c_value = (f.value_map.fetchRemove(ref) orelse return).value; | | |
| 7835 | const local_index = switch (c_value) { | 7855 | const local_index = switch (c_value) { |
| 7836 | .local, .new_local => |l| l, | 7856 | .local, .new_local => |l| l, |
| 7837 | else => return, | 7857 | else => return, |