diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-09-16 21:03:55 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-09-16 21:03:55 -0700 |
| commit | dbe9a5114e2d56f847b674539ffa0d28fc57ea78 (patch) | |
| tree | 078fe7aadd48de9c78aea90d6a383ba134622be5 /src/Sema.zig | |
| parent | dc9d76b630e0fe9a465cec67dc4dc66e8cce7c58 (diff) | |
| download | zig-dbe9a5114e2d56f847b674539ffa0d28fc57ea78.tar.gz zig-dbe9a5114e2d56f847b674539ffa0d28fc57ea78.zip | |
stage2: implement `@setAlignStack` and 128-bit cmpxchg
* test runner is improved to respect `error.SkipZigTest`
* start code is improved to `@setAlignStack(16)` before calling main()
* the newly passing behavior test has a workaround for the fact that
stage2 cannot yet call `std.Target.x86.featureSetHas()` at comptime.
This is blocking on comptime closures. The workaround is that there
is a new decl `@import("builtin").stage2_x86_cx16` which is a `bool`.
* Implement `@setAlignStack`. This language feature should be re-evaluated
at some point - I'll file an issue for it.
* LLVM backend: apply/remove the cold attribute and noinline attribute
where appropriate.
* LLVM backend: loads and stores are properly annotated with alignment
and volatile attributes.
* LLVM backend: allocas are properly annotated with alignment.
* Type: fix integers reporting wrong alignment for 256-bit integers and
beyond. Once you get to 16 byte aligned, there is no further
alignment for larger integers.
Diffstat (limited to 'src/Sema.zig')
| -rw-r--r-- | src/Sema.zig | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 19e0f41b98..58aa7ca1c0 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -833,6 +833,7 @@ fn failWithUseOfUndef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) Compile /// Appropriate to call when the coercion has already been done by result /// location semantics. Asserts the value fits in the provided `Int` type. /// Only supports `Int` types 64 bits or less. +/// TODO don't ever call this since we're migrating towards ResultLoc.coerced_ty. fn resolveAlreadyCoercedInt( sema: *Sema, block: *Scope.Block, @@ -849,6 +850,23 @@ fn resolveAlreadyCoercedInt( } } +fn resolveAlign( + sema: *Sema, + block: *Scope.Block, + src: LazySrcLoc, + zir_ref: Zir.Inst.Ref, +) !u16 { + const alignment_big = try sema.resolveInt(block, src, zir_ref, Type.initTag(.u16)); + const alignment = @intCast(u16, alignment_big); // We coerce to u16 in the prev line. + if (alignment == 0) return sema.mod.fail(&block.base, src, "alignment must be >= 1", .{}); + if (!std.math.isPowerOfTwo(alignment)) { + return sema.mod.fail(&block.base, src, "alignment value {d} is not a power of two", .{ + alignment, + }); + } + return alignment; +} + fn resolveInt( sema: *Sema, block: *Scope.Block, @@ -2285,9 +2303,36 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro } fn zirSetAlignStack(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { + const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[inst].un_node; + const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const src: LazySrcLoc = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetAlignStack", .{}); + const alignment = try sema.resolveAlign(block, operand_src, inst_data.operand); + if (alignment > 256) { + return mod.fail(&block.base, src, "attempt to @setAlignStack({d}); maximum is 256", .{ + alignment, + }); + } + const func = sema.owner_func orelse + return mod.fail(&block.base, src, "@setAlignStack outside function body", .{}); + + switch (func.owner_decl.ty.fnCallingConvention()) { + .Naked => return mod.fail(&block.base, src, "@setAlignStack in naked function", .{}), + .Inline => return mod.fail(&block.base, src, "@setAlignStack in inline function", .{}), + else => {}, + } + + const gop = try mod.align_stack_fns.getOrPut(mod.gpa, func); + if (gop.found_existing) { + const msg = msg: { + const msg = try mod.errMsg(&block.base, src, "multiple @setAlignStack in the same function body", .{}); + errdefer msg.destroy(mod.gpa); + try mod.errNote(&block.base, src, msg, "other instance here", .{}); + break :msg msg; + }; + return mod.failWithOwnedErrorMsg(&block.base, msg); + } + gop.value_ptr.* = .{ .alignment = alignment, .src = src }; } fn zirSetCold(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { |
