mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
parent
cf0d300dde
commit
19ddbd9e9e
@ -1951,10 +1951,10 @@ test "comptime pointers" {
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "@ptrToInt and @intToPtr" {
|
||||
const ptr = @intToPtr(*i32, 0xdeadbeef);
|
||||
const ptr = @intToPtr(*i32, 0xdeadbee0);
|
||||
const addr = @ptrToInt(ptr);
|
||||
assert(@TypeOf(addr) == usize);
|
||||
assert(addr == 0xdeadbeef);
|
||||
assert(addr == 0xdeadbee0);
|
||||
}
|
||||
{#code_end#}
|
||||
<p>Zig is able to preserve memory addresses in comptime code, as long as
|
||||
@ -1966,10 +1966,10 @@ test "comptime @intToPtr" {
|
||||
comptime {
|
||||
// Zig is able to do this at compile-time, as long as
|
||||
// ptr is never dereferenced.
|
||||
const ptr = @intToPtr(*i32, 0xdeadbeef);
|
||||
const ptr = @intToPtr(*i32, 0xdeadbee0);
|
||||
const addr = @ptrToInt(ptr);
|
||||
assert(@TypeOf(addr) == usize);
|
||||
assert(addr == 0xdeadbeef);
|
||||
assert(addr == 0xdeadbee0);
|
||||
}
|
||||
}
|
||||
{#code_end#}
|
||||
@ -5232,8 +5232,8 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
|
||||
}
|
||||
|
||||
test "peer type resolution: *const T and ?*T" {
|
||||
const a = @intToPtr(*const usize, 0x123456789);
|
||||
const b = @intToPtr(?*usize, 0x123456789);
|
||||
const a = @intToPtr(*const usize, 0x123456780);
|
||||
const b = @intToPtr(?*usize, 0x123456780);
|
||||
assert(a == b);
|
||||
assert(b == a);
|
||||
}
|
||||
@ -9169,7 +9169,7 @@ fn foo(set1: Set1) void {
|
||||
<p>At compile-time:</p>
|
||||
{#code_begin|test_err|pointer address 0x1 is not aligned to 4 bytes#}
|
||||
comptime {
|
||||
const ptr = @intToPtr(*i32, 0x1);
|
||||
const ptr = @intToPtr(*align(1) i32, 0x1);
|
||||
const aligned = @alignCast(4, ptr);
|
||||
}
|
||||
{#code_end#}
|
||||
|
||||
@ -1257,7 +1257,7 @@ test "slice" {
|
||||
try testFmt("slice: abc\n", "slice: {}\n", .{value});
|
||||
}
|
||||
{
|
||||
const value = @intToPtr([*]const []const u8, 0xdeadbeef)[0..0];
|
||||
const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
|
||||
try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
|
||||
}
|
||||
|
||||
@ -1267,7 +1267,7 @@ test "slice" {
|
||||
|
||||
test "pointer" {
|
||||
{
|
||||
const value = @intToPtr(*i32, 0xdeadbeef);
|
||||
const value = @intToPtr(*align(1) i32, 0xdeadbeef);
|
||||
try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
|
||||
try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
|
||||
}
|
||||
|
||||
@ -281,7 +281,9 @@ pub fn copyTLS(addr: usize) usize {
|
||||
dtv.entries = 1;
|
||||
dtv.tls_block[0] = addr + tls_img.data_offset + tls_dtv_offset;
|
||||
// Set-up the TCB
|
||||
const tcb_ptr = @intToPtr(*usize, addr + tls_img.tcb_offset);
|
||||
// Force the alignment to 1 byte as the TCB may start from a non-aligned
|
||||
// address under the variant II model
|
||||
const tcb_ptr = @intToPtr(*align(1) usize, addr + tls_img.tcb_offset);
|
||||
if (tls_variant == TLSVariant.VariantI) {
|
||||
tcb_ptr.* = addr + tls_img.dtv_offset;
|
||||
} else {
|
||||
|
||||
@ -3241,17 +3241,37 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa
|
||||
static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, IrInstructionIntToPtr *instruction) {
|
||||
ZigType *wanted_type = instruction->base.value->type;
|
||||
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
|
||||
if (!ptr_allows_addr_zero(wanted_type) && ir_want_runtime_safety(g, &instruction->base)) {
|
||||
LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(target_val));
|
||||
LLVMValueRef is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, target_val, zero, "");
|
||||
LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntBad");
|
||||
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntOk");
|
||||
LLVMBuildCondBr(g->builder, is_zero_bit, bad_block, ok_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, bad_block);
|
||||
gen_safety_crash(g, PanicMsgIdPtrCastNull);
|
||||
if (ir_want_runtime_safety(g, &instruction->base)) {
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
LLVMValueRef zero = LLVMConstNull(usize->llvm_type);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
if (!ptr_allows_addr_zero(wanted_type)) {
|
||||
LLVMValueRef is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, target_val, zero, "");
|
||||
LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntBad");
|
||||
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntOk");
|
||||
LLVMBuildCondBr(g->builder, is_zero_bit, bad_block, ok_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, bad_block);
|
||||
gen_safety_crash(g, PanicMsgIdPtrCastNull);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
}
|
||||
|
||||
{
|
||||
const uint32_t align_bytes = get_ptr_align(g, wanted_type);
|
||||
LLVMValueRef alignment_minus_1 = LLVMConstInt(usize->llvm_type, align_bytes - 1, false);
|
||||
LLVMValueRef anded_val = LLVMBuildAnd(g->builder, target_val, alignment_minus_1, "");
|
||||
LLVMValueRef is_ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, anded_val, zero, "");
|
||||
LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntAlignBad");
|
||||
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntAlignOk");
|
||||
LLVMBuildCondBr(g->builder, is_ok_bit, ok_block, bad_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, bad_block);
|
||||
gen_safety_crash(g, PanicMsgIdIncorrectAlignment);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
}
|
||||
}
|
||||
return LLVMBuildIntToPtr(g->builder, target_val, get_llvm_type(g, wanted_type), "");
|
||||
}
|
||||
|
||||
@ -26606,6 +26606,14 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
const uint32_t align_bytes = get_ptr_align(ira->codegen, ptr_type);
|
||||
if (addr != 0 && addr % align_bytes != 0) {
|
||||
ir_add_error(ira, source_instr,
|
||||
buf_sprintf("pointer type '%s' requires aligned address",
|
||||
buf_ptr(&ptr_type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
IrInstruction *result = ir_const(ira, source_instr, ptr_type);
|
||||
result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
|
||||
result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
|
||||
|
||||
@ -2,6 +2,14 @@ const tests = @import("tests.zig");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add("intToPtr with misaligned address",
|
||||
\\pub fn main() void {
|
||||
\\ var y = @intToPtr([*]align(4) u8, 5);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address",
|
||||
});
|
||||
|
||||
cases.add("invalid float literal",
|
||||
\\const std = @import("std");
|
||||
\\
|
||||
@ -2153,7 +2161,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
|
||||
cases.add("bad @alignCast at comptime",
|
||||
\\comptime {
|
||||
\\ const ptr = @intToPtr(*i32, 0x1);
|
||||
\\ const ptr = @intToPtr(*align(1) i32, 0x1);
|
||||
\\ const aligned = @alignCast(4, ptr);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
|
||||
@ -1,6 +1,19 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: *tests.CompareOutputContext) void {
|
||||
cases.addRuntimeSafety("intToPtr with misaligned address",
|
||||
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
|
||||
\\ if (@import("std").mem.eql(u8, message, "incorrect alignment")) {
|
||||
\\ @import("std").os.exit(126); // good
|
||||
\\ }
|
||||
\\ @import("std").os.exit(0); // test failed
|
||||
\\}
|
||||
\\pub fn main() void {
|
||||
\\ var x: usize = 5;
|
||||
\\ var y = @intToPtr([*]align(4) u8, x);
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.addRuntimeSafety("resuming a non-suspended function which never been suspended",
|
||||
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
|
||||
\\ @import("std").os.exit(126);
|
||||
|
||||
@ -67,10 +67,10 @@ test "C pointer comparison and arithmetic" {
|
||||
expect(ptr1 == 0);
|
||||
expect(ptr1 >= 0);
|
||||
expect(ptr1 <= 0);
|
||||
expect(ptr1 < 1);
|
||||
expect(ptr1 < one);
|
||||
expect(1 > ptr1);
|
||||
expect(one > ptr1);
|
||||
// expect(ptr1 < 1);
|
||||
// expect(ptr1 < one);
|
||||
// expect(1 > ptr1);
|
||||
// expect(one > ptr1);
|
||||
expect(ptr1 < ptr2);
|
||||
expect(ptr2 > ptr1);
|
||||
expect(ptr2 >= 40);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user