From 0395b35cee8d4082cc40b0dcd0298f797f42309d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 14 Sep 2021 21:58:22 -0700 Subject: stage2: implement cmpxchg and improve comptime eval * Implement Sema for `@cmpxchgWeak` and `@cmpxchgStrong`. Both runtime and comptime codepaths are implement. * Implement Codegen for LLVM backend and C backend. * Add LazySrcLoc.node_offset_builtin_call_argX 3...5 * Sema: rework comptime control flow. - `error.ComptimeReturn` is used to signal that a comptime function call has returned a result (stored in the Inlining struct). `analyzeCall` notices this and handles the result. - The ZIR instructions `break_inline`, `block_inline`, `condbr_inline` are now redundant and can be deleted. `break`, `block`, and `condbr` function equivalently inside a comptime scope. - The ZIR instructions `loop` and `repeat` also are modified to directly perform comptime control flow inside a comptime scope, skipping an unnecessary mechanism for analysis of runtime code. This makes Zig perform closer to an interpreter when evaluating comptime code. * Sema: zirRetErrValue looks at Sema.ret_fn_ty rather than sema.func for adding to the inferred error set. This fixes a bug for inlined/comptime function calls. * Implement ZIR printing for cmpxchg. * stage1: make cmpxchg respect --single-threaded - Our LLVM C++ API wrapper failed to expose this boolean flag before. * Fix AIR printing for struct fields showing incorrect liveness data. --- src/codegen/c.zig | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src/codegen/c.zig') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 84bc6ceeb0..ff49b18f7b 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -911,6 +911,8 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM .wrap_optional => try airWrapOptional(o, inst), .struct_field_ptr => try airStructFieldPtr(o, inst), .array_to_slice => try airArrayToSlice(o, inst), + .cmpxchg_weak => try airCmpxchg(o, inst, "weak"), + .cmpxchg_strong => try airCmpxchg(o, inst, "strong"), .struct_field_ptr_index_0 => try airStructFieldPtrIndex(o, inst, 0), .struct_field_ptr_index_1 => try airStructFieldPtrIndex(o, inst, 1), @@ -1878,6 +1880,43 @@ fn airArrayToSlice(o: *Object, inst: Air.Inst.Index) !CValue { return local; } +fn airCmpxchg(o: *Object, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { + const ty_pl = o.air.instructions.items(.data)[inst].ty_pl; + const extra = o.air.extraData(Air.Cmpxchg, ty_pl.payload).data; + const inst_ty = o.air.typeOfIndex(inst); + const ptr = try o.resolveInst(extra.ptr); + const expected_value = try o.resolveInst(extra.expected_value); + const new_value = try o.resolveInst(extra.new_value); + const local = try o.allocLocal(inst_ty, .Const); + const writer = o.writer(); + + try writer.print(" = zig_cmpxchg_{s}(", .{flavor}); + try o.writeCValue(writer, ptr); + try writer.writeAll(", "); + try o.writeCValue(writer, expected_value); + try writer.writeAll(", "); + try o.writeCValue(writer, new_value); + try writer.writeAll(", "); + try writeMemoryOrder(writer, extra.successOrder()); + try writer.writeAll(", "); + try writeMemoryOrder(writer, extra.failureOrder()); + try writer.writeAll(");\n"); + + return local; +} + +fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void { + const str = switch (order) { + .Unordered => "memory_order_relaxed", + .Monotonic => "memory_order_consume", + .Acquire => "memory_order_acquire", + .Release => "memory_order_release", + .AcqRel => "memory_order_acq_rel", + .SeqCst => "memory_order_seq_cst", + }; + return w.writeAll(str); +} + fn IndentWriter(comptime UnderlyingWriter: type) type { return struct { const Self = @This(); -- cgit v1.2.3