mirror of
https://github.com/ziglang/zig.git
synced 2025-02-10 22:50:18 +00:00
disallow single-item pointer indexing
add pointer arithmetic for unknown length pointer
This commit is contained in:
parent
4c273126df
commit
96164ce613
@ -458,7 +458,7 @@ test "string literals" {
|
||||
|
||||
// A C string literal is a null terminated pointer.
|
||||
const null_terminated_bytes = c"hello";
|
||||
assert(@typeOf(null_terminated_bytes) == *const u8);
|
||||
assert(@typeOf(null_terminated_bytes) == [*]const u8);
|
||||
assert(null_terminated_bytes[5] == 0);
|
||||
}
|
||||
{#code_end#}
|
||||
@ -547,7 +547,7 @@ const c_string_literal =
|
||||
;
|
||||
{#code_end#}
|
||||
<p>
|
||||
In this example the variable <code>c_string_literal</code> has type <code>*const char</code> and
|
||||
In this example the variable <code>c_string_literal</code> has type <code>[*]const char</code> and
|
||||
has a terminating null byte.
|
||||
</p>
|
||||
{#see_also|@embedFile#}
|
||||
@ -1288,7 +1288,7 @@ const assert = @import("std").debug.assert;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
// array literal
|
||||
const message = []u8{'h', 'e', 'l', 'l', 'o'};
|
||||
const message = []u8{ 'h', 'e', 'l', 'l', 'o' };
|
||||
|
||||
// get the size of an array
|
||||
comptime {
|
||||
@ -1324,11 +1324,11 @@ test "modify an array" {
|
||||
|
||||
// array concatenation works if the values are known
|
||||
// at compile time
|
||||
const part_one = []i32{1, 2, 3, 4};
|
||||
const part_two = []i32{5, 6, 7, 8};
|
||||
const part_one = []i32{ 1, 2, 3, 4 };
|
||||
const part_two = []i32{ 5, 6, 7, 8 };
|
||||
const all_of_it = part_one ++ part_two;
|
||||
comptime {
|
||||
assert(mem.eql(i32, all_of_it, []i32{1,2,3,4,5,6,7,8}));
|
||||
assert(mem.eql(i32, all_of_it, []i32{ 1, 2, 3, 4, 5, 6, 7, 8 }));
|
||||
}
|
||||
|
||||
// remember that string literals are arrays
|
||||
@ -1357,7 +1357,7 @@ comptime {
|
||||
var fancy_array = init: {
|
||||
var initial_value: [10]Point = undefined;
|
||||
for (initial_value) |*pt, i| {
|
||||
pt.* = Point {
|
||||
pt.* = Point{
|
||||
.x = i32(i),
|
||||
.y = i32(i) * 2,
|
||||
};
|
||||
@ -1377,7 +1377,7 @@ test "compile-time array initalization" {
|
||||
// call a function to initialize an array
|
||||
var more_points = []Point{makePoint(3)} ** 10;
|
||||
fn makePoint(x: i32) Point {
|
||||
return Point {
|
||||
return Point{
|
||||
.x = x,
|
||||
.y = x * 2,
|
||||
};
|
||||
@ -1414,25 +1414,24 @@ test "address of syntax" {
|
||||
}
|
||||
|
||||
test "pointer array access" {
|
||||
// Pointers do not support pointer arithmetic. If you
|
||||
// need such a thing, use array index syntax:
|
||||
// Taking an address of an individual element gives a
|
||||
// pointer to a single item. This kind of pointer
|
||||
// does not support pointer arithmetic.
|
||||
|
||||
var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
const ptr = &array[1];
|
||||
const ptr = &array[2];
|
||||
assert(@typeOf(ptr) == *u8);
|
||||
|
||||
assert(array[2] == 3);
|
||||
ptr[1] += 1;
|
||||
ptr.* += 1;
|
||||
assert(array[2] == 4);
|
||||
}
|
||||
|
||||
test "pointer slicing" {
|
||||
// In Zig, we prefer using slices over null-terminated pointers.
|
||||
// You can turn a pointer into a slice using slice syntax:
|
||||
// You can turn an array into a slice using slice syntax:
|
||||
var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
const ptr = &array[1];
|
||||
const slice = ptr[1..3];
|
||||
|
||||
assert(slice.ptr == &ptr[1]);
|
||||
const slice = array[2..4];
|
||||
assert(slice.len == 2);
|
||||
|
||||
// Slices have bounds checking and are therefore protected
|
||||
@ -1622,18 +1621,27 @@ fn foo(bytes: []u8) u32 {
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "basic slices" {
|
||||
var array = []i32{1, 2, 3, 4};
|
||||
var array = []i32{ 1, 2, 3, 4 };
|
||||
// A slice is a pointer and a length. The difference between an array and
|
||||
// a slice is that the array's length is part of the type and known at
|
||||
// compile-time, whereas the slice's length is known at runtime.
|
||||
// Both can be accessed with the `len` field.
|
||||
const slice = array[0..array.len];
|
||||
assert(slice.ptr == &array[0]);
|
||||
assert(&slice[0] == &array[0]);
|
||||
assert(slice.len == array.len);
|
||||
|
||||
// Using the address-of operator on a slice gives a pointer to a single
|
||||
// item, while using the `ptr` field gives an unknown length pointer.
|
||||
assert(@typeOf(slice.ptr) == [*]i32);
|
||||
assert(@typeOf(&slice[0]) == *i32);
|
||||
assert(@ptrToInt(slice.ptr) == @ptrToInt(&slice[0]));
|
||||
|
||||
// Slices have array bounds checking. If you try to access something out
|
||||
// of bounds, you'll get a safety check failure:
|
||||
slice[10] += 1;
|
||||
|
||||
// Note that `slice.ptr` does not invoke safety checking, while `&slice[0]`
|
||||
// asserts that the slice has len >= 1.
|
||||
}
|
||||
{#code_end#}
|
||||
<p>This is one reason we prefer slices to pointers.</p>
|
||||
@ -5937,7 +5945,7 @@ pub const __zig_test_fn_slice = {}; // overwritten later
|
||||
{#header_open|C String Literals#}
|
||||
{#code_begin|exe#}
|
||||
{#link_libc#}
|
||||
extern fn puts(*const u8) void;
|
||||
extern fn puts([*]const u8) void;
|
||||
|
||||
pub fn main() void {
|
||||
puts(c"this has a null terminator");
|
||||
|
@ -974,8 +974,14 @@ struct FnTypeId {
|
||||
uint32_t fn_type_id_hash(FnTypeId*);
|
||||
bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
|
||||
|
||||
enum PtrLen {
|
||||
PtrLenUnknown,
|
||||
PtrLenSingle,
|
||||
};
|
||||
|
||||
struct TypeTableEntryPointer {
|
||||
TypeTableEntry *child_type;
|
||||
PtrLen ptr_len;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
uint32_t alignment;
|
||||
@ -1397,6 +1403,7 @@ struct TypeId {
|
||||
union {
|
||||
struct {
|
||||
TypeTableEntry *child_type;
|
||||
PtrLen ptr_len;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
uint32_t alignment;
|
||||
@ -2268,6 +2275,7 @@ struct IrInstructionElemPtr {
|
||||
|
||||
IrInstruction *array_ptr;
|
||||
IrInstruction *elem_index;
|
||||
PtrLen ptr_len;
|
||||
bool is_const;
|
||||
bool safety_check_on;
|
||||
};
|
||||
@ -2419,6 +2427,7 @@ struct IrInstructionPtrType {
|
||||
IrInstruction *child_type;
|
||||
uint32_t bit_offset_start;
|
||||
uint32_t bit_offset_end;
|
||||
PtrLen ptr_len;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
};
|
||||
|
@ -381,14 +381,14 @@ TypeTableEntry *get_promise_type(CodeGen *g, TypeTableEntry *result_type) {
|
||||
}
|
||||
|
||||
TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,
|
||||
bool is_volatile, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count)
|
||||
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count)
|
||||
{
|
||||
assert(!type_is_invalid(child_type));
|
||||
|
||||
TypeId type_id = {};
|
||||
TypeTableEntry **parent_pointer = nullptr;
|
||||
uint32_t abi_alignment = get_abi_alignment(g, child_type);
|
||||
if (unaligned_bit_count != 0 || is_volatile || byte_alignment != abi_alignment) {
|
||||
if (unaligned_bit_count != 0 || is_volatile || byte_alignment != abi_alignment || ptr_len != PtrLenSingle) {
|
||||
type_id.id = TypeTableEntryIdPointer;
|
||||
type_id.data.pointer.child_type = child_type;
|
||||
type_id.data.pointer.is_const = is_const;
|
||||
@ -396,6 +396,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
|
||||
type_id.data.pointer.alignment = byte_alignment;
|
||||
type_id.data.pointer.bit_offset = bit_offset;
|
||||
type_id.data.pointer.unaligned_bit_count = unaligned_bit_count;
|
||||
type_id.data.pointer.ptr_len = ptr_len;
|
||||
|
||||
auto existing_entry = g->type_table.maybe_get(type_id);
|
||||
if (existing_entry)
|
||||
@ -414,16 +415,17 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer);
|
||||
entry->is_copyable = true;
|
||||
|
||||
const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";
|
||||
const char *const_str = is_const ? "const " : "";
|
||||
const char *volatile_str = is_volatile ? "volatile " : "";
|
||||
buf_resize(&entry->name, 0);
|
||||
if (unaligned_bit_count == 0 && byte_alignment == abi_alignment) {
|
||||
buf_appendf(&entry->name, "*%s%s%s", const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
} else if (unaligned_bit_count == 0) {
|
||||
buf_appendf(&entry->name, "*align(%" PRIu32 ") %s%s%s", byte_alignment,
|
||||
buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
|
||||
const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
} else {
|
||||
buf_appendf(&entry->name, "*align(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", byte_alignment,
|
||||
buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
|
||||
bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
}
|
||||
|
||||
@ -433,7 +435,9 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
|
||||
|
||||
if (!entry->zero_bits) {
|
||||
assert(byte_alignment > 0);
|
||||
if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != abi_alignment) {
|
||||
if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != abi_alignment ||
|
||||
ptr_len != PtrLenSingle)
|
||||
{
|
||||
TypeTableEntry *peer_type = get_pointer_to_type(g, child_type, false);
|
||||
entry->type_ref = peer_type->type_ref;
|
||||
entry->di_type = peer_type->di_type;
|
||||
@ -451,6 +455,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
|
||||
entry->di_type = g->builtin_types.entry_void->di_type;
|
||||
}
|
||||
|
||||
entry->data.pointer.ptr_len = ptr_len;
|
||||
entry->data.pointer.child_type = child_type;
|
||||
entry->data.pointer.is_const = is_const;
|
||||
entry->data.pointer.is_volatile = is_volatile;
|
||||
@ -467,7 +472,8 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
|
||||
}
|
||||
|
||||
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
|
||||
return get_pointer_to_type_extra(g, child_type, is_const, false, get_abi_alignment(g, child_type), 0, 0);
|
||||
return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle,
|
||||
get_abi_alignment(g, child_type), 0, 0);
|
||||
}
|
||||
|
||||
TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type) {
|
||||
@ -757,6 +763,7 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *pointer_type, Typ
|
||||
|
||||
TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type) {
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown);
|
||||
|
||||
TypeTableEntry **parent_pointer = &ptr_type->data.pointer.slice_parent;
|
||||
if (*parent_pointer) {
|
||||
@ -768,14 +775,16 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type) {
|
||||
|
||||
// replace the & with [] to go from a ptr type name to a slice type name
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + 1);
|
||||
size_t name_offset = (ptr_type->data.pointer.ptr_len == PtrLenSingle) ? 1 : 3;
|
||||
buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset);
|
||||
|
||||
TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
|
||||
uint32_t abi_alignment;
|
||||
uint32_t abi_alignment = get_abi_alignment(g, child_type);
|
||||
if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
|
||||
ptr_type->data.pointer.alignment != (abi_alignment = get_abi_alignment(g, child_type)))
|
||||
ptr_type->data.pointer.alignment != abi_alignment)
|
||||
{
|
||||
TypeTableEntry *peer_ptr_type = get_pointer_to_type(g, child_type, false);
|
||||
TypeTableEntry *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
|
||||
PtrLenUnknown, abi_alignment, 0, 0);
|
||||
TypeTableEntry *peer_slice_type = get_slice_type(g, peer_ptr_type);
|
||||
|
||||
slice_type_common_init(g, ptr_type, entry);
|
||||
@ -799,9 +808,11 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type) {
|
||||
if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
|
||||
child_ptr_type->data.pointer.alignment != get_abi_alignment(g, grand_child_type))
|
||||
{
|
||||
TypeTableEntry *bland_child_ptr_type = get_pointer_to_type(g, grand_child_type, false);
|
||||
TypeTableEntry *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, grand_child_type), 0, 0);
|
||||
TypeTableEntry *bland_child_slice = get_slice_type(g, bland_child_ptr_type);
|
||||
TypeTableEntry *peer_ptr_type = get_pointer_to_type(g, bland_child_slice, false);
|
||||
TypeTableEntry *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, bland_child_slice), 0, 0);
|
||||
TypeTableEntry *peer_slice_type = get_slice_type(g, peer_ptr_type);
|
||||
|
||||
entry->type_ref = peer_slice_type->type_ref;
|
||||
@ -1284,7 +1295,8 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_
|
||||
}
|
||||
|
||||
static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) {
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, ptr_type);
|
||||
IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
|
||||
if (type_is_invalid(instr->value.type))
|
||||
@ -2954,7 +2966,8 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) {
|
||||
if (fn_type_id->param_count != 2) {
|
||||
return wrong_panic_prototype(g, proto_node, fn_type);
|
||||
}
|
||||
TypeTableEntry *const_u8_ptr = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *const_u8_slice = get_slice_type(g, const_u8_ptr);
|
||||
if (fn_type_id->param_info[0].type != const_u8_slice) {
|
||||
return wrong_panic_prototype(g, proto_node, fn_type);
|
||||
@ -4994,7 +5007,9 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
|
||||
|
||||
// then make the pointer point to it
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
// TODO make this `[*]null u8` instead of `[*]u8`
|
||||
const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
|
||||
const_val->data.x_ptr.data.base_array.array_val = array_val;
|
||||
const_val->data.x_ptr.data.base_array.elem_index = 0;
|
||||
@ -5135,7 +5150,9 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
|
||||
{
|
||||
assert(array_val->type->id == TypeTableEntryIdArray);
|
||||
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(g, array_val->type->data.array.child_type, is_const);
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, array_val->type->data.array.child_type,
|
||||
is_const, false, PtrLenUnknown, get_abi_alignment(g, array_val->type->data.array.child_type),
|
||||
0, 0);
|
||||
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->type = get_slice_type(g, ptr_type);
|
||||
@ -5759,6 +5776,7 @@ uint32_t type_id_hash(TypeId x) {
|
||||
return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
|
||||
case TypeTableEntryIdPointer:
|
||||
return hash_ptr(x.data.pointer.child_type) +
|
||||
((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
|
||||
(x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
|
||||
(x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
|
||||
(((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
|
||||
@ -5807,6 +5825,7 @@ bool type_id_eql(TypeId a, TypeId b) {
|
||||
|
||||
case TypeTableEntryIdPointer:
|
||||
return a.data.pointer.child_type == b.data.pointer.child_type &&
|
||||
a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
|
||||
a.data.pointer.is_const == b.data.pointer.is_const &&
|
||||
a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
|
||||
a.data.pointer.alignment == b.data.pointer.alignment &&
|
||||
|
@ -16,7 +16,7 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m
|
||||
TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
|
||||
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
|
||||
TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,
|
||||
bool is_volatile, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);
|
||||
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);
|
||||
uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
|
||||
uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry);
|
||||
TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits);
|
||||
|
@ -625,7 +625,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
case NodeTypePointerType:
|
||||
{
|
||||
if (!grouped) fprintf(ar->f, "(");
|
||||
fprintf(ar->f, "*");
|
||||
const char *star = "[*]";
|
||||
if (node->data.pointer_type.star_token != nullptr &&
|
||||
(node->data.pointer_type.star_token->id == TokenIdStar || node->data.pointer_type.star_token->id == TokenIdStarStar))
|
||||
{
|
||||
star = "*";
|
||||
}
|
||||
fprintf(ar->f, "%s", star);
|
||||
if (node->data.pointer_type.align_expr != nullptr) {
|
||||
fprintf(ar->f, "align(");
|
||||
render_node_grouped(ar, node->data.pointer_type.align_expr);
|
||||
|
@ -893,7 +893,8 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
|
||||
assert(val->global_refs->llvm_global);
|
||||
}
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
|
||||
return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(str_type->type_ref, 0));
|
||||
}
|
||||
@ -1461,7 +1462,8 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
|
||||
LLVMValueRef full_buf_ptr = LLVMConstInBoundsGEP(global_array, full_buf_ptr_indices, 2);
|
||||
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
|
||||
LLVMValueRef global_slice_fields[] = {
|
||||
full_buf_ptr,
|
||||
@ -2212,9 +2214,13 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
IrInstruction *op2 = bin_op_instruction->op2;
|
||||
|
||||
assert(op1->value.type == op2->value.type || op_id == IrBinOpBitShiftLeftLossy ||
|
||||
op_id == IrBinOpBitShiftLeftExact || op_id == IrBinOpBitShiftRightLossy ||
|
||||
op_id == IrBinOpBitShiftRightExact ||
|
||||
(op1->value.type->id == TypeTableEntryIdErrorSet && op2->value.type->id == TypeTableEntryIdErrorSet));
|
||||
op_id == IrBinOpBitShiftLeftExact || op_id == IrBinOpBitShiftRightLossy ||
|
||||
op_id == IrBinOpBitShiftRightExact ||
|
||||
(op1->value.type->id == TypeTableEntryIdErrorSet && op2->value.type->id == TypeTableEntryIdErrorSet) ||
|
||||
(op1->value.type->id == TypeTableEntryIdPointer &&
|
||||
(op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
|
||||
op1->value.type->data.pointer.ptr_len == PtrLenUnknown)
|
||||
);
|
||||
TypeTableEntry *type_entry = op1->value.type;
|
||||
|
||||
bool want_runtime_safety = bin_op_instruction->safety_check_on &&
|
||||
@ -2222,6 +2228,8 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
|
||||
LLVMValueRef op1_value = ir_llvm_value(g, op1);
|
||||
LLVMValueRef op2_value = ir_llvm_value(g, op2);
|
||||
|
||||
|
||||
switch (op_id) {
|
||||
case IrBinOpInvalid:
|
||||
case IrBinOpArrayCat:
|
||||
@ -2260,7 +2268,11 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
case IrBinOpAdd:
|
||||
case IrBinOpAddWrap:
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == TypeTableEntryIdPointer) {
|
||||
assert(type_entry->data.pointer.ptr_len == PtrLenUnknown);
|
||||
// TODO runtime safety
|
||||
return LLVMBuildInBoundsGEP(g->builder, op1_value, &op2_value, 1, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
|
||||
return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
@ -2323,7 +2335,12 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
case IrBinOpSub:
|
||||
case IrBinOpSubWrap:
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == TypeTableEntryIdPointer) {
|
||||
assert(type_entry->data.pointer.ptr_len == PtrLenUnknown);
|
||||
// TODO runtime safety
|
||||
LLVMValueRef subscript_value = LLVMBuildNeg(g->builder, op2_value, "");
|
||||
return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
|
||||
return LLVMBuildFSub(g->builder, op1_value, op2_value, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
@ -2770,7 +2787,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
||||
if (have_init_expr) {
|
||||
assert(var->value->type == init_value->value.type);
|
||||
TypeTableEntry *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
|
||||
var->align_bytes, 0, 0);
|
||||
PtrLenSingle, var->align_bytes, 0, 0);
|
||||
gen_assign_raw(g, var->value_ref, var_ptr_type, ir_llvm_value(g, init_value));
|
||||
} else {
|
||||
bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
|
||||
@ -4172,7 +4189,7 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable,
|
||||
uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry);
|
||||
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
|
||||
false, false, field_align_bytes,
|
||||
false, false, PtrLenSingle, field_align_bytes,
|
||||
(uint32_t)type_struct_field->packed_bits_offset, (uint32_t)type_struct_field->unaligned_bit_count);
|
||||
|
||||
gen_assign_raw(g, field_ptr, ptr_type, value);
|
||||
@ -4188,7 +4205,7 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
|
||||
|
||||
uint32_t field_align_bytes = get_abi_alignment(g, type_union_field->type_entry);
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,
|
||||
false, false, field_align_bytes,
|
||||
false, false, PtrLenSingle, field_align_bytes,
|
||||
0, 0);
|
||||
|
||||
LLVMValueRef uncasted_union_ptr;
|
||||
@ -4435,7 +4452,8 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_payload_index, "");
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, false, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *slice_type = get_slice_type(g, u8_ptr_type);
|
||||
size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, payload_ptr, ptr_field_index, "");
|
||||
@ -5377,7 +5395,8 @@ static void generate_error_name_table(CodeGen *g) {
|
||||
|
||||
assert(g->errors_by_index.length > 0);
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
|
||||
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(g->errors_by_index.length);
|
||||
@ -5415,7 +5434,8 @@ static void generate_error_name_table(CodeGen *g) {
|
||||
}
|
||||
|
||||
static void generate_enum_name_tables(CodeGen *g) {
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
|
||||
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
@ -6869,7 +6889,8 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
|
||||
TypeTableEntry *fn_type = get_test_fn_type(g);
|
||||
|
||||
|
177
src/ir.cpp
177
src/ir.cpp
@ -1009,12 +1009,13 @@ static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *so
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr,
|
||||
IrInstruction *elem_index, bool safety_check_on)
|
||||
IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len)
|
||||
{
|
||||
IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node);
|
||||
instruction->array_ptr = array_ptr;
|
||||
instruction->elem_index = elem_index;
|
||||
instruction->safety_check_on = safety_check_on;
|
||||
instruction->ptr_len = ptr_len;
|
||||
|
||||
ir_ref_instruction(array_ptr, irb->current_basic_block);
|
||||
ir_ref_instruction(elem_index, irb->current_basic_block);
|
||||
@ -1022,15 +1023,6 @@ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *s
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_elem_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
|
||||
IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on)
|
||||
{
|
||||
IrInstruction *new_instruction = ir_build_elem_ptr(irb, old_instruction->scope,
|
||||
old_instruction->source_node, array_ptr, elem_index, safety_check_on);
|
||||
ir_link_new_instruction(new_instruction, old_instruction);
|
||||
return new_instruction;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *container_ptr, IrInstruction *field_name_expr)
|
||||
{
|
||||
@ -1188,14 +1180,15 @@ static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instru
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value,
|
||||
uint32_t bit_offset_start, uint32_t bit_offset_end)
|
||||
IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,
|
||||
IrInstruction *align_value, uint32_t bit_offset_start, uint32_t bit_offset_end)
|
||||
{
|
||||
IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node);
|
||||
ptr_type_of_instruction->align_value = align_value;
|
||||
ptr_type_of_instruction->child_type = child_type;
|
||||
ptr_type_of_instruction->is_const = is_const;
|
||||
ptr_type_of_instruction->is_volatile = is_volatile;
|
||||
ptr_type_of_instruction->ptr_len = ptr_len;
|
||||
ptr_type_of_instruction->bit_offset_start = bit_offset_start;
|
||||
ptr_type_of_instruction->bit_offset_end = bit_offset_end;
|
||||
|
||||
@ -3547,7 +3540,7 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode
|
||||
return subscript_instruction;
|
||||
|
||||
IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction,
|
||||
subscript_instruction, true);
|
||||
subscript_instruction, true, PtrLenSingle);
|
||||
if (lval.is_ptr)
|
||||
return ptr_instruction;
|
||||
|
||||
@ -4626,6 +4619,11 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
|
||||
|
||||
static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||
assert(node->type == NodeTypePointerType);
|
||||
// The null check here is for C imports which don't set a token on the AST node. We could potentially
|
||||
// update that code to create a fake token and then remove this check.
|
||||
PtrLen ptr_len = (node->data.pointer_type.star_token != nullptr &&
|
||||
(node->data.pointer_type.star_token->id == TokenIdStar ||
|
||||
node->data.pointer_type.star_token->id == TokenIdStarStar)) ? PtrLenSingle : PtrLenUnknown;
|
||||
bool is_const = node->data.pointer_type.is_const;
|
||||
bool is_volatile = node->data.pointer_type.is_volatile;
|
||||
AstNode *expr_node = node->data.pointer_type.op_expr;
|
||||
@ -4675,7 +4673,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
|
||||
}
|
||||
|
||||
return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile,
|
||||
align_value, bit_offset_start, bit_offset_end);
|
||||
ptr_len, align_value, bit_offset_start, bit_offset_end);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
|
||||
@ -5172,7 +5170,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
|
||||
ir_mark_gen(ir_build_cond_br(irb, child_scope, node, cond, body_block, else_block, is_comptime));
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, body_block);
|
||||
IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false);
|
||||
IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false, PtrLenSingle);
|
||||
IrInstruction *elem_val;
|
||||
if (node->data.for_expr.elem_is_ptr) {
|
||||
elem_val = elem_ptr;
|
||||
@ -6811,9 +6809,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_normal_final);
|
||||
if (type_has_bits(return_type)) {
|
||||
IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
|
||||
get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
|
||||
false, false, PtrLenUnknown, get_abi_alignment(irb->codegen, irb->codegen->builtin_types.entry_u8),
|
||||
0, 0));
|
||||
IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
|
||||
IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, result_ptr);
|
||||
IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type,
|
||||
IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
|
||||
IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,
|
||||
irb->exec->coro_result_field_ptr);
|
||||
IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
|
||||
fn_entry->type_entry->data.fn.fn_type_id.return_type);
|
||||
@ -7691,6 +7693,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
|
||||
// pointer const
|
||||
if (expected_type->id == TypeTableEntryIdPointer &&
|
||||
actual_type->id == TypeTableEntryIdPointer &&
|
||||
(actual_type->data.pointer.ptr_len == expected_type->data.pointer.ptr_len) &&
|
||||
(!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const) &&
|
||||
(!actual_type->data.pointer.is_volatile || expected_type->data.pointer.is_volatile) &&
|
||||
actual_type->data.pointer.bit_offset == expected_type->data.pointer.bit_offset &&
|
||||
@ -8644,7 +8647,11 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
|
||||
|
||||
if (convert_to_const_slice) {
|
||||
assert(prev_inst->value.type->id == TypeTableEntryIdArray);
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, prev_inst->value.type->data.array.child_type, true);
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(
|
||||
ira->codegen, prev_inst->value.type->data.array.child_type,
|
||||
true, false, PtrLenUnknown,
|
||||
get_abi_alignment(ira->codegen, prev_inst->value.type->data.array.child_type),
|
||||
0, 0);
|
||||
TypeTableEntry *slice_type = get_slice_type(ira->codegen, ptr_type);
|
||||
if (err_set_type != nullptr) {
|
||||
return get_error_union_type(ira->codegen, err_set_type, slice_type);
|
||||
@ -8961,7 +8968,7 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
|
||||
ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile, uint32_t ptr_align)
|
||||
{
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type,
|
||||
ptr_is_const, ptr_is_volatile, ptr_align, 0, 0);
|
||||
ptr_is_const, ptr_is_volatile, PtrLenSingle, ptr_align, 0, 0);
|
||||
IrInstruction *const_instr = ir_get_const(ira, instruction);
|
||||
ConstExprValue *const_val = &const_instr->value;
|
||||
const_val->type = ptr_type;
|
||||
@ -9302,7 +9309,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
|
||||
}
|
||||
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
|
||||
is_const, is_volatile, get_abi_alignment(ira->codegen, value->value.type), 0, 0);
|
||||
is_const, is_volatile, PtrLenSingle, get_abi_alignment(ira->codegen, value->value.type), 0, 0);
|
||||
IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
|
||||
source_instruction->source_node, value, is_const, is_volatile);
|
||||
new_instruction->value.type = ptr_type;
|
||||
@ -10399,7 +10406,9 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
|
||||
if (type_is_invalid(value->value.type))
|
||||
return nullptr;
|
||||
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
|
||||
true, false, PtrLenUnknown,
|
||||
get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(ira->codegen, ptr_type);
|
||||
IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type);
|
||||
if (type_is_invalid(casted_value->value.type))
|
||||
@ -11054,11 +11063,27 @@ static TypeTableEntry *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *
|
||||
static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
|
||||
IrInstruction *op1 = bin_op_instruction->op1->other;
|
||||
IrInstruction *op2 = bin_op_instruction->op2->other;
|
||||
IrBinOp op_id = bin_op_instruction->op_id;
|
||||
|
||||
// look for pointer math
|
||||
if (op1->value.type->id == TypeTableEntryIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&
|
||||
(op_id == IrBinOpAdd || op_id == IrBinOpSub))
|
||||
{
|
||||
IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);
|
||||
if (casted_op2 == ira->codegen->invalid_instruction)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
IrInstruction *result = ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.scope,
|
||||
bin_op_instruction->base.source_node, op_id, op1, casted_op2, true);
|
||||
result->value.type = op1->value.type;
|
||||
ir_link_new_instruction(result, &bin_op_instruction->base);
|
||||
return result->value.type;
|
||||
}
|
||||
|
||||
IrInstruction *instructions[] = {op1, op2};
|
||||
TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, nullptr, instructions, 2);
|
||||
if (type_is_invalid(resolved_type))
|
||||
return resolved_type;
|
||||
IrBinOp op_id = bin_op_instruction->op_id;
|
||||
|
||||
bool is_int = resolved_type->id == TypeTableEntryIdInt || resolved_type->id == TypeTableEntryIdNumLitInt;
|
||||
bool is_float = resolved_type->id == TypeTableEntryIdFloat || resolved_type->id == TypeTableEntryIdNumLitFloat;
|
||||
@ -11331,7 +11356,8 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
|
||||
|
||||
out_array_val = out_val;
|
||||
} else if (is_slice(op1_type) || is_slice(op2_type)) {
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, child_type, true);
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
|
||||
true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, child_type), 0, 0);
|
||||
result_type = get_slice_type(ira->codegen, ptr_type);
|
||||
out_array_val = create_const_vals(1);
|
||||
out_array_val->special = ConstValSpecialStatic;
|
||||
@ -11351,7 +11377,9 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
|
||||
} else {
|
||||
new_len += 1; // null byte
|
||||
|
||||
result_type = get_pointer_to_type(ira->codegen, child_type, true);
|
||||
// TODO make this `[*]null T` instead of `[*]T`
|
||||
result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(ira->codegen, child_type), 0, 0);
|
||||
|
||||
out_array_val = create_const_vals(1);
|
||||
out_array_val->special = ConstValSpecialStatic;
|
||||
@ -12173,7 +12201,7 @@ no_mem_slot:
|
||||
IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
|
||||
instruction->scope, instruction->source_node, var);
|
||||
var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,
|
||||
var->src_is_const, is_volatile, var->align_bytes, 0, 0);
|
||||
var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
|
||||
type_ensure_zero_bits_known(ira->codegen, var->value->type);
|
||||
|
||||
bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
|
||||
@ -12352,7 +12380,9 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
|
||||
|
||||
IrInstruction *casted_new_stack = nullptr;
|
||||
if (call_instruction->new_stack != nullptr) {
|
||||
TypeTableEntry *u8_ptr = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false);
|
||||
TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
|
||||
false, false, PtrLenUnknown,
|
||||
get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *u8_slice = get_slice_type(ira->codegen, u8_ptr);
|
||||
IrInstruction *new_stack = call_instruction->new_stack->other;
|
||||
if (type_is_invalid(new_stack->value.type))
|
||||
@ -13112,10 +13142,21 @@ static TypeTableEntry *adjust_ptr_align(CodeGen *g, TypeTableEntry *ptr_type, ui
|
||||
return get_pointer_to_type_extra(g,
|
||||
ptr_type->data.pointer.child_type,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
|
||||
ptr_type->data.pointer.ptr_len,
|
||||
new_align,
|
||||
ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count);
|
||||
}
|
||||
|
||||
static TypeTableEntry *adjust_ptr_len(CodeGen *g, TypeTableEntry *ptr_type, PtrLen ptr_len) {
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
return get_pointer_to_type_extra(g,
|
||||
ptr_type->data.pointer.child_type,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
|
||||
ptr_len,
|
||||
ptr_type->data.pointer.alignment,
|
||||
ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count);
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {
|
||||
IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other;
|
||||
if (type_is_invalid(array_ptr->value.type))
|
||||
@ -13146,6 +13187,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
|
||||
if (ptr_type->data.pointer.unaligned_bit_count == 0) {
|
||||
return_type = get_pointer_to_type_extra(ira->codegen, child_type,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
|
||||
elem_ptr_instruction->ptr_len,
|
||||
ptr_type->data.pointer.alignment, 0, 0);
|
||||
} else {
|
||||
uint64_t elem_val_scalar;
|
||||
@ -13157,12 +13199,19 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
|
||||
|
||||
return_type = get_pointer_to_type_extra(ira->codegen, child_type,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
|
||||
elem_ptr_instruction->ptr_len,
|
||||
1, (uint32_t)bit_offset, (uint32_t)bit_width);
|
||||
}
|
||||
} else if (array_type->id == TypeTableEntryIdPointer) {
|
||||
return_type = array_type;
|
||||
if (array_type->data.pointer.ptr_len == PtrLenSingle) {
|
||||
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
|
||||
buf_sprintf("indexing not allowed on pointer to single item"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len);
|
||||
} else if (is_slice(array_type)) {
|
||||
return_type = array_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
return_type = adjust_ptr_len(ira->codegen, array_type->data.structure.fields[slice_ptr_index].type_entry,
|
||||
elem_ptr_instruction->ptr_len);
|
||||
} else if (array_type->id == TypeTableEntryIdArgTuple) {
|
||||
ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
|
||||
if (!ptr_val)
|
||||
@ -13304,8 +13353,10 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
|
||||
} else if (is_slice(array_type)) {
|
||||
ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];
|
||||
if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
|
||||
ir_build_elem_ptr_from(&ira->new_irb, &elem_ptr_instruction->base, array_ptr,
|
||||
casted_elem_index, false);
|
||||
IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,
|
||||
array_ptr, casted_elem_index, false, elem_ptr_instruction->ptr_len);
|
||||
result->value.type = return_type;
|
||||
ir_link_new_instruction(result, &elem_ptr_instruction->base);
|
||||
return return_type;
|
||||
}
|
||||
ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
|
||||
@ -13373,8 +13424,10 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
|
||||
}
|
||||
}
|
||||
|
||||
ir_build_elem_ptr_from(&ira->new_irb, &elem_ptr_instruction->base, array_ptr,
|
||||
casted_elem_index, safety_check_on);
|
||||
IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,
|
||||
array_ptr, casted_elem_index, safety_check_on, elem_ptr_instruction->ptr_len);
|
||||
result->value.type = return_type;
|
||||
ir_link_new_instruction(result, &elem_ptr_instruction->base);
|
||||
return return_type;
|
||||
}
|
||||
|
||||
@ -13449,7 +13502,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
|
||||
return ira->codegen->invalid_instruction;
|
||||
ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type,
|
||||
is_const, is_volatile, align_bytes,
|
||||
is_const, is_volatile, PtrLenSingle, align_bytes,
|
||||
(uint32_t)(ptr_bit_offset + field->packed_bits_offset),
|
||||
(uint32_t)unaligned_bit_count_for_result_type);
|
||||
IrInstruction *result = ir_get_const(ira, source_instr);
|
||||
@ -13465,6 +13518,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
|
||||
IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
|
||||
container_ptr, field);
|
||||
result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
|
||||
PtrLenSingle,
|
||||
align_bytes,
|
||||
(uint32_t)(ptr_bit_offset + field->packed_bits_offset),
|
||||
(uint32_t)unaligned_bit_count_for_result_type);
|
||||
@ -13511,7 +13565,9 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
|
||||
payload_val->type = field_type;
|
||||
}
|
||||
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, is_const, is_volatile,
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
|
||||
is_const, is_volatile,
|
||||
PtrLenSingle,
|
||||
get_abi_alignment(ira->codegen, field_type), 0, 0);
|
||||
|
||||
IrInstruction *result = ir_get_const(ira, source_instr);
|
||||
@ -13526,7 +13582,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
|
||||
|
||||
IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
|
||||
result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
|
||||
get_abi_alignment(ira->codegen, field->type_entry), 0, 0);
|
||||
PtrLenSingle, get_abi_alignment(ira->codegen, field->type_entry), 0, 0);
|
||||
return result;
|
||||
} else {
|
||||
return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
|
||||
@ -14119,7 +14175,7 @@ static TypeTableEntry *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
|
||||
if (type_entry->id == TypeTableEntryIdArray) {
|
||||
ptr_type = get_pointer_to_type(ira->codegen, type_entry->data.array.child_type, false);
|
||||
} else if (is_slice(type_entry)) {
|
||||
ptr_type = type_entry->data.structure.fields[0].type_entry;
|
||||
ptr_type = adjust_ptr_len(ira->codegen, type_entry->data.structure.fields[0].type_entry, PtrLenSingle);
|
||||
} else if (type_entry->id == TypeTableEntryIdArgTuple) {
|
||||
ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);
|
||||
if (!arg_tuple_val)
|
||||
@ -14367,7 +14423,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
|
||||
{
|
||||
type_ensure_zero_bits_known(ira->codegen, child_type);
|
||||
TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
|
||||
is_const, is_volatile, align_bytes, 0, 0);
|
||||
is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0);
|
||||
TypeTableEntry *result_type = get_slice_type(ira->codegen, slice_ptr_type);
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base);
|
||||
out_val->data.x_type = result_type;
|
||||
@ -14619,6 +14675,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
|
||||
PtrLenSingle,
|
||||
get_abi_alignment(ira->codegen, child_type), 0, 0);
|
||||
|
||||
if (instr_is_comptime(value)) {
|
||||
@ -15566,7 +15623,8 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc
|
||||
if (type_is_invalid(casted_value->value.type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
|
||||
true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(ira->codegen, u8_ptr_type);
|
||||
if (casted_value->value.special == ConstValSpecialStatic) {
|
||||
ErrorTableEntry *err = casted_value->value.data.x_err_set;
|
||||
@ -15607,7 +15665,11 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn
|
||||
IrInstruction *result = ir_build_tag_name(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node, target);
|
||||
ir_link_new_instruction(result, &instruction->base);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(
|
||||
ira->codegen, ira->codegen->builtin_types.entry_u8,
|
||||
true, false, PtrLenUnknown,
|
||||
get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8),
|
||||
0, 0);
|
||||
result->value.type = get_slice_type(ira->codegen, u8_ptr_type);
|
||||
return result->value.type;
|
||||
}
|
||||
@ -15660,6 +15722,7 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
|
||||
TypeTableEntry *field_ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
|
||||
field_ptr->value.type->data.pointer.is_const,
|
||||
field_ptr->value.type->data.pointer.is_volatile,
|
||||
PtrLenSingle,
|
||||
field_ptr_align, 0, 0);
|
||||
IrInstruction *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type);
|
||||
if (type_is_invalid(casted_field_ptr->value.type))
|
||||
@ -15668,6 +15731,7 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
|
||||
TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, container_type,
|
||||
casted_field_ptr->value.type->data.pointer.is_const,
|
||||
casted_field_ptr->value.type->data.pointer.is_volatile,
|
||||
PtrLenSingle,
|
||||
parent_ptr_align, 0, 0);
|
||||
|
||||
if (instr_is_comptime(casted_field_ptr)) {
|
||||
@ -15983,11 +16047,13 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop
|
||||
// lib_name: ?[]const u8
|
||||
ensure_field_index(fn_def_val->type, "lib_name", 6);
|
||||
fn_def_fields[6].special = ConstValSpecialStatic;
|
||||
fn_def_fields[6].type = get_maybe_type(ira->codegen,
|
||||
get_slice_type(ira->codegen, get_pointer_to_type(ira->codegen,
|
||||
ira->codegen->builtin_types.entry_u8, true)));
|
||||
if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0)
|
||||
{
|
||||
TypeTableEntry *u8_ptr = get_pointer_to_type_extra(
|
||||
ira->codegen, ira->codegen->builtin_types.entry_u8,
|
||||
true, false, PtrLenUnknown,
|
||||
get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8),
|
||||
0, 0);
|
||||
fn_def_fields[6].type = get_maybe_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
|
||||
if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {
|
||||
fn_def_fields[6].data.x_maybe = create_const_vals(1);
|
||||
ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name);
|
||||
init_const_slice(ira->codegen, fn_def_fields[6].data.x_maybe, lib_name, 0, buf_len(fn_node->lib_name), true);
|
||||
@ -16009,8 +16075,8 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop
|
||||
size_t fn_arg_count = fn_entry->variable_list.length;
|
||||
ConstExprValue *fn_arg_name_array = create_const_vals(1);
|
||||
fn_arg_name_array->special = ConstValSpecialStatic;
|
||||
fn_arg_name_array->type = get_array_type(ira->codegen, get_slice_type(ira->codegen,
|
||||
get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true)), fn_arg_count);
|
||||
fn_arg_name_array->type = get_array_type(ira->codegen,
|
||||
get_slice_type(ira->codegen, u8_ptr), fn_arg_count);
|
||||
fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
|
||||
fn_arg_name_array->data.x_array.s_none.parent.id = ConstParentIdNone;
|
||||
fn_arg_name_array->data.x_array.s_none.elements = create_const_vals(fn_arg_count);
|
||||
@ -17088,7 +17154,8 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi
|
||||
TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8;
|
||||
uint32_t dest_align = (dest_uncasted_type->id == TypeTableEntryIdPointer) ?
|
||||
dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);
|
||||
TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, dest_align, 0, 0);
|
||||
TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
|
||||
PtrLenUnknown, dest_align, 0, 0);
|
||||
|
||||
IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr);
|
||||
if (type_is_invalid(casted_dest_ptr->value.type))
|
||||
@ -17184,8 +17251,10 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi
|
||||
src_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);
|
||||
|
||||
TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize;
|
||||
TypeTableEntry *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, dest_align, 0, 0);
|
||||
TypeTableEntry *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile, src_align, 0, 0);
|
||||
TypeTableEntry *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
|
||||
PtrLenUnknown, dest_align, 0, 0);
|
||||
TypeTableEntry *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile,
|
||||
PtrLenUnknown, src_align, 0, 0);
|
||||
|
||||
IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut);
|
||||
if (type_is_invalid(casted_dest_ptr->value.type))
|
||||
@ -17333,11 +17402,13 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
|
||||
TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,
|
||||
ptr_type->data.pointer.is_const || is_comptime_const,
|
||||
ptr_type->data.pointer.is_volatile,
|
||||
PtrLenUnknown,
|
||||
byte_alignment, 0, 0);
|
||||
return_type = get_slice_type(ira->codegen, slice_ptr_type);
|
||||
} else if (array_type->id == TypeTableEntryIdPointer) {
|
||||
TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type,
|
||||
array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
|
||||
PtrLenUnknown,
|
||||
array_type->data.pointer.alignment, 0, 0);
|
||||
return_type = get_slice_type(ira->codegen, slice_ptr_type);
|
||||
if (!end) {
|
||||
@ -17774,6 +17845,7 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst
|
||||
if (result_ptr->value.type->id == TypeTableEntryIdPointer) {
|
||||
expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type,
|
||||
false, result_ptr->value.type->data.pointer.is_volatile,
|
||||
PtrLenSingle,
|
||||
result_ptr->value.type->data.pointer.alignment, 0, 0);
|
||||
} else {
|
||||
expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false);
|
||||
@ -17929,6 +18001,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
|
||||
TypeTableEntry *payload_type = type_entry->data.error_union.payload_type;
|
||||
TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
|
||||
PtrLenSingle,
|
||||
get_abi_alignment(ira->codegen, payload_type), 0, 0);
|
||||
if (instr_is_comptime(value)) {
|
||||
ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
|
||||
@ -18270,7 +18343,8 @@ static TypeTableEntry *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructio
|
||||
return ir_unreach_error(ira);
|
||||
}
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true);
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
|
||||
true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(ira->codegen, u8_ptr_type);
|
||||
IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type);
|
||||
if (type_is_invalid(casted_msg->value.type))
|
||||
@ -18801,7 +18875,8 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruc
|
||||
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
|
||||
out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type,
|
||||
instruction->is_const, instruction->is_volatile, align_bytes,
|
||||
instruction->is_const, instruction->is_volatile,
|
||||
instruction->ptr_len, align_bytes,
|
||||
instruction->bit_offset_start, instruction->bit_offset_end - instruction->bit_offset_start);
|
||||
|
||||
return ira->codegen->builtin_types.entry_type;
|
||||
|
@ -1225,6 +1225,7 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,
|
||||
AstNode *child_node = ast_parse_pointer_type(pc, token_index, token);
|
||||
child_node->column += 1;
|
||||
AstNode *parent_node = ast_create_node(pc, NodeTypePointerType, token);
|
||||
parent_node->data.pointer_type.star_token = token;
|
||||
parent_node->data.pointer_type.op_expr = child_node;
|
||||
return parent_node;
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ pub const Buffer = struct {
|
||||
}
|
||||
|
||||
/// For passing to C functions.
|
||||
pub fn ptr(self: *const Buffer) *u8 {
|
||||
pub fn ptr(self: *const Buffer) [*]u8 {
|
||||
return self.list.items.ptr;
|
||||
}
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
extern "c" fn __error() *c_int;
|
||||
pub extern "c" fn _NSGetExecutablePath(buf: *u8, bufsize: *u32) c_int;
|
||||
pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;
|
||||
|
||||
pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: *u8, buf_len: usize, basep: *i64) usize;
|
||||
pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: [*]u8, buf_len: usize, basep: *i64) usize;
|
||||
|
||||
pub extern "c" fn mach_absolute_time() u64;
|
||||
pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) void;
|
||||
|
@ -9,6 +9,8 @@ pub use switch (builtin.os) {
|
||||
};
|
||||
const empty_import = @import("../empty.zig");
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/265 on this whole file
|
||||
|
||||
pub extern "c" fn abort() noreturn;
|
||||
pub extern "c" fn exit(code: c_int) noreturn;
|
||||
pub extern "c" fn isatty(fd: c_int) c_int;
|
||||
@ -16,45 +18,45 @@ pub extern "c" fn close(fd: c_int) c_int;
|
||||
pub extern "c" fn fstat(fd: c_int, buf: *Stat) c_int;
|
||||
pub extern "c" fn @"fstat$INODE64"(fd: c_int, buf: *Stat) c_int;
|
||||
pub extern "c" fn lseek(fd: c_int, offset: isize, whence: c_int) isize;
|
||||
pub extern "c" fn open(path: *const u8, oflag: c_int, ...) c_int;
|
||||
pub extern "c" fn open(path: [*]const u8, oflag: c_int, ...) c_int;
|
||||
pub extern "c" fn raise(sig: c_int) c_int;
|
||||
pub extern "c" fn read(fd: c_int, buf: *c_void, nbyte: usize) isize;
|
||||
pub extern "c" fn stat(noalias path: *const u8, noalias buf: *Stat) c_int;
|
||||
pub extern "c" fn write(fd: c_int, buf: *const c_void, nbyte: usize) isize;
|
||||
pub extern "c" fn mmap(addr: ?*c_void, len: usize, prot: c_int, flags: c_int, fd: c_int, offset: isize) ?*c_void;
|
||||
pub extern "c" fn munmap(addr: *c_void, len: usize) c_int;
|
||||
pub extern "c" fn unlink(path: *const u8) c_int;
|
||||
pub extern "c" fn getcwd(buf: *u8, size: usize) ?*u8;
|
||||
pub extern "c" fn read(fd: c_int, buf: [*]c_void, nbyte: usize) isize;
|
||||
pub extern "c" fn stat(noalias path: [*]const u8, noalias buf: *Stat) c_int;
|
||||
pub extern "c" fn write(fd: c_int, buf: [*]const c_void, nbyte: usize) isize;
|
||||
pub extern "c" fn mmap(addr: ?[*]c_void, len: usize, prot: c_int, flags: c_int, fd: c_int, offset: isize) ?[*]c_void;
|
||||
pub extern "c" fn munmap(addr: [*]c_void, len: usize) c_int;
|
||||
pub extern "c" fn unlink(path: [*]const u8) c_int;
|
||||
pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8;
|
||||
pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_int, options: c_int) c_int;
|
||||
pub extern "c" fn fork() c_int;
|
||||
pub extern "c" fn access(path: *const u8, mode: c_uint) c_int;
|
||||
pub extern "c" fn pipe(fds: *c_int) c_int;
|
||||
pub extern "c" fn mkdir(path: *const u8, mode: c_uint) c_int;
|
||||
pub extern "c" fn symlink(existing: *const u8, new: *const u8) c_int;
|
||||
pub extern "c" fn rename(old: *const u8, new: *const u8) c_int;
|
||||
pub extern "c" fn chdir(path: *const u8) c_int;
|
||||
pub extern "c" fn execve(path: *const u8, argv: *const ?*const u8, envp: *const ?*const u8) c_int;
|
||||
pub extern "c" fn access(path: [*]const u8, mode: c_uint) c_int;
|
||||
pub extern "c" fn pipe(fds: *[2]c_int) c_int;
|
||||
pub extern "c" fn mkdir(path: [*]const u8, mode: c_uint) c_int;
|
||||
pub extern "c" fn symlink(existing: [*]const u8, new: [*]const u8) c_int;
|
||||
pub extern "c" fn rename(old: [*]const u8, new: [*]const u8) c_int;
|
||||
pub extern "c" fn chdir(path: [*]const u8) c_int;
|
||||
pub extern "c" fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) c_int;
|
||||
pub extern "c" fn dup(fd: c_int) c_int;
|
||||
pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;
|
||||
pub extern "c" fn readlink(noalias path: *const u8, noalias buf: *u8, bufsize: usize) isize;
|
||||
pub extern "c" fn realpath(noalias file_name: *const u8, noalias resolved_name: *u8) ?*u8;
|
||||
pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;
|
||||
pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;
|
||||
pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;
|
||||
pub extern "c" fn gettimeofday(tv: ?*timeval, tz: ?*timezone) c_int;
|
||||
pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;
|
||||
pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;
|
||||
pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;
|
||||
pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int;
|
||||
pub extern "c" fn rmdir(path: *const u8) c_int;
|
||||
pub extern "c" fn rmdir(path: [*]const u8) c_int;
|
||||
|
||||
pub extern "c" fn aligned_alloc(alignment: usize, size: usize) ?*c_void;
|
||||
pub extern "c" fn malloc(usize) ?*c_void;
|
||||
pub extern "c" fn realloc(*c_void, usize) ?*c_void;
|
||||
pub extern "c" fn free(*c_void) void;
|
||||
pub extern "c" fn posix_memalign(memptr: **c_void, alignment: usize, size: usize) c_int;
|
||||
pub extern "c" fn aligned_alloc(alignment: usize, size: usize) ?[*]c_void;
|
||||
pub extern "c" fn malloc(usize) ?[*]c_void;
|
||||
pub extern "c" fn realloc([*]c_void, usize) ?[*]c_void;
|
||||
pub extern "c" fn free([*]c_void) void;
|
||||
pub extern "c" fn posix_memalign(memptr: *[*]c_void, alignment: usize, size: usize) c_int;
|
||||
|
||||
pub extern "pthread" fn pthread_create(noalias newthread: *pthread_t, noalias attr: ?*const pthread_attr_t, start_routine: extern fn (?*c_void) ?*c_void, noalias arg: ?*c_void) c_int;
|
||||
pub extern "pthread" fn pthread_attr_init(attr: *pthread_attr_t) c_int;
|
||||
pub extern "pthread" fn pthread_attr_setstack(attr: *pthread_attr_t, stackaddr: *c_void, stacksize: usize) c_int;
|
||||
pub extern "pthread" fn pthread_attr_setstack(attr: *pthread_attr_t, stackaddr: [*]c_void, stacksize: usize) c_int;
|
||||
pub extern "pthread" fn pthread_attr_destroy(attr: *pthread_attr_t) c_int;
|
||||
pub extern "pthread" fn pthread_join(thread: pthread_t, arg_return: ?*?*c_void) c_int;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
pub use @import("../os/linux/errno.zig");
|
||||
|
||||
pub extern "c" fn getrandom(buf_ptr: *u8, buf_len: usize, flags: c_uint) c_int;
|
||||
pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;
|
||||
extern "c" fn __errno_location() *c_int;
|
||||
pub const _errno = __errno_location;
|
||||
|
||||
|
10
std/cstr.zig
10
std/cstr.zig
@ -57,7 +57,7 @@ pub fn addNullByte(allocator: *mem.Allocator, slice: []const u8) ![]u8 {
|
||||
pub const NullTerminated2DArray = struct {
|
||||
allocator: *mem.Allocator,
|
||||
byte_count: usize,
|
||||
ptr: ?*?*u8,
|
||||
ptr: ?[*]?[*]u8,
|
||||
|
||||
/// Takes N lists of strings, concatenates the lists together, and adds a null terminator
|
||||
/// Caller must deinit result
|
||||
@ -79,12 +79,12 @@ pub const NullTerminated2DArray = struct {
|
||||
errdefer allocator.free(buf);
|
||||
|
||||
var write_index = index_size;
|
||||
const index_buf = ([]?*u8)(buf);
|
||||
const index_buf = ([]?[*]u8)(buf);
|
||||
|
||||
var i: usize = 0;
|
||||
for (slices) |slice| {
|
||||
for (slice) |inner| {
|
||||
index_buf[i] = &buf[write_index];
|
||||
index_buf[i] = buf.ptr + write_index;
|
||||
i += 1;
|
||||
mem.copy(u8, buf[write_index..], inner);
|
||||
write_index += inner.len;
|
||||
@ -97,12 +97,12 @@ pub const NullTerminated2DArray = struct {
|
||||
return NullTerminated2DArray{
|
||||
.allocator = allocator,
|
||||
.byte_count = byte_count,
|
||||
.ptr = @ptrCast(?*?*u8, buf.ptr),
|
||||
.ptr = @ptrCast(?[*]?[*]u8, buf.ptr),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *NullTerminated2DArray) void {
|
||||
const buf = @ptrCast(*u8, self.ptr);
|
||||
const buf = @ptrCast([*]u8, self.ptr);
|
||||
self.allocator.free(buf[0..self.byte_count]);
|
||||
}
|
||||
};
|
||||
|
18
std/heap.zig
18
std/heap.zig
@ -18,11 +18,11 @@ var c_allocator_state = Allocator{
|
||||
|
||||
fn cAlloc(self: *Allocator, n: usize, alignment: u29) ![]u8 {
|
||||
assert(alignment <= @alignOf(c_longdouble));
|
||||
return if (c.malloc(n)) |buf| @ptrCast(*u8, buf)[0..n] else error.OutOfMemory;
|
||||
return if (c.malloc(n)) |buf| @ptrCast([*]u8, buf)[0..n] else error.OutOfMemory;
|
||||
}
|
||||
|
||||
fn cRealloc(self: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
|
||||
const old_ptr = @ptrCast(*c_void, old_mem.ptr);
|
||||
const old_ptr = @ptrCast([*]c_void, old_mem.ptr);
|
||||
if (c.realloc(old_ptr, new_size)) |buf| {
|
||||
return @ptrCast(*u8, buf)[0..new_size];
|
||||
} else if (new_size <= old_mem.len) {
|
||||
@ -33,7 +33,7 @@ fn cRealloc(self: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![
|
||||
}
|
||||
|
||||
fn cFree(self: *Allocator, old_mem: []u8) void {
|
||||
const old_ptr = @ptrCast(*c_void, old_mem.ptr);
|
||||
const old_ptr = @ptrCast([*]c_void, old_mem.ptr);
|
||||
c.free(old_ptr);
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ pub const DirectAllocator = struct {
|
||||
const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0);
|
||||
if (addr == p.MAP_FAILED) return error.OutOfMemory;
|
||||
|
||||
if (alloc_size == n) return @intToPtr(*u8, addr)[0..n];
|
||||
if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];
|
||||
|
||||
var aligned_addr = addr & ~usize(alignment - 1);
|
||||
aligned_addr += alignment;
|
||||
@ -93,7 +93,7 @@ pub const DirectAllocator = struct {
|
||||
//It is impossible that there is an unoccupied page at the top of our
|
||||
// mmap.
|
||||
|
||||
return @intToPtr(*u8, aligned_addr)[0..n];
|
||||
return @intToPtr([*]u8, aligned_addr)[0..n];
|
||||
},
|
||||
Os.windows => {
|
||||
const amt = n + alignment + @sizeOf(usize);
|
||||
@ -109,7 +109,7 @@ pub const DirectAllocator = struct {
|
||||
const adjusted_addr = root_addr + march_forward_bytes;
|
||||
const record_addr = adjusted_addr + n;
|
||||
@intToPtr(*align(1) usize, record_addr).* = root_addr;
|
||||
return @intToPtr(*u8, adjusted_addr)[0..n];
|
||||
return @intToPtr([*]u8, adjusted_addr)[0..n];
|
||||
},
|
||||
else => @compileError("Unsupported OS"),
|
||||
}
|
||||
@ -140,7 +140,7 @@ pub const DirectAllocator = struct {
|
||||
const old_adjusted_addr = @ptrToInt(old_mem.ptr);
|
||||
const old_record_addr = old_adjusted_addr + old_mem.len;
|
||||
const root_addr = @intToPtr(*align(1) usize, old_record_addr).*;
|
||||
const old_ptr = @intToPtr(os.windows.LPVOID, root_addr);
|
||||
const old_ptr = @intToPtr([*]c_void, root_addr);
|
||||
const amt = new_size + alignment + @sizeOf(usize);
|
||||
const new_ptr = os.windows.HeapReAlloc(??self.heap_handle, 0, old_ptr, amt) ?? blk: {
|
||||
if (new_size > old_mem.len) return error.OutOfMemory;
|
||||
@ -154,7 +154,7 @@ pub const DirectAllocator = struct {
|
||||
assert(new_adjusted_addr % alignment == 0);
|
||||
const new_record_addr = new_adjusted_addr + new_size;
|
||||
@intToPtr(*align(1) usize, new_record_addr).* = new_root_addr;
|
||||
return @intToPtr(*u8, new_adjusted_addr)[0..new_size];
|
||||
return @intToPtr([*]u8, new_adjusted_addr)[0..new_size];
|
||||
},
|
||||
else => @compileError("Unsupported OS"),
|
||||
}
|
||||
@ -170,7 +170,7 @@ pub const DirectAllocator = struct {
|
||||
Os.windows => {
|
||||
const record_addr = @ptrToInt(bytes.ptr) + bytes.len;
|
||||
const root_addr = @intToPtr(*align(1) usize, record_addr).*;
|
||||
const ptr = @intToPtr(os.windows.LPVOID, root_addr);
|
||||
const ptr = @intToPtr([*]c_void, root_addr);
|
||||
_ = os.windows.HeapFree(??self.heap_handle, 0, ptr);
|
||||
},
|
||||
else => @compileError("Unsupported OS"),
|
||||
|
@ -639,7 +639,7 @@ pub const ChildProcess = struct {
|
||||
}
|
||||
};
|
||||
|
||||
fn windowsCreateProcess(app_name: *u8, cmd_line: *u8, envp_ptr: ?*u8, cwd_ptr: ?*u8, lpStartupInfo: *windows.STARTUPINFOA, lpProcessInformation: *windows.PROCESS_INFORMATION) !void {
|
||||
fn windowsCreateProcess(app_name: [*]u8, cmd_line: [*]u8, envp_ptr: ?[*]u8, cwd_ptr: ?[*]u8, lpStartupInfo: *windows.STARTUPINFOA, lpProcessInformation: *windows.PROCESS_INFORMATION) !void {
|
||||
if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, @ptrCast(?*c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) {
|
||||
const err = windows.GetLastError();
|
||||
return switch (err) {
|
||||
|
@ -317,7 +317,8 @@ pub fn lseek(fd: i32, offset: isize, whence: c_int) usize {
|
||||
return errnoWrap(c.lseek(fd, offset, whence));
|
||||
}
|
||||
|
||||
pub fn open(path: *const u8, flags: u32, mode: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265 on the whole file
|
||||
pub fn open(path: [*]const u8, flags: u32, mode: usize) usize {
|
||||
return errnoWrap(c.open(path, @bitCast(c_int, flags), mode));
|
||||
}
|
||||
|
||||
@ -325,33 +326,33 @@ pub fn raise(sig: i32) usize {
|
||||
return errnoWrap(c.raise(sig));
|
||||
}
|
||||
|
||||
pub fn read(fd: i32, buf: *u8, nbyte: usize) usize {
|
||||
return errnoWrap(c.read(fd, @ptrCast(*c_void, buf), nbyte));
|
||||
pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize {
|
||||
return errnoWrap(c.read(fd, @ptrCast([*]c_void, buf), nbyte));
|
||||
}
|
||||
|
||||
pub fn stat(noalias path: *const u8, noalias buf: *stat) usize {
|
||||
pub fn stat(noalias path: [*]const u8, noalias buf: *stat) usize {
|
||||
return errnoWrap(c.stat(path, buf));
|
||||
}
|
||||
|
||||
pub fn write(fd: i32, buf: *const u8, nbyte: usize) usize {
|
||||
return errnoWrap(c.write(fd, @ptrCast(*const c_void, buf), nbyte));
|
||||
pub fn write(fd: i32, buf: [*]const u8, nbyte: usize) usize {
|
||||
return errnoWrap(c.write(fd, @ptrCast([*]const c_void, buf), nbyte));
|
||||
}
|
||||
|
||||
pub fn mmap(address: ?*u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
|
||||
const ptr_result = c.mmap(@ptrCast(*c_void, address), length, @bitCast(c_int, c_uint(prot)), @bitCast(c_int, c_uint(flags)), fd, offset);
|
||||
pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
|
||||
const ptr_result = c.mmap(@ptrCast([*]c_void, address), length, @bitCast(c_int, c_uint(prot)), @bitCast(c_int, c_uint(flags)), fd, offset);
|
||||
const isize_result = @bitCast(isize, @ptrToInt(ptr_result));
|
||||
return errnoWrap(isize_result);
|
||||
}
|
||||
|
||||
pub fn munmap(address: usize, length: usize) usize {
|
||||
return errnoWrap(c.munmap(@intToPtr(*c_void, address), length));
|
||||
return errnoWrap(c.munmap(@intToPtr([*]c_void, address), length));
|
||||
}
|
||||
|
||||
pub fn unlink(path: *const u8) usize {
|
||||
pub fn unlink(path: [*]const u8) usize {
|
||||
return errnoWrap(c.unlink(path));
|
||||
}
|
||||
|
||||
pub fn getcwd(buf: *u8, size: usize) usize {
|
||||
pub fn getcwd(buf: [*]u8, size: usize) usize {
|
||||
return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(c._errno().*)) else 0;
|
||||
}
|
||||
|
||||
@ -364,40 +365,40 @@ pub fn fork() usize {
|
||||
return errnoWrap(c.fork());
|
||||
}
|
||||
|
||||
pub fn access(path: *const u8, mode: u32) usize {
|
||||
pub fn access(path: [*]const u8, mode: u32) usize {
|
||||
return errnoWrap(c.access(path, mode));
|
||||
}
|
||||
|
||||
pub fn pipe(fds: *[2]i32) usize {
|
||||
comptime assert(i32.bit_count == c_int.bit_count);
|
||||
return errnoWrap(c.pipe(@ptrCast(*c_int, fds)));
|
||||
return errnoWrap(c.pipe(@ptrCast(*[2]c_int, fds)));
|
||||
}
|
||||
|
||||
pub fn getdirentries64(fd: i32, buf_ptr: *u8, buf_len: usize, basep: *i64) usize {
|
||||
pub fn getdirentries64(fd: i32, buf_ptr: [*]u8, buf_len: usize, basep: *i64) usize {
|
||||
return errnoWrap(@bitCast(isize, c.__getdirentries64(fd, buf_ptr, buf_len, basep)));
|
||||
}
|
||||
|
||||
pub fn mkdir(path: *const u8, mode: u32) usize {
|
||||
pub fn mkdir(path: [*]const u8, mode: u32) usize {
|
||||
return errnoWrap(c.mkdir(path, mode));
|
||||
}
|
||||
|
||||
pub fn symlink(existing: *const u8, new: *const u8) usize {
|
||||
pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
|
||||
return errnoWrap(c.symlink(existing, new));
|
||||
}
|
||||
|
||||
pub fn rename(old: *const u8, new: *const u8) usize {
|
||||
pub fn rename(old: [*]const u8, new: [*]const u8) usize {
|
||||
return errnoWrap(c.rename(old, new));
|
||||
}
|
||||
|
||||
pub fn rmdir(path: *const u8) usize {
|
||||
pub fn rmdir(path: [*]const u8) usize {
|
||||
return errnoWrap(c.rmdir(path));
|
||||
}
|
||||
|
||||
pub fn chdir(path: *const u8) usize {
|
||||
pub fn chdir(path: [*]const u8) usize {
|
||||
return errnoWrap(c.chdir(path));
|
||||
}
|
||||
|
||||
pub fn execve(path: *const u8, argv: *const ?*const u8, envp: *const ?*const u8) usize {
|
||||
pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
|
||||
return errnoWrap(c.execve(path, argv, envp));
|
||||
}
|
||||
|
||||
@ -405,7 +406,7 @@ pub fn dup2(old: i32, new: i32) usize {
|
||||
return errnoWrap(c.dup2(old, new));
|
||||
}
|
||||
|
||||
pub fn readlink(noalias path: *const u8, noalias buf_ptr: *u8, buf_len: usize) usize {
|
||||
pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
|
||||
return errnoWrap(c.readlink(path, buf_ptr, buf_len));
|
||||
}
|
||||
|
||||
@ -417,7 +418,7 @@ pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
|
||||
return errnoWrap(c.nanosleep(req, rem));
|
||||
}
|
||||
|
||||
pub fn realpath(noalias filename: *const u8, noalias resolved_name: *u8) usize {
|
||||
pub fn realpath(noalias filename: [*]const u8, noalias resolved_name: [*]u8) usize {
|
||||
return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(c._errno().*)) else 0;
|
||||
}
|
||||
|
||||
|
@ -313,7 +313,7 @@ pub const File = struct {
|
||||
if (is_posix) {
|
||||
var index: usize = 0;
|
||||
while (index < buffer.len) {
|
||||
const amt_read = posix.read(self.handle, &buffer[index], buffer.len - index);
|
||||
const amt_read = posix.read(self.handle, buffer.ptr + index, buffer.len - index);
|
||||
const read_err = posix.getErrno(amt_read);
|
||||
if (read_err > 0) {
|
||||
switch (read_err) {
|
||||
@ -334,7 +334,7 @@ pub const File = struct {
|
||||
while (index < buffer.len) {
|
||||
const want_read_count = windows.DWORD(math.min(windows.DWORD(@maxValue(windows.DWORD)), buffer.len - index));
|
||||
var amt_read: windows.DWORD = undefined;
|
||||
if (windows.ReadFile(self.handle, @ptrCast(*c_void, &buffer[index]), want_read_count, &amt_read, null) == 0) {
|
||||
if (windows.ReadFile(self.handle, @ptrCast([*]c_void, buffer.ptr + index), want_read_count, &amt_read, null) == 0) {
|
||||
const err = windows.GetLastError();
|
||||
return switch (err) {
|
||||
windows.ERROR.OPERATION_ABORTED => continue,
|
||||
|
101
std/os/index.zig
101
std/os/index.zig
@ -134,20 +134,7 @@ pub fn getRandomBytes(buf: []u8) !void {
|
||||
}
|
||||
},
|
||||
Os.zen => {
|
||||
const randomness = []u8{
|
||||
42,
|
||||
1,
|
||||
7,
|
||||
12,
|
||||
22,
|
||||
17,
|
||||
99,
|
||||
16,
|
||||
26,
|
||||
87,
|
||||
41,
|
||||
45,
|
||||
};
|
||||
const randomness = []u8{ 42, 1, 7, 12, 22, 17, 99, 16, 26, 87, 41, 45 };
|
||||
var i: usize = 0;
|
||||
while (i < buf.len) : (i += 1) {
|
||||
if (i > randomness.len) return error.Unknown;
|
||||
@ -238,7 +225,7 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
|
||||
var index: usize = 0;
|
||||
while (index < buf.len) {
|
||||
const want_to_read = math.min(buf.len - index, usize(max_buf_len));
|
||||
const rc = posix.read(fd, &buf[index], want_to_read);
|
||||
const rc = posix.read(fd, buf.ptr + index, want_to_read);
|
||||
const err = posix.getErrno(rc);
|
||||
if (err > 0) {
|
||||
return switch (err) {
|
||||
@ -278,7 +265,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
|
||||
var index: usize = 0;
|
||||
while (index < bytes.len) {
|
||||
const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len));
|
||||
const rc = posix.write(fd, &bytes[index], amt_to_write);
|
||||
const rc = posix.write(fd, bytes.ptr + index, amt_to_write);
|
||||
const write_err = posix.getErrno(rc);
|
||||
if (write_err > 0) {
|
||||
return switch (write_err) {
|
||||
@ -328,7 +315,8 @@ pub fn posixOpen(allocator: *Allocator, file_path: []const u8, flags: u32, perm:
|
||||
return posixOpenC(path_with_null.ptr, flags, perm);
|
||||
}
|
||||
|
||||
pub fn posixOpenC(file_path: *const u8, flags: u32, perm: usize) !i32 {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
|
||||
while (true) {
|
||||
const result = posix.open(file_path, flags, perm);
|
||||
const err = posix.getErrno(result);
|
||||
@ -374,19 +362,19 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn createNullDelimitedEnvMap(allocator: *Allocator, env_map: *const BufMap) ![]?*u8 {
|
||||
pub fn createNullDelimitedEnvMap(allocator: *Allocator, env_map: *const BufMap) ![]?[*]u8 {
|
||||
const envp_count = env_map.count();
|
||||
const envp_buf = try allocator.alloc(?*u8, envp_count + 1);
|
||||
mem.set(?*u8, envp_buf, null);
|
||||
const envp_buf = try allocator.alloc(?[*]u8, envp_count + 1);
|
||||
mem.set(?[*]u8, envp_buf, null);
|
||||
errdefer freeNullDelimitedEnvMap(allocator, envp_buf);
|
||||
{
|
||||
var it = env_map.iterator();
|
||||
var i: usize = 0;
|
||||
while (it.next()) |pair| : (i += 1) {
|
||||
const env_buf = try allocator.alloc(u8, pair.key.len + pair.value.len + 2);
|
||||
@memcpy(&env_buf[0], pair.key.ptr, pair.key.len);
|
||||
@memcpy(env_buf.ptr, pair.key.ptr, pair.key.len);
|
||||
env_buf[pair.key.len] = '=';
|
||||
@memcpy(&env_buf[pair.key.len + 1], pair.value.ptr, pair.value.len);
|
||||
@memcpy(env_buf.ptr + pair.key.len + 1, pair.value.ptr, pair.value.len);
|
||||
env_buf[env_buf.len - 1] = 0;
|
||||
|
||||
envp_buf[i] = env_buf.ptr;
|
||||
@ -397,7 +385,7 @@ pub fn createNullDelimitedEnvMap(allocator: *Allocator, env_map: *const BufMap)
|
||||
return envp_buf;
|
||||
}
|
||||
|
||||
pub fn freeNullDelimitedEnvMap(allocator: *Allocator, envp_buf: []?*u8) void {
|
||||
pub fn freeNullDelimitedEnvMap(allocator: *Allocator, envp_buf: []?[*]u8) void {
|
||||
for (envp_buf) |env| {
|
||||
const env_buf = if (env) |ptr| ptr[0 .. cstr.len(ptr) + 1] else break;
|
||||
allocator.free(env_buf);
|
||||
@ -411,8 +399,8 @@ pub fn freeNullDelimitedEnvMap(allocator: *Allocator, envp_buf: []?*u8) void {
|
||||
/// `argv[0]` is the executable path.
|
||||
/// This function also uses the PATH environment variable to get the full path to the executable.
|
||||
pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator: *Allocator) !void {
|
||||
const argv_buf = try allocator.alloc(?*u8, argv.len + 1);
|
||||
mem.set(?*u8, argv_buf, null);
|
||||
const argv_buf = try allocator.alloc(?[*]u8, argv.len + 1);
|
||||
mem.set(?[*]u8, argv_buf, null);
|
||||
defer {
|
||||
for (argv_buf) |arg| {
|
||||
const arg_buf = if (arg) |ptr| cstr.toSlice(ptr) else break;
|
||||
@ -422,7 +410,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator:
|
||||
}
|
||||
for (argv) |arg, i| {
|
||||
const arg_buf = try allocator.alloc(u8, arg.len + 1);
|
||||
@memcpy(&arg_buf[0], arg.ptr, arg.len);
|
||||
@memcpy(arg_buf.ptr, arg.ptr, arg.len);
|
||||
arg_buf[arg.len] = 0;
|
||||
|
||||
argv_buf[i] = arg_buf.ptr;
|
||||
@ -494,7 +482,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError {
|
||||
}
|
||||
|
||||
pub var linux_aux_raw = []usize{0} ** 38;
|
||||
pub var posix_environ_raw: []*u8 = undefined;
|
||||
pub var posix_environ_raw: [][*]u8 = undefined;
|
||||
|
||||
/// Caller must free result when done.
|
||||
pub fn getEnvMap(allocator: *Allocator) !BufMap {
|
||||
@ -1311,7 +1299,7 @@ pub const Dir = struct {
|
||||
const next_index = self.index + linux_entry.d_reclen;
|
||||
self.index = next_index;
|
||||
|
||||
const name = cstr.toSlice(&linux_entry.d_name);
|
||||
const name = cstr.toSlice(@ptrCast([*]u8, &linux_entry.d_name));
|
||||
|
||||
// skip . and .. entries
|
||||
if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) {
|
||||
@ -1485,12 +1473,12 @@ pub const ArgIteratorPosix = struct {
|
||||
|
||||
/// This is marked as public but actually it's only meant to be used
|
||||
/// internally by zig's startup code.
|
||||
pub var raw: []*u8 = undefined;
|
||||
pub var raw: [][*]u8 = undefined;
|
||||
};
|
||||
|
||||
pub const ArgIteratorWindows = struct {
|
||||
index: usize,
|
||||
cmd_line: *const u8,
|
||||
cmd_line: [*]const u8,
|
||||
in_quote: bool,
|
||||
quote_count: usize,
|
||||
seen_quote_count: usize,
|
||||
@ -1501,7 +1489,7 @@ pub const ArgIteratorWindows = struct {
|
||||
return initWithCmdLine(windows.GetCommandLineA());
|
||||
}
|
||||
|
||||
pub fn initWithCmdLine(cmd_line: *const u8) ArgIteratorWindows {
|
||||
pub fn initWithCmdLine(cmd_line: [*]const u8) ArgIteratorWindows {
|
||||
return ArgIteratorWindows{
|
||||
.index = 0,
|
||||
.cmd_line = cmd_line,
|
||||
@ -1616,7 +1604,7 @@ pub const ArgIteratorWindows = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn countQuotes(cmd_line: *const u8) usize {
|
||||
fn countQuotes(cmd_line: [*]const u8) usize {
|
||||
var result: usize = 0;
|
||||
var backslash_count: usize = 0;
|
||||
var index: usize = 0;
|
||||
@ -1722,39 +1710,12 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
|
||||
}
|
||||
|
||||
test "windows arg parsing" {
|
||||
testWindowsCmdLine(c"a b\tc d", [][]const u8{
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d",
|
||||
});
|
||||
testWindowsCmdLine(c"\"abc\" d e", [][]const u8{
|
||||
"abc",
|
||||
"d",
|
||||
"e",
|
||||
});
|
||||
testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8{
|
||||
"a\\\\\\b",
|
||||
"de fg",
|
||||
"h",
|
||||
});
|
||||
testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8{
|
||||
"a\\\"b",
|
||||
"c",
|
||||
"d",
|
||||
});
|
||||
testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8{
|
||||
"a\\\\b c",
|
||||
"d",
|
||||
"e",
|
||||
});
|
||||
testWindowsCmdLine(c"a b\tc \"d f", [][]const u8{
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"\"d",
|
||||
"f",
|
||||
});
|
||||
testWindowsCmdLine(c"a b\tc d", [][]const u8{ "a", "b", "c", "d" });
|
||||
testWindowsCmdLine(c"\"abc\" d e", [][]const u8{ "abc", "d", "e" });
|
||||
testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8{ "a\\\\\\b", "de fg", "h" });
|
||||
testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8{ "a\\\"b", "c", "d" });
|
||||
testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8{ "a\\\\b c", "d", "e" });
|
||||
testWindowsCmdLine(c"a b\tc \"d f", [][]const u8{ "a", "b", "c", "\"d", "f" });
|
||||
|
||||
testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [][]const u8{
|
||||
".\\..\\zig-cache\\build",
|
||||
@ -1765,7 +1726,7 @@ test "windows arg parsing" {
|
||||
});
|
||||
}
|
||||
|
||||
fn testWindowsCmdLine(input_cmd_line: *const u8, expected_args: []const []const u8) void {
|
||||
fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []const u8) void {
|
||||
var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line);
|
||||
for (expected_args) |expected_arg| {
|
||||
const arg = ??it.next(debug.global_allocator) catch unreachable;
|
||||
@ -2350,7 +2311,7 @@ pub fn posixConnectAsync(sockfd: i32, sockaddr: *const posix.sockaddr) PosixConn
|
||||
pub fn posixGetSockOptConnectError(sockfd: i32) PosixConnectError!void {
|
||||
var err_code: i32 = undefined;
|
||||
var size: u32 = @sizeOf(i32);
|
||||
const rc = posix.getsockopt(sockfd, posix.SOL_SOCKET, posix.SO_ERROR, @ptrCast(*u8, &err_code), &size);
|
||||
const rc = posix.getsockopt(sockfd, posix.SOL_SOCKET, posix.SO_ERROR, @ptrCast([*]u8, &err_code), &size);
|
||||
assert(size == 4);
|
||||
const err = posix.getErrno(rc);
|
||||
switch (err) {
|
||||
@ -2401,7 +2362,7 @@ pub const Thread = struct {
|
||||
},
|
||||
builtin.Os.windows => struct {
|
||||
handle: windows.HANDLE,
|
||||
alloc_start: *c_void,
|
||||
alloc_start: [*]c_void,
|
||||
heap_handle: windows.HANDLE,
|
||||
},
|
||||
else => @compileError("Unsupported OS"),
|
||||
@ -2500,7 +2461,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
|
||||
const byte_count = @alignOf(WinThread.OuterContext) + @sizeOf(WinThread.OuterContext);
|
||||
const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) ?? return SpawnThreadError.OutOfMemory;
|
||||
errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0);
|
||||
const bytes = @ptrCast(*u8, bytes_ptr)[0..byte_count];
|
||||
const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count];
|
||||
const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext) catch unreachable;
|
||||
outer_context.inner = context;
|
||||
outer_context.thread.data.heap_handle = heap_handle;
|
||||
@ -2572,7 +2533,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
|
||||
|
||||
// align to page
|
||||
stack_end -= stack_end % os.page_size;
|
||||
assert(c.pthread_attr_setstack(&attr, @intToPtr(*c_void, stack_addr), stack_end - stack_addr) == 0);
|
||||
assert(c.pthread_attr_setstack(&attr, @intToPtr([*]c_void, stack_addr), stack_end - stack_addr) == 0);
|
||||
|
||||
const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));
|
||||
switch (err) {
|
||||
|
@ -665,15 +665,18 @@ pub fn dup2(old: i32, new: i32) usize {
|
||||
return syscall2(SYS_dup2, usize(old), usize(new));
|
||||
}
|
||||
|
||||
pub fn chdir(path: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn chdir(path: [*]const u8) usize {
|
||||
return syscall1(SYS_chdir, @ptrToInt(path));
|
||||
}
|
||||
|
||||
pub fn chroot(path: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn chroot(path: [*]const u8) usize {
|
||||
return syscall1(SYS_chroot, @ptrToInt(path));
|
||||
}
|
||||
|
||||
pub fn execve(path: *const u8, argv: *const ?*const u8, envp: *const ?*const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
|
||||
return syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));
|
||||
}
|
||||
|
||||
@ -685,11 +688,11 @@ pub fn futex_wait(uaddr: usize, futex_op: u32, val: i32, timeout: ?*timespec) us
|
||||
return syscall4(SYS_futex, uaddr, futex_op, @bitCast(u32, val), @ptrToInt(timeout));
|
||||
}
|
||||
|
||||
pub fn getcwd(buf: *u8, size: usize) usize {
|
||||
pub fn getcwd(buf: [*]u8, size: usize) usize {
|
||||
return syscall2(SYS_getcwd, @ptrToInt(buf), size);
|
||||
}
|
||||
|
||||
pub fn getdents(fd: i32, dirp: *u8, count: usize) usize {
|
||||
pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
|
||||
return syscall3(SYS_getdents, usize(fd), @ptrToInt(dirp), count);
|
||||
}
|
||||
|
||||
@ -698,27 +701,32 @@ pub fn isatty(fd: i32) bool {
|
||||
return syscall3(SYS_ioctl, usize(fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
|
||||
}
|
||||
|
||||
pub fn readlink(noalias path: *const u8, noalias buf_ptr: *u8, buf_len: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
|
||||
return syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
|
||||
}
|
||||
|
||||
pub fn mkdir(path: *const u8, mode: u32) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn mkdir(path: [*]const u8, mode: u32) usize {
|
||||
return syscall2(SYS_mkdir, @ptrToInt(path), mode);
|
||||
}
|
||||
|
||||
pub fn mount(special: *const u8, dir: *const u8, fstype: *const u8, flags: usize, data: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn mount(special: [*]const u8, dir: [*]const u8, fstype: [*]const u8, flags: usize, data: usize) usize {
|
||||
return syscall5(SYS_mount, @ptrToInt(special), @ptrToInt(dir), @ptrToInt(fstype), flags, data);
|
||||
}
|
||||
|
||||
pub fn umount(special: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn umount(special: [*]const u8) usize {
|
||||
return syscall2(SYS_umount2, @ptrToInt(special), 0);
|
||||
}
|
||||
|
||||
pub fn umount2(special: *const u8, flags: u32) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn umount2(special: [*]const u8, flags: u32) usize {
|
||||
return syscall2(SYS_umount2, @ptrToInt(special), flags);
|
||||
}
|
||||
|
||||
pub fn mmap(address: ?*u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
|
||||
pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
|
||||
return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd), @bitCast(usize, offset));
|
||||
}
|
||||
|
||||
@ -726,23 +734,26 @@ pub fn munmap(address: usize, length: usize) usize {
|
||||
return syscall2(SYS_munmap, address, length);
|
||||
}
|
||||
|
||||
pub fn read(fd: i32, buf: *u8, count: usize) usize {
|
||||
pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
|
||||
return syscall3(SYS_read, usize(fd), @ptrToInt(buf), count);
|
||||
}
|
||||
|
||||
pub fn rmdir(path: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn rmdir(path: [*]const u8) usize {
|
||||
return syscall1(SYS_rmdir, @ptrToInt(path));
|
||||
}
|
||||
|
||||
pub fn symlink(existing: *const u8, new: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
|
||||
return syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
|
||||
}
|
||||
|
||||
pub fn pread(fd: i32, buf: *u8, count: usize, offset: usize) usize {
|
||||
pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
|
||||
return syscall4(SYS_pread, usize(fd), @ptrToInt(buf), count, offset);
|
||||
}
|
||||
|
||||
pub fn access(path: *const u8, mode: u32) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn access(path: [*]const u8, mode: u32) usize {
|
||||
return syscall2(SYS_access, @ptrToInt(path), mode);
|
||||
}
|
||||
|
||||
@ -754,27 +765,31 @@ pub fn pipe2(fd: *[2]i32, flags: usize) usize {
|
||||
return syscall2(SYS_pipe2, @ptrToInt(fd), flags);
|
||||
}
|
||||
|
||||
pub fn write(fd: i32, buf: *const u8, count: usize) usize {
|
||||
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
|
||||
return syscall3(SYS_write, usize(fd), @ptrToInt(buf), count);
|
||||
}
|
||||
|
||||
pub fn pwrite(fd: i32, buf: *const u8, count: usize, offset: usize) usize {
|
||||
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
|
||||
return syscall4(SYS_pwrite, usize(fd), @ptrToInt(buf), count, offset);
|
||||
}
|
||||
|
||||
pub fn rename(old: *const u8, new: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn rename(old: [*]const u8, new: [*]const u8) usize {
|
||||
return syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
|
||||
}
|
||||
|
||||
pub fn open(path: *const u8, flags: u32, perm: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
|
||||
return syscall3(SYS_open, @ptrToInt(path), flags, perm);
|
||||
}
|
||||
|
||||
pub fn create(path: *const u8, perm: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn create(path: [*]const u8, perm: usize) usize {
|
||||
return syscall2(SYS_creat, @ptrToInt(path), perm);
|
||||
}
|
||||
|
||||
pub fn openat(dirfd: i32, path: *const u8, flags: usize, mode: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize {
|
||||
return syscall4(SYS_openat, usize(dirfd), @ptrToInt(path), flags, mode);
|
||||
}
|
||||
|
||||
@ -801,7 +816,7 @@ pub fn exit(status: i32) noreturn {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn getrandom(buf: *u8, count: usize, flags: u32) usize {
|
||||
pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
|
||||
return syscall3(SYS_getrandom, @ptrToInt(buf), count, usize(flags));
|
||||
}
|
||||
|
||||
@ -809,7 +824,8 @@ pub fn kill(pid: i32, sig: i32) usize {
|
||||
return syscall2(SYS_kill, @bitCast(usize, isize(pid)), usize(sig));
|
||||
}
|
||||
|
||||
pub fn unlink(path: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn unlink(path: [*]const u8) usize {
|
||||
return syscall1(SYS_unlink, @ptrToInt(path));
|
||||
}
|
||||
|
||||
@ -942,8 +958,8 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
|
||||
.restorer = @ptrCast(extern fn () void, restore_rt),
|
||||
};
|
||||
var ksa_old: k_sigaction = undefined;
|
||||
@memcpy(@ptrCast(*u8, *ksa.mask), @ptrCast(*const u8, *act.mask), 8);
|
||||
const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(*ksa), @ptrToInt(*ksa_old), @sizeOf(@typeOf(ksa.mask)));
|
||||
@memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), 8);
|
||||
const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @sizeOf(@typeOf(ksa.mask)));
|
||||
const err = getErrno(result);
|
||||
if (err != 0) {
|
||||
return result;
|
||||
@ -951,7 +967,7 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
|
||||
if (oact) |old| {
|
||||
old.handler = ksa_old.handler;
|
||||
old.flags = @truncate(u32, ksa_old.flags);
|
||||
@memcpy(@ptrCast(*u8, *old.mask), @ptrCast(*const u8, *ksa_old.mask), @sizeOf(@typeOf(ksa_old.mask)));
|
||||
@memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), @sizeOf(@typeOf(ksa_old.mask)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1036,7 +1052,7 @@ pub const sockaddr_in6 = extern struct {
|
||||
};
|
||||
|
||||
pub const iovec = extern struct {
|
||||
iov_base: *u8,
|
||||
iov_base: [*]u8,
|
||||
iov_len: usize,
|
||||
};
|
||||
|
||||
@ -1052,11 +1068,11 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
|
||||
return syscall3(SYS_socket, domain, socket_type, protocol);
|
||||
}
|
||||
|
||||
pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: *const u8, optlen: socklen_t) usize {
|
||||
pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
|
||||
return syscall5(SYS_setsockopt, usize(fd), level, optname, usize(optval), @ptrToInt(optlen));
|
||||
}
|
||||
|
||||
pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: *u8, noalias optlen: *socklen_t) usize {
|
||||
pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
|
||||
return syscall5(SYS_getsockopt, usize(fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
|
||||
}
|
||||
|
||||
@ -1072,7 +1088,7 @@ pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
|
||||
return syscall3(SYS_recvmsg, usize(fd), @ptrToInt(msg), flags);
|
||||
}
|
||||
|
||||
pub fn recvfrom(fd: i32, noalias buf: *u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
|
||||
pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
|
||||
return syscall6(SYS_recvfrom, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
|
||||
}
|
||||
|
||||
@ -1088,7 +1104,7 @@ pub fn listen(fd: i32, backlog: u32) usize {
|
||||
return syscall2(SYS_listen, usize(fd), backlog);
|
||||
}
|
||||
|
||||
pub fn sendto(fd: i32, buf: *const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
|
||||
pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
|
||||
return syscall6(SYS_sendto, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), usize(alen));
|
||||
}
|
||||
|
||||
@ -1108,59 +1124,72 @@ pub fn fstat(fd: i32, stat_buf: *Stat) usize {
|
||||
return syscall2(SYS_fstat, usize(fd), @ptrToInt(stat_buf));
|
||||
}
|
||||
|
||||
pub fn stat(pathname: *const u8, statbuf: *Stat) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn stat(pathname: [*]const u8, statbuf: *Stat) usize {
|
||||
return syscall2(SYS_stat, @ptrToInt(pathname), @ptrToInt(statbuf));
|
||||
}
|
||||
|
||||
pub fn lstat(pathname: *const u8, statbuf: *Stat) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
|
||||
return syscall2(SYS_lstat, @ptrToInt(pathname), @ptrToInt(statbuf));
|
||||
}
|
||||
|
||||
pub fn listxattr(path: *const u8, list: *u8, size: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn listxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
|
||||
return syscall3(SYS_listxattr, @ptrToInt(path), @ptrToInt(list), size);
|
||||
}
|
||||
|
||||
pub fn llistxattr(path: *const u8, list: *u8, size: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn llistxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
|
||||
return syscall3(SYS_llistxattr, @ptrToInt(path), @ptrToInt(list), size);
|
||||
}
|
||||
|
||||
pub fn flistxattr(fd: usize, list: *u8, size: usize) usize {
|
||||
pub fn flistxattr(fd: usize, list: [*]u8, size: usize) usize {
|
||||
return syscall3(SYS_flistxattr, fd, @ptrToInt(list), size);
|
||||
}
|
||||
|
||||
pub fn getxattr(path: *const u8, name: *const u8, value: *void, size: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn getxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
|
||||
return syscall4(SYS_getxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
|
||||
}
|
||||
|
||||
pub fn lgetxattr(path: *const u8, name: *const u8, value: *void, size: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn lgetxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
|
||||
return syscall4(SYS_lgetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
|
||||
}
|
||||
|
||||
pub fn fgetxattr(fd: usize, name: *const u8, value: *void, size: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn fgetxattr(fd: usize, name: [*]const u8, value: [*]u8, size: usize) usize {
|
||||
return syscall4(SYS_lgetxattr, fd, @ptrToInt(name), @ptrToInt(value), size);
|
||||
}
|
||||
|
||||
pub fn setxattr(path: *const u8, name: *const u8, value: *const void, size: usize, flags: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn setxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
|
||||
return syscall5(SYS_setxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
|
||||
}
|
||||
|
||||
pub fn lsetxattr(path: *const u8, name: *const u8, value: *const void, size: usize, flags: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn lsetxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
|
||||
return syscall5(SYS_lsetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
|
||||
}
|
||||
|
||||
pub fn fsetxattr(fd: usize, name: *const u8, value: *const void, size: usize, flags: usize) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn fsetxattr(fd: usize, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
|
||||
return syscall5(SYS_fsetxattr, fd, @ptrToInt(name), @ptrToInt(value), size, flags);
|
||||
}
|
||||
|
||||
pub fn removexattr(path: *const u8, name: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn removexattr(path: [*]const u8, name: [*]const u8) usize {
|
||||
return syscall2(SYS_removexattr, @ptrToInt(path), @ptrToInt(name));
|
||||
}
|
||||
|
||||
pub fn lremovexattr(path: *const u8, name: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn lremovexattr(path: [*]const u8, name: [*]const u8) usize {
|
||||
return syscall2(SYS_lremovexattr, @ptrToInt(path), @ptrToInt(name));
|
||||
}
|
||||
|
||||
pub fn fremovexattr(fd: usize, name: *const u8) usize {
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
pub fn fremovexattr(fd: usize, name: [*]const u8) usize {
|
||||
return syscall2(SYS_fremovexattr, fd, @ptrToInt(name));
|
||||
}
|
||||
|
||||
@ -1188,7 +1217,7 @@ pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
|
||||
return syscall4(SYS_epoll_ctl, usize(epoll_fd), usize(op), usize(fd), @ptrToInt(ev));
|
||||
}
|
||||
|
||||
pub fn epoll_wait(epoll_fd: i32, events: *epoll_event, maxevents: u32, timeout: i32) usize {
|
||||
pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
|
||||
return syscall4(SYS_epoll_wait, usize(epoll_fd), @ptrToInt(events), usize(maxevents), usize(timeout));
|
||||
}
|
||||
|
||||
|
@ -35,5 +35,6 @@ test "timer" {
|
||||
const events_one: linux.epoll_event = undefined;
|
||||
var events = []linux.epoll_event{events_one} ** 8;
|
||||
|
||||
err = linux.epoll_wait(i32(epoll_fd), &events[0], 8, -1);
|
||||
// TODO implicit cast from *[N]T to [*]T
|
||||
err = linux.epoll_wait(i32(epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
|
||||
var ph_addr: usize = vdso_addr + eh.e_phoff;
|
||||
const ph = @intToPtr(*elf.Phdr, ph_addr);
|
||||
|
||||
var maybe_dynv: ?*usize = null;
|
||||
var maybe_dynv: ?[*]usize = null;
|
||||
var base: usize = @maxValue(usize);
|
||||
{
|
||||
var i: usize = 0;
|
||||
@ -23,7 +23,7 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
|
||||
const this_ph = @intToPtr(*elf.Phdr, ph_addr);
|
||||
switch (this_ph.p_type) {
|
||||
elf.PT_LOAD => base = vdso_addr + this_ph.p_offset - this_ph.p_vaddr,
|
||||
elf.PT_DYNAMIC => maybe_dynv = @intToPtr(*usize, vdso_addr + this_ph.p_offset),
|
||||
elf.PT_DYNAMIC => maybe_dynv = @intToPtr([*]usize, vdso_addr + this_ph.p_offset),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
@ -31,10 +31,10 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
|
||||
const dynv = maybe_dynv ?? return 0;
|
||||
if (base == @maxValue(usize)) return 0;
|
||||
|
||||
var maybe_strings: ?*u8 = null;
|
||||
var maybe_syms: ?*elf.Sym = null;
|
||||
var maybe_hashtab: ?*linux.Elf_Symndx = null;
|
||||
var maybe_versym: ?*u16 = null;
|
||||
var maybe_strings: ?[*]u8 = null;
|
||||
var maybe_syms: ?[*]elf.Sym = null;
|
||||
var maybe_hashtab: ?[*]linux.Elf_Symndx = null;
|
||||
var maybe_versym: ?[*]u16 = null;
|
||||
var maybe_verdef: ?*elf.Verdef = null;
|
||||
|
||||
{
|
||||
@ -42,10 +42,10 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
|
||||
while (dynv[i] != 0) : (i += 2) {
|
||||
const p = base + dynv[i + 1];
|
||||
switch (dynv[i]) {
|
||||
elf.DT_STRTAB => maybe_strings = @intToPtr(*u8, p),
|
||||
elf.DT_SYMTAB => maybe_syms = @intToPtr(*elf.Sym, p),
|
||||
elf.DT_HASH => maybe_hashtab = @intToPtr(*linux.Elf_Symndx, p),
|
||||
elf.DT_VERSYM => maybe_versym = @intToPtr(*u16, p),
|
||||
elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),
|
||||
elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),
|
||||
elf.DT_HASH => maybe_hashtab = @intToPtr([*]linux.Elf_Symndx, p),
|
||||
elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
|
||||
elf.DT_VERDEF => maybe_verdef = @intToPtr(*elf.Verdef, p),
|
||||
else => {},
|
||||
}
|
||||
@ -65,7 +65,7 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
|
||||
if (0 == (u32(1) << u5(syms[i].st_info & 0xf) & OK_TYPES)) continue;
|
||||
if (0 == (u32(1) << u5(syms[i].st_info >> 4) & OK_BINDS)) continue;
|
||||
if (0 == syms[i].st_shndx) continue;
|
||||
if (!mem.eql(u8, name, cstr.toSliceConst(&strings[syms[i].st_name]))) continue;
|
||||
if (!mem.eql(u8, name, cstr.toSliceConst(strings + syms[i].st_name))) continue;
|
||||
if (maybe_versym) |versym| {
|
||||
if (!checkver(??maybe_verdef, versym[i], vername, strings))
|
||||
continue;
|
||||
@ -76,7 +76,7 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: *u8) bool {
|
||||
fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [*]u8) bool {
|
||||
var def = def_arg;
|
||||
const vsym = @bitCast(u32, vsym_arg) & 0x7fff;
|
||||
while (true) {
|
||||
@ -87,5 +87,5 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: *
|
||||
def = @intToPtr(*elf.Verdef, @ptrToInt(def) + def.vd_next);
|
||||
}
|
||||
const aux = @intToPtr(*elf.Verdaux, @ptrToInt(def) + def.vd_aux);
|
||||
return mem.eql(u8, vername, cstr.toSliceConst(&strings[aux.vda_name]));
|
||||
return mem.eql(u8, vername, cstr.toSliceConst(strings + aux.vda_name));
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ pub extern "advapi32" stdcallcc fn CryptAcquireContextA(
|
||||
|
||||
pub extern "advapi32" stdcallcc fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) BOOL;
|
||||
|
||||
pub extern "advapi32" stdcallcc fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: *BYTE) BOOL;
|
||||
pub extern "advapi32" stdcallcc fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: [*]BYTE) BOOL;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL;
|
||||
|
||||
@ -61,7 +61,7 @@ pub extern "kernel32" stdcallcc fn DeleteFileA(lpFileName: LPCSTR) BOOL;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: LPCH) BOOL;
|
||||
pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
|
||||
|
||||
@ -69,7 +69,7 @@ pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out
|
||||
|
||||
pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) DWORD;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?LPCH;
|
||||
pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;
|
||||
|
||||
@ -101,17 +101,17 @@ pub extern "kernel32" stdcallcc fn GetSystemTimeAsFileTime(?*FILETIME) void;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn HeapCreate(flOptions: DWORD, dwInitialSize: SIZE_T, dwMaximumSize: SIZE_T) ?HANDLE;
|
||||
pub extern "kernel32" stdcallcc fn HeapDestroy(hHeap: HANDLE) BOOL;
|
||||
pub extern "kernel32" stdcallcc fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: *c_void, dwBytes: SIZE_T) ?*c_void;
|
||||
pub extern "kernel32" stdcallcc fn HeapSize(hHeap: HANDLE, dwFlags: DWORD, lpMem: *const c_void) SIZE_T;
|
||||
pub extern "kernel32" stdcallcc fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: *const c_void) BOOL;
|
||||
pub extern "kernel32" stdcallcc fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: [*]c_void, dwBytes: SIZE_T) ?[*]c_void;
|
||||
pub extern "kernel32" stdcallcc fn HeapSize(hHeap: HANDLE, dwFlags: DWORD, lpMem: [*]const c_void) SIZE_T;
|
||||
pub extern "kernel32" stdcallcc fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: [*]const c_void) BOOL;
|
||||
pub extern "kernel32" stdcallcc fn HeapCompact(hHeap: HANDLE, dwFlags: DWORD) SIZE_T;
|
||||
pub extern "kernel32" stdcallcc fn HeapSummary(hHeap: HANDLE, dwFlags: DWORD, lpSummary: LPHEAP_SUMMARY) BOOL;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) ?HANDLE;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) ?*c_void;
|
||||
pub extern "kernel32" stdcallcc fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) ?[*]c_void;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: *c_void) BOOL;
|
||||
pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: [*]c_void) BOOL;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn MoveFileExA(
|
||||
lpExistingFileName: LPCSTR,
|
||||
@ -127,7 +127,7 @@ pub extern "kernel32" stdcallcc fn PathFileExists(pszPath: ?LPCTSTR) BOOL;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn ReadFile(
|
||||
in_hFile: HANDLE,
|
||||
out_lpBuffer: *c_void,
|
||||
out_lpBuffer: [*]c_void,
|
||||
in_nNumberOfBytesToRead: DWORD,
|
||||
out_lpNumberOfBytesRead: *DWORD,
|
||||
in_out_lpOverlapped: ?*OVERLAPPED,
|
||||
@ -150,7 +150,7 @@ pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMillis
|
||||
|
||||
pub extern "kernel32" stdcallcc fn WriteFile(
|
||||
in_hFile: HANDLE,
|
||||
in_lpBuffer: *const c_void,
|
||||
in_lpBuffer: [*]const c_void,
|
||||
in_nNumberOfBytesToWrite: DWORD,
|
||||
out_lpNumberOfBytesWritten: ?*DWORD,
|
||||
in_out_lpOverlapped: ?*OVERLAPPED,
|
||||
@ -178,16 +178,16 @@ pub const HMODULE = *@OpaqueType();
|
||||
pub const INT = c_int;
|
||||
pub const LPBYTE = *BYTE;
|
||||
pub const LPCH = *CHAR;
|
||||
pub const LPCSTR = *const CHAR;
|
||||
pub const LPCTSTR = *const TCHAR;
|
||||
pub const LPCSTR = [*]const CHAR;
|
||||
pub const LPCTSTR = [*]const TCHAR;
|
||||
pub const LPCVOID = *const c_void;
|
||||
pub const LPDWORD = *DWORD;
|
||||
pub const LPSTR = *CHAR;
|
||||
pub const LPSTR = [*]CHAR;
|
||||
pub const LPTSTR = if (UNICODE) LPWSTR else LPSTR;
|
||||
pub const LPVOID = *c_void;
|
||||
pub const LPWSTR = *WCHAR;
|
||||
pub const LPWSTR = [*]WCHAR;
|
||||
pub const PVOID = *c_void;
|
||||
pub const PWSTR = *WCHAR;
|
||||
pub const PWSTR = [*]WCHAR;
|
||||
pub const SIZE_T = usize;
|
||||
pub const TCHAR = if (UNICODE) WCHAR else u8;
|
||||
pub const UINT = c_uint;
|
||||
|
@ -42,7 +42,7 @@ pub const WriteError = error{
|
||||
};
|
||||
|
||||
pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) WriteError!void {
|
||||
if (windows.WriteFile(handle, @ptrCast(*const c_void, bytes.ptr), u32(bytes.len), null, null) == 0) {
|
||||
if (windows.WriteFile(handle, @ptrCast([*]const c_void, bytes.ptr), u32(bytes.len), null, null) == 0) {
|
||||
const err = windows.GetLastError();
|
||||
return switch (err) {
|
||||
windows.ERROR.INVALID_USER_BUFFER => WriteError.SystemResources,
|
||||
|
@ -87,7 +87,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
const ShelfIndex = std.math.Log2Int(usize);
|
||||
|
||||
prealloc_segment: [prealloc_item_count]T,
|
||||
dynamic_segments: []*T,
|
||||
dynamic_segments: [][*]T,
|
||||
allocator: *Allocator,
|
||||
len: usize,
|
||||
|
||||
@ -99,7 +99,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
.allocator = allocator,
|
||||
.len = 0,
|
||||
.prealloc_segment = undefined,
|
||||
.dynamic_segments = []*T{},
|
||||
.dynamic_segments = [][*]T{},
|
||||
};
|
||||
}
|
||||
|
||||
@ -160,11 +160,11 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
const new_cap_shelf_count = shelfCount(new_capacity);
|
||||
const old_shelf_count = ShelfIndex(self.dynamic_segments.len);
|
||||
if (new_cap_shelf_count > old_shelf_count) {
|
||||
self.dynamic_segments = try self.allocator.realloc(*T, self.dynamic_segments, new_cap_shelf_count);
|
||||
self.dynamic_segments = try self.allocator.realloc([*]T, self.dynamic_segments, new_cap_shelf_count);
|
||||
var i = old_shelf_count;
|
||||
errdefer {
|
||||
self.freeShelves(i, old_shelf_count);
|
||||
self.dynamic_segments = self.allocator.shrink(*T, self.dynamic_segments, old_shelf_count);
|
||||
self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, old_shelf_count);
|
||||
}
|
||||
while (i < new_cap_shelf_count) : (i += 1) {
|
||||
self.dynamic_segments[i] = (try self.allocator.alloc(T, shelfSize(i))).ptr;
|
||||
@ -178,7 +178,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
const len = ShelfIndex(self.dynamic_segments.len);
|
||||
self.freeShelves(len, 0);
|
||||
self.allocator.free(self.dynamic_segments);
|
||||
self.dynamic_segments = []*T{};
|
||||
self.dynamic_segments = [][*]T{};
|
||||
return;
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||
}
|
||||
|
||||
self.freeShelves(old_shelf_count, new_cap_shelf_count);
|
||||
self.dynamic_segments = self.allocator.shrink(*T, self.dynamic_segments, new_cap_shelf_count);
|
||||
self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, new_cap_shelf_count);
|
||||
}
|
||||
|
||||
pub fn uncheckedAt(self: *Self, index: usize) *T {
|
||||
|
@ -5,7 +5,7 @@ const root = @import("@root");
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
var argc_ptr: *usize = undefined;
|
||||
var argc_ptr: [*]usize = undefined;
|
||||
|
||||
comptime {
|
||||
const strong_linkage = builtin.GlobalLinkage.Strong;
|
||||
@ -28,12 +28,12 @@ nakedcc fn _start() noreturn {
|
||||
switch (builtin.arch) {
|
||||
builtin.Arch.x86_64 => {
|
||||
argc_ptr = asm ("lea (%%rsp), %[argc]"
|
||||
: [argc] "=r" (-> *usize)
|
||||
: [argc] "=r" (-> [*]usize)
|
||||
);
|
||||
},
|
||||
builtin.Arch.i386 => {
|
||||
argc_ptr = asm ("lea (%%esp), %[argc]"
|
||||
: [argc] "=r" (-> *usize)
|
||||
: [argc] "=r" (-> [*]usize)
|
||||
);
|
||||
},
|
||||
else => @compileError("unsupported arch"),
|
||||
@ -49,15 +49,17 @@ extern fn WinMainCRTStartup() noreturn {
|
||||
std.os.windows.ExitProcess(callMain());
|
||||
}
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/265
|
||||
fn posixCallMainAndExit() noreturn {
|
||||
const argc = argc_ptr.*;
|
||||
const argv = @ptrCast(**u8, &argc_ptr[1]);
|
||||
const envp_nullable = @ptrCast(*?*u8, &argv[argc + 1]);
|
||||
const argv = @ptrCast([*][*]u8, argc_ptr + 1);
|
||||
|
||||
const envp_nullable = @ptrCast([*]?[*]u8, argv + argc + 1);
|
||||
var envp_count: usize = 0;
|
||||
while (envp_nullable[envp_count]) |_| : (envp_count += 1) {}
|
||||
const envp = @ptrCast(**u8, envp_nullable)[0..envp_count];
|
||||
const envp = @ptrCast([*][*]u8, envp_nullable)[0..envp_count];
|
||||
if (builtin.os == builtin.Os.linux) {
|
||||
const auxv = &@ptrCast(*usize, envp.ptr)[envp_count + 1];
|
||||
const auxv = @ptrCast([*]usize, envp.ptr + envp_count + 1);
|
||||
var i: usize = 0;
|
||||
while (auxv[i] != 0) : (i += 2) {
|
||||
if (auxv[i] < std.os.linux_aux_raw.len) std.os.linux_aux_raw[auxv[i]] = auxv[i + 1];
|
||||
@ -68,16 +70,16 @@ fn posixCallMainAndExit() noreturn {
|
||||
std.os.posix.exit(callMainWithArgs(argc, argv, envp));
|
||||
}
|
||||
|
||||
fn callMainWithArgs(argc: usize, argv: **u8, envp: []*u8) u8 {
|
||||
fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
|
||||
std.os.ArgIteratorPosix.raw = argv[0..argc];
|
||||
std.os.posix_environ_raw = envp;
|
||||
return callMain();
|
||||
}
|
||||
|
||||
extern fn main(c_argc: i32, c_argv: **u8, c_envp: *?*u8) i32 {
|
||||
extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
|
||||
var env_count: usize = 0;
|
||||
while (c_envp[env_count] != null) : (env_count += 1) {}
|
||||
const envp = @ptrCast(**u8, c_envp)[0..env_count];
|
||||
const envp = @ptrCast([*][*]u8, c_envp)[0..env_count];
|
||||
return callMainWithArgs(usize(c_argc), c_argv, envp);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
|
||||
}
|
||||
}
|
||||
|
||||
export fn memset(dest: ?*u8, c: u8, n: usize) ?*u8 {
|
||||
export fn memset(dest: ?[*]u8, c: u8, n: usize) ?[*]u8 {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
var index: usize = 0;
|
||||
@ -24,7 +24,7 @@ export fn memset(dest: ?*u8, c: u8, n: usize) ?*u8 {
|
||||
return dest;
|
||||
}
|
||||
|
||||
export fn memcpy(noalias dest: ?*u8, noalias src: ?*const u8, n: usize) ?*u8 {
|
||||
export fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) ?[*]u8 {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
var index: usize = 0;
|
||||
@ -34,7 +34,7 @@ export fn memcpy(noalias dest: ?*u8, noalias src: ?*const u8, n: usize) ?*u8 {
|
||||
return dest;
|
||||
}
|
||||
|
||||
export fn memmove(dest: ?*u8, src: ?*const u8, n: usize) ?*u8 {
|
||||
export fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) ?[*]u8 {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
if (@ptrToInt(dest) < @ptrToInt(src)) {
|
||||
|
@ -167,54 +167,41 @@ test "@ptrCast preserves alignment of bigger source" {
|
||||
assert(@typeOf(ptr) == *align(16) u8);
|
||||
}
|
||||
|
||||
test "compile-time known array index has best alignment possible" {
|
||||
test "runtime known array index has best alignment possible" {
|
||||
// take full advantage of over-alignment
|
||||
var array align(4) = []u8{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
};
|
||||
var array align(4) = []u8{ 1, 2, 3, 4 };
|
||||
assert(@typeOf(&array[0]) == *align(4) u8);
|
||||
assert(@typeOf(&array[1]) == *u8);
|
||||
assert(@typeOf(&array[2]) == *align(2) u8);
|
||||
assert(@typeOf(&array[3]) == *u8);
|
||||
|
||||
// because align is too small but we still figure out to use 2
|
||||
var bigger align(2) = []u64{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
};
|
||||
var bigger align(2) = []u64{ 1, 2, 3, 4 };
|
||||
assert(@typeOf(&bigger[0]) == *align(2) u64);
|
||||
assert(@typeOf(&bigger[1]) == *align(2) u64);
|
||||
assert(@typeOf(&bigger[2]) == *align(2) u64);
|
||||
assert(@typeOf(&bigger[3]) == *align(2) u64);
|
||||
|
||||
// because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
|
||||
var smaller align(2) = []u32{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
};
|
||||
testIndex(&smaller[0], 0, *align(2) u32);
|
||||
testIndex(&smaller[0], 1, *align(2) u32);
|
||||
testIndex(&smaller[0], 2, *align(2) u32);
|
||||
testIndex(&smaller[0], 3, *align(2) u32);
|
||||
var smaller align(2) = []u32{ 1, 2, 3, 4 };
|
||||
comptime assert(@typeOf(smaller[0..]) == []align(2) u32);
|
||||
comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
|
||||
testIndex(smaller[0..].ptr, 0, *align(2) u32);
|
||||
testIndex(smaller[0..].ptr, 1, *align(2) u32);
|
||||
testIndex(smaller[0..].ptr, 2, *align(2) u32);
|
||||
testIndex(smaller[0..].ptr, 3, *align(2) u32);
|
||||
|
||||
// has to use ABI alignment because index known at runtime only
|
||||
testIndex2(&array[0], 0, *u8);
|
||||
testIndex2(&array[0], 1, *u8);
|
||||
testIndex2(&array[0], 2, *u8);
|
||||
testIndex2(&array[0], 3, *u8);
|
||||
testIndex2(array[0..].ptr, 0, *u8);
|
||||
testIndex2(array[0..].ptr, 1, *u8);
|
||||
testIndex2(array[0..].ptr, 2, *u8);
|
||||
testIndex2(array[0..].ptr, 3, *u8);
|
||||
}
|
||||
fn testIndex(smaller: *align(2) u32, index: usize, comptime T: type) void {
|
||||
assert(@typeOf(&smaller[index]) == T);
|
||||
fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
|
||||
comptime assert(@typeOf(&smaller[index]) == T);
|
||||
}
|
||||
fn testIndex2(ptr: *align(4) u8, index: usize, comptime T: type) void {
|
||||
assert(@typeOf(&ptr[index]) == T);
|
||||
fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
|
||||
comptime assert(@typeOf(&ptr[index]) == T);
|
||||
}
|
||||
|
||||
test "alignstack" {
|
||||
|
@ -1,15 +1,16 @@
|
||||
const debug = @import("std").debug;
|
||||
const assert = debug.assert;
|
||||
|
||||
var argv: *const *const u8 = undefined;
|
||||
var argv: [*]const [*]const u8 = undefined;
|
||||
|
||||
test "const slice child" {
|
||||
const strs = ([]*const u8){
|
||||
const strs = ([][*]const u8){
|
||||
c"one",
|
||||
c"two",
|
||||
c"three",
|
||||
};
|
||||
argv = &strs[0];
|
||||
// TODO this should implicitly cast
|
||||
argv = @ptrCast([*]const [*]const u8, &strs);
|
||||
bar(strs.len);
|
||||
}
|
||||
|
||||
@ -29,7 +30,7 @@ fn bar(argc: usize) void {
|
||||
foo(args);
|
||||
}
|
||||
|
||||
fn strlen(ptr: *const u8) usize {
|
||||
fn strlen(ptr: [*]const u8) usize {
|
||||
var count: usize = 0;
|
||||
while (ptr[count] != 0) : (count += 1) {}
|
||||
return count;
|
||||
|
@ -35,34 +35,12 @@ fn mangleString(s: []u8) void {
|
||||
}
|
||||
|
||||
test "basic for loop" {
|
||||
const expected_result = []u8{
|
||||
9,
|
||||
8,
|
||||
7,
|
||||
6,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
9,
|
||||
8,
|
||||
7,
|
||||
6,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
};
|
||||
const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3, 9, 8, 7, 6, 0, 1, 2, 3 };
|
||||
|
||||
var buffer: [expected_result.len]u8 = undefined;
|
||||
var buf_index: usize = 0;
|
||||
|
||||
const array = []u8{
|
||||
9,
|
||||
8,
|
||||
7,
|
||||
6,
|
||||
};
|
||||
const array = []u8{ 9, 8, 7, 6 };
|
||||
for (array) |item| {
|
||||
buffer[buf_index] = item;
|
||||
buf_index += 1;
|
||||
|
@ -171,8 +171,8 @@ test "memcpy and memset intrinsics" {
|
||||
var foo: [20]u8 = undefined;
|
||||
var bar: [20]u8 = undefined;
|
||||
|
||||
@memset(&foo[0], 'A', foo.len);
|
||||
@memcpy(&bar[0], &foo[0], bar.len);
|
||||
@memset(foo[0..].ptr, 'A', foo.len);
|
||||
@memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
|
||||
|
||||
if (bar[11] != 'A') unreachable;
|
||||
}
|
||||
@ -194,7 +194,7 @@ test "slicing" {
|
||||
if (slice.len != 5) unreachable;
|
||||
|
||||
const ptr = &slice[0];
|
||||
if (ptr[0] != 1234) unreachable;
|
||||
if (ptr.* != 1234) unreachable;
|
||||
|
||||
var slice_rest = array[10..];
|
||||
if (slice_rest.len != 10) unreachable;
|
||||
@ -464,8 +464,9 @@ test "array 2D const double ptr" {
|
||||
}
|
||||
|
||||
fn testArray2DConstDoublePtr(ptr: *const f32) void {
|
||||
assert(ptr[0] == 1.0);
|
||||
assert(ptr[1] == 2.0);
|
||||
const ptr2 = @ptrCast([*]const f32, ptr);
|
||||
assert(ptr2[0] == 1.0);
|
||||
assert(ptr2[1] == 2.0);
|
||||
}
|
||||
|
||||
const Tid = builtin.TypeId;
|
||||
|
@ -12,3 +12,33 @@ fn testDerefPtr() void {
|
||||
y.* += 1;
|
||||
assert(x == 1235);
|
||||
}
|
||||
|
||||
test "pointer arithmetic" {
|
||||
var ptr = c"abcd";
|
||||
|
||||
assert(ptr[0] == 'a');
|
||||
ptr += 1;
|
||||
assert(ptr[0] == 'b');
|
||||
ptr += 1;
|
||||
assert(ptr[0] == 'c');
|
||||
ptr += 1;
|
||||
assert(ptr[0] == 'd');
|
||||
ptr += 1;
|
||||
assert(ptr[0] == 0);
|
||||
ptr -= 1;
|
||||
assert(ptr[0] == 'd');
|
||||
ptr -= 1;
|
||||
assert(ptr[0] == 'c');
|
||||
ptr -= 1;
|
||||
assert(ptr[0] == 'b');
|
||||
ptr -= 1;
|
||||
assert(ptr[0] == 'a');
|
||||
}
|
||||
|
||||
test "double pointer parsing" {
|
||||
comptime assert(PtrOf(PtrOf(i32)) == **i32);
|
||||
}
|
||||
|
||||
fn PtrOf(comptime T: type) type {
|
||||
return *T;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ const VoidStructFieldsFoo = struct {
|
||||
|
||||
test "structs" {
|
||||
var foo: StructFoo = undefined;
|
||||
@memset(@ptrCast(*u8, &foo), 0, @sizeOf(StructFoo));
|
||||
@memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
|
||||
foo.a += 1;
|
||||
foo.b = foo.a == 1;
|
||||
testFoo(foo);
|
||||
@ -396,8 +396,8 @@ const Bitfields = packed struct {
|
||||
test "native bit field understands endianness" {
|
||||
var all: u64 = 0x7765443322221111;
|
||||
var bytes: [8]u8 = undefined;
|
||||
@memcpy(&bytes[0], @ptrCast(*u8, &all), 8);
|
||||
var bitfields = @ptrCast(*Bitfields, &bytes[0]).*;
|
||||
@memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
|
||||
var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
|
||||
|
||||
assert(bitfields.f1 == 0x1111);
|
||||
assert(bitfields.f2 == 0x2222);
|
||||
|
@ -6,7 +6,7 @@ const tests = @import("tests.zig");
|
||||
pub fn addCases(cases: *tests.CompareOutputContext) void {
|
||||
cases.addC("hello world with libc",
|
||||
\\const c = @cImport(@cInclude("stdio.h"));
|
||||
\\export fn main(argc: c_int, argv: **u8) c_int {
|
||||
\\export fn main(argc: c_int, argv: [*][*]u8) c_int {
|
||||
\\ _ = c.puts(c"Hello, world!");
|
||||
\\ return 0;
|
||||
\\}
|
||||
@ -139,7 +139,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
|
||||
\\ @cInclude("stdio.h");
|
||||
\\});
|
||||
\\
|
||||
\\export fn main(argc: c_int, argv: **u8) c_int {
|
||||
\\export fn main(argc: c_int, argv: [*][*]u8) c_int {
|
||||
\\ if (is_windows) {
|
||||
\\ // we want actual \n, not \r\n
|
||||
\\ _ = c._setmode(1, c._O_BINARY);
|
||||
@ -284,9 +284,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
|
||||
cases.addC("expose function pointer to C land",
|
||||
\\const c = @cImport(@cInclude("stdlib.h"));
|
||||
\\
|
||||
\\export fn compare_fn(a: ?*const c_void, b: ?*const c_void) c_int {
|
||||
\\ const a_int = @ptrCast(*align(1) const i32, a ?? unreachable);
|
||||
\\ const b_int = @ptrCast(*align(1) const i32, b ?? unreachable);
|
||||
\\export fn compare_fn(a: ?[*]const c_void, b: ?[*]const c_void) c_int {
|
||||
\\ const a_int = @ptrCast(*const i32, @alignCast(@alignOf(i32), a));
|
||||
\\ const b_int = @ptrCast(*const i32, @alignCast(@alignOf(i32), b));
|
||||
\\ if (a_int.* < b_int.*) {
|
||||
\\ return -1;
|
||||
\\ } else if (a_int.* > b_int.*) {
|
||||
@ -297,9 +297,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
|
||||
\\}
|
||||
\\
|
||||
\\export fn main() c_int {
|
||||
\\ var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };
|
||||
\\ var array = []u32{ 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };
|
||||
\\
|
||||
\\ c.qsort(@ptrCast(*c_void, &array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn);
|
||||
\\ c.qsort(@ptrCast(?[*]c_void, array[0..].ptr), c_ulong(array.len), @sizeOf(i32), compare_fn);
|
||||
\\
|
||||
\\ for (array) |item, i| {
|
||||
\\ if (item != i) {
|
||||
@ -324,7 +324,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
|
||||
\\ @cInclude("stdio.h");
|
||||
\\});
|
||||
\\
|
||||
\\export fn main(argc: c_int, argv: **u8) c_int {
|
||||
\\export fn main(argc: c_int, argv: [*][*]u8) c_int {
|
||||
\\ if (is_windows) {
|
||||
\\ // we want actual \n, not \r\n
|
||||
\\ _ = c._setmode(1, c._O_BINARY);
|
||||
|
@ -1,6 +1,15 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add(
|
||||
"indexing single-item pointer",
|
||||
\\export fn entry(ptr: *i32) i32 {
|
||||
\\ return ptr[1];
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:15: error: indexing not allowed on pointer to single item",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"invalid deref on switch target",
|
||||
\\const NextError = error{NextError};
|
||||
@ -1002,7 +1011,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ return a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:12: error: expected type 'i32', found '*const u8'",
|
||||
".tmp_source.zig:3:12: error: expected type 'i32', found '[*]const u8'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2442,13 +2451,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\var s_buffer: [10]u8 = undefined;
|
||||
\\pub fn pass(in: []u8) []u8 {
|
||||
\\ var out = &s_buffer;
|
||||
\\ out[0].* = in[0];
|
||||
\\ out.*.* = in[0];
|
||||
\\ return out.*[0..1];
|
||||
\\}
|
||||
\\
|
||||
\\export fn entry() usize { return @sizeOf(@typeOf(pass)); }
|
||||
,
|
||||
".tmp_source.zig:4:11: error: attempt to dereference non pointer type '[10]u8'",
|
||||
".tmp_source.zig:4:10: error: attempt to dereference non pointer type '[10]u8'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
|
@ -14,11 +14,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\};
|
||||
,
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ a: ?*Foo,
|
||||
\\ a: ?[*]Foo,
|
||||
\\};
|
||||
\\pub const Foo = struct_Foo;
|
||||
\\pub const struct_Bar = extern struct {
|
||||
\\ a: ?*Foo,
|
||||
\\ a: ?[*]Foo,
|
||||
\\};
|
||||
);
|
||||
|
||||
@ -99,7 +99,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
cases.add("restrict -> noalias",
|
||||
\\void foo(void *restrict bar, void *restrict);
|
||||
,
|
||||
\\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void;
|
||||
\\pub extern fn foo(noalias bar: ?[*]c_void, noalias arg1: ?[*]c_void) void;
|
||||
);
|
||||
|
||||
cases.add("simple struct",
|
||||
@ -110,7 +110,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
,
|
||||
\\const struct_Foo = extern struct {
|
||||
\\ x: c_int,
|
||||
\\ y: ?*u8,
|
||||
\\ y: ?[*]u8,
|
||||
\\};
|
||||
,
|
||||
\\pub const Foo = struct_Foo;
|
||||
@ -141,7 +141,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
,
|
||||
\\pub const BarB = enum_Bar.B;
|
||||
,
|
||||
\\pub extern fn func(a: ?*struct_Foo, b: ?*(?*enum_Bar)) void;
|
||||
\\pub extern fn func(a: ?[*]struct_Foo, b: ?[*](?[*]enum_Bar)) void;
|
||||
,
|
||||
\\pub const Foo = struct_Foo;
|
||||
,
|
||||
@ -151,7 +151,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
cases.add("constant size array",
|
||||
\\void func(int array[20]);
|
||||
,
|
||||
\\pub extern fn func(array: ?*c_int) void;
|
||||
\\pub extern fn func(array: ?[*]c_int) void;
|
||||
);
|
||||
|
||||
cases.add("self referential struct with function pointer",
|
||||
@ -160,7 +160,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\};
|
||||
,
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ derp: ?extern fn(?*struct_Foo) void,
|
||||
\\ derp: ?extern fn(?[*]struct_Foo) void,
|
||||
\\};
|
||||
,
|
||||
\\pub const Foo = struct_Foo;
|
||||
@ -172,7 +172,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
,
|
||||
\\pub const struct_Foo = @OpaqueType();
|
||||
,
|
||||
\\pub extern fn some_func(foo: ?*struct_Foo, x: c_int) ?*struct_Foo;
|
||||
\\pub extern fn some_func(foo: ?[*]struct_Foo, x: c_int) ?[*]struct_Foo;
|
||||
,
|
||||
\\pub const Foo = struct_Foo;
|
||||
);
|
||||
@ -219,11 +219,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\};
|
||||
,
|
||||
\\pub const struct_Bar = extern struct {
|
||||
\\ next: ?*struct_Foo,
|
||||
\\ next: ?[*]struct_Foo,
|
||||
\\};
|
||||
,
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ next: ?*struct_Bar,
|
||||
\\ next: ?[*]struct_Bar,
|
||||
\\};
|
||||
);
|
||||
|
||||
@ -233,7 +233,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
,
|
||||
\\pub const Foo = c_void;
|
||||
,
|
||||
\\pub extern fn fun(a: ?*Foo) Foo;
|
||||
\\pub extern fn fun(a: ?[*]Foo) Foo;
|
||||
);
|
||||
|
||||
cases.add("generate inline func for #define global extern fn",
|
||||
@ -505,7 +505,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return 6;
|
||||
\\}
|
||||
,
|
||||
\\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
|
||||
\\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?[*]c_void) c_int {
|
||||
\\ if ((a != 0) and (b != 0)) return 0;
|
||||
\\ if ((b != 0) and (c != null)) return 1;
|
||||
\\ if ((a != 0) and (c != null)) return 2;
|
||||
@ -607,7 +607,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub const struct_Foo = extern struct {
|
||||
\\ field: c_int,
|
||||
\\};
|
||||
\\pub export fn read_field(foo: ?*struct_Foo) c_int {
|
||||
\\pub export fn read_field(foo: ?[*]struct_Foo) c_int {
|
||||
\\ return (??foo).field;
|
||||
\\}
|
||||
);
|
||||
@ -653,8 +653,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return x;
|
||||
\\}
|
||||
,
|
||||
\\pub export fn foo(x: ?*c_ushort) ?*c_void {
|
||||
\\ return @ptrCast(?*c_void, x);
|
||||
\\pub export fn foo(x: ?[*]c_ushort) ?[*]c_void {
|
||||
\\ return @ptrCast(?[*]c_void, x);
|
||||
\\}
|
||||
);
|
||||
|
||||
@ -674,7 +674,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return 0;
|
||||
\\}
|
||||
,
|
||||
\\pub export fn foo() ?*c_int {
|
||||
\\pub export fn foo() ?[*]c_int {
|
||||
\\ return null;
|
||||
\\}
|
||||
);
|
||||
@ -983,7 +983,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ *x = 1;
|
||||
\\}
|
||||
,
|
||||
\\pub export fn foo(x: ?*c_int) void {
|
||||
\\pub export fn foo(x: ?[*]c_int) void {
|
||||
\\ (??x).* = 1;
|
||||
\\}
|
||||
);
|
||||
@ -1011,7 +1011,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
,
|
||||
\\pub fn foo() c_int {
|
||||
\\ var x: c_int = 1234;
|
||||
\\ var ptr: ?*c_int = &x;
|
||||
\\ var ptr: ?[*]c_int = &x;
|
||||
\\ return (??ptr).*;
|
||||
\\}
|
||||
);
|
||||
@ -1021,7 +1021,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return "bar";
|
||||
\\}
|
||||
,
|
||||
\\pub fn foo() ?*const u8 {
|
||||
\\pub fn foo() ?[*]const u8 {
|
||||
\\ return c"bar";
|
||||
\\}
|
||||
);
|
||||
@ -1150,8 +1150,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return (float *)a;
|
||||
\\}
|
||||
,
|
||||
\\fn ptrcast(a: ?*c_int) ?*f32 {
|
||||
\\ return @ptrCast(?*f32, a);
|
||||
\\fn ptrcast(a: ?[*]c_int) ?[*]f32 {
|
||||
\\ return @ptrCast(?[*]f32, a);
|
||||
\\}
|
||||
);
|
||||
|
||||
@ -1173,7 +1173,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return !c;
|
||||
\\}
|
||||
,
|
||||
\\pub fn foo(a: c_int, b: f32, c: ?*c_void) c_int {
|
||||
\\pub fn foo(a: c_int, b: f32, c: ?[*]c_void) c_int {
|
||||
\\ return !(a == 0);
|
||||
\\ return !(a != 0);
|
||||
\\ return !(b != 0);
|
||||
@ -1194,7 +1194,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
cases.add("const ptr initializer",
|
||||
\\static const char *v0 = "0.0.0";
|
||||
,
|
||||
\\pub var v0: ?*const u8 = c"0.0.0";
|
||||
\\pub var v0: ?[*]const u8 = c"0.0.0";
|
||||
);
|
||||
|
||||
cases.add("static incomplete array inside function",
|
||||
@ -1203,14 +1203,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
,
|
||||
\\pub fn foo() void {
|
||||
\\ const v2: *const u8 = c"2.2.2";
|
||||
\\ const v2: [*]const u8 = c"2.2.2";
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.add("macro pointer cast",
|
||||
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
|
||||
,
|
||||
\\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast(*NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr(*NRF_GPIO_Type, NRF_GPIO_BASE) else (*NRF_GPIO_Type)(NRF_GPIO_BASE);
|
||||
\\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*]NRF_GPIO_Type)(NRF_GPIO_BASE);
|
||||
);
|
||||
|
||||
cases.add("if on none bool",
|
||||
@ -1231,7 +1231,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ B,
|
||||
\\ C,
|
||||
\\};
|
||||
\\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
|
||||
\\pub fn if_none_bool(a: c_int, b: f32, c: ?[*]c_void, d: enum_SomeEnum) c_int {
|
||||
\\ if (a != 0) return 0;
|
||||
\\ if (b != 0) return 1;
|
||||
\\ if (c != null) return 2;
|
||||
@ -1248,7 +1248,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return 3;
|
||||
\\}
|
||||
,
|
||||
\\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
|
||||
\\pub fn while_none_bool(a: c_int, b: f32, c: ?[*]c_void) c_int {
|
||||
\\ while (a != 0) return 0;
|
||||
\\ while (b != 0) return 1;
|
||||
\\ while (c != null) return 2;
|
||||
@ -1264,7 +1264,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return 3;
|
||||
\\}
|
||||
,
|
||||
\\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
|
||||
\\pub fn for_none_bool(a: c_int, b: f32, c: ?[*]c_void) c_int {
|
||||
\\ while (a != 0) return 0;
|
||||
\\ while (b != 0) return 1;
|
||||
\\ while (c != null) return 2;
|
||||
|
Loading…
Reference in New Issue
Block a user