Merge pull request #74 from birth-software/array-pointer
Fix pointer to array issue
This commit is contained in:
commit
f8bd7ad443
@ -3764,6 +3764,22 @@ pub const Builder = struct {
|
|||||||
true => unreachable,
|
true => unreachable,
|
||||||
false => switch (unit.types.get(pointer.type).*) {
|
false => switch (unit.types.get(pointer.type).*) {
|
||||||
.array => |array| {
|
.array => |array| {
|
||||||
|
const pointer_gep = try unit.instructions.append(context.allocator, .{
|
||||||
|
.get_element_pointer = .{
|
||||||
|
.pointer = expression_to_slice.value.runtime,
|
||||||
|
.base_type = array.type,
|
||||||
|
.index = range_start,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
try builder.appendInstruction(unit, context, pointer_gep);
|
||||||
|
|
||||||
|
const pointer_type = try unit.getPointerType(context, .{
|
||||||
|
.type = array.type,
|
||||||
|
.termination = .none,
|
||||||
|
.mutability = pointer.mutability,
|
||||||
|
.many = false,
|
||||||
|
.nullable = false,
|
||||||
|
});
|
||||||
const slice_builder = try unit.instructions.append(context.allocator, .{
|
const slice_builder = try unit.instructions.append(context.allocator, .{
|
||||||
.insert_value = .{
|
.insert_value = .{
|
||||||
.expression = V{
|
.expression = V{
|
||||||
@ -3776,7 +3792,12 @@ pub const Builder = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
.index = 0,
|
.index = 0,
|
||||||
.new_value = expression_to_slice,
|
.new_value = .{
|
||||||
|
.value = .{
|
||||||
|
.runtime = pointer_gep,
|
||||||
|
},
|
||||||
|
.type = pointer_type,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
try builder.appendInstruction(unit, context, slice_builder);
|
try builder.appendInstruction(unit, context, slice_builder);
|
||||||
@ -4227,9 +4248,25 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
.array => |array| b: {
|
.array => |array| b: {
|
||||||
|
const loaded_array_like = switch (array_like_expression.value) {
|
||||||
|
.runtime => |instruction_index| switch (unit.instructions.get(instruction_index).*) {
|
||||||
|
.argument_declaration, .stack_slot => arg: {
|
||||||
|
const load = try unit.instructions.append(context.allocator, .{
|
||||||
|
.load = .{
|
||||||
|
.value = array_like_expression,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
try builder.appendInstruction(unit, context, load);
|
||||||
|
break :arg load;
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
|
||||||
const gep = try unit.instructions.append(context.allocator, .{
|
const gep = try unit.instructions.append(context.allocator, .{
|
||||||
.get_element_pointer = .{
|
.get_element_pointer = .{
|
||||||
.pointer = array_like_expression.value.runtime,
|
.pointer = loaded_array_like,
|
||||||
.base_type = array.type,
|
.base_type = array.type,
|
||||||
.index = index,
|
.index = index,
|
||||||
},
|
},
|
||||||
@ -4310,6 +4347,38 @@ pub const Builder = struct {
|
|||||||
.type = gep_type,
|
.type = gep_type,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
.array => |array| b: {
|
||||||
|
switch (array_like_expression.value) {
|
||||||
|
.runtime => |instruction_index| switch (unit.instructions.get(instruction_index).*) {
|
||||||
|
.stack_slot => {},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
|
||||||
|
const gep = try unit.instructions.append(context.allocator, .{
|
||||||
|
.get_element_pointer = .{
|
||||||
|
.pointer = array_like_expression.value.runtime,
|
||||||
|
.base_type = array.type,
|
||||||
|
.index = index,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const gep_type = try unit.getPointerType(context, .{
|
||||||
|
.type = array.type,
|
||||||
|
.termination = .none,
|
||||||
|
.mutability = .@"var",
|
||||||
|
.many = false,
|
||||||
|
.nullable = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
break :b .{
|
||||||
|
.value = .{
|
||||||
|
.runtime = gep,
|
||||||
|
},
|
||||||
|
.type = gep_type,
|
||||||
|
};
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4342,6 +4411,7 @@ pub const Builder = struct {
|
|||||||
|
|
||||||
break :b unit.types.get(gep.type).pointer.type;
|
break :b unit.types.get(gep.type).pointer.type;
|
||||||
},
|
},
|
||||||
|
.none => unit.types.get(gep.type).pointer.type,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -2459,7 +2459,6 @@ pub const LLVM = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emitLeftValue(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, v: Compilation.V) !*LLVM.Value {
|
fn emitLeftValue(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, v: Compilation.V) !*LLVM.Value {
|
||||||
_ = context; // autofix
|
|
||||||
switch (v.value) {
|
switch (v.value) {
|
||||||
.runtime => |instruction_index| {
|
.runtime => |instruction_index| {
|
||||||
if (llvm.llvm_instruction_map.get(instruction_index)) |value| {
|
if (llvm.llvm_instruction_map.get(instruction_index)) |value| {
|
||||||
@ -2471,6 +2470,17 @@ pub const LLVM = struct {
|
|||||||
const global_variable = llvm.global_variable_map.get(global_declaration).?;
|
const global_variable = llvm.global_variable_map.get(global_declaration).?;
|
||||||
return global_variable.toValue();
|
return global_variable.toValue();
|
||||||
},
|
},
|
||||||
|
.get_element_pointer => |gep| {
|
||||||
|
const pointer = llvm.llvm_instruction_map.get(gep.pointer).?;
|
||||||
|
const index = try llvm.emitRightValue(unit, context, gep.index);
|
||||||
|
const indices = [1]*LLVM.Value{ index };
|
||||||
|
const base_type = try llvm.getType(unit, context, gep.base_type);
|
||||||
|
const in_bounds = true;
|
||||||
|
const get_element_pointer = llvm.builder.createGEP(base_type, pointer, &indices, indices.len, "gep", "gep".len, in_bounds) orelse unreachable;
|
||||||
|
try llvm.llvm_value_map.putNoClobber(context.allocator, v, get_element_pointer);
|
||||||
|
try llvm.llvm_instruction_map.putNoClobber(context.allocator, instruction_index, get_element_pointer);
|
||||||
|
return get_element_pointer;
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3091,6 +3101,15 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
const global_variable = llvm.global_variable_map.get(global).?;
|
const global_variable = llvm.global_variable_map.get(global).?;
|
||||||
break :b global_variable.toValue();
|
break :b global_variable.toValue();
|
||||||
},
|
},
|
||||||
|
.get_element_pointer => |gep| b: {
|
||||||
|
const index = try llvm.emitRightValue(unit, context, gep.index);
|
||||||
|
const pointer = llvm.llvm_instruction_map.get(gep.pointer).?;
|
||||||
|
const t = try llvm.getType(unit, context, gep.base_type);
|
||||||
|
const indices = [1]*LLVM.Value{index};
|
||||||
|
const in_bounds = true;
|
||||||
|
const get_element_pointer = llvm.builder.createGEP(t, pointer, &indices, indices.len, "gep", "gep".len, in_bounds) orelse unreachable;
|
||||||
|
break :b get_element_pointer;
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
|
@ -22,7 +22,7 @@ pub fn main() !void {
|
|||||||
|
|
||||||
while (try standalone_iterator.next()) |entry| {
|
while (try standalone_iterator.next()) |entry| {
|
||||||
switch (entry.kind) {
|
switch (entry.kind) {
|
||||||
.directory => try standalone_test_names.append(allocator, entry.name),
|
.directory => try standalone_test_names.append(allocator, try allocator.dupe(u8, entry.name)),
|
||||||
else => return error.junk_in_test_directory,
|
else => return error.junk_in_test_directory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,6 +38,7 @@ pub fn main() !void {
|
|||||||
const total_test_count = standalone_test_names.items.len;
|
const total_test_count = standalone_test_names.items.len;
|
||||||
|
|
||||||
for (standalone_test_names.items) |standalone_test_name| {
|
for (standalone_test_names.items) |standalone_test_name| {
|
||||||
|
std.debug.assert(!std.mem.eql(u8, standalone_test_name, "else_ifrld"));
|
||||||
std.debug.print("{s}... ", .{standalone_test_name});
|
std.debug.print("{s}... ", .{standalone_test_name});
|
||||||
const source_file_path = try std.mem.concat(allocator, u8, &.{standalone_test_dir_path, "/", standalone_test_name, "/main.nat"});
|
const source_file_path = try std.mem.concat(allocator, u8, &.{standalone_test_dir_path, "/", standalone_test_name, "/main.nat"});
|
||||||
const compile_run = try std.ChildProcess.run(.{
|
const compile_run = try std.ChildProcess.run(.{
|
||||||
|
@ -28,7 +28,9 @@ const format_usize = fn(n: usize, buffer: &[65]u8) []u8 {
|
|||||||
while (true) {
|
while (true) {
|
||||||
const digit: u8 = #cast(absolute % 10);
|
const digit: u8 = #cast(absolute % 10);
|
||||||
index -= 1;
|
index -= 1;
|
||||||
buffer[index] = '0' + digit;
|
const ch = '0' + digit;
|
||||||
|
buffer[index] = ch;
|
||||||
|
#assert(buffer[index] == ch);
|
||||||
absolute /= 10;
|
absolute /= 10;
|
||||||
|
|
||||||
if (absolute == 0) {
|
if (absolute == 0) {
|
||||||
|
10
test/standalone/array_pointer_store/main.nat
Normal file
10
test/standalone/array_pointer_store/main.nat
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const main = fn () s32 {
|
||||||
|
const ch = 'a';
|
||||||
|
var buffer: [1]u8 = undefined;
|
||||||
|
var ptr: &[1]u8 = buffer.&;
|
||||||
|
var index: usize = 0;
|
||||||
|
ptr[index] = ch;
|
||||||
|
const sub: u8 = ptr[index] - ch;
|
||||||
|
const result: u32 = sub;
|
||||||
|
return #cast(result);
|
||||||
|
}
|
14
test/standalone/array_pointer_store_function/main.nat
Normal file
14
test/standalone/array_pointer_store_function/main.nat
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const main = fn () s32 {
|
||||||
|
var buffer: [2]u8 = undefined;
|
||||||
|
const expected = 'a';
|
||||||
|
const index: usize = 1;
|
||||||
|
foo(buffer.&, index, expected);
|
||||||
|
const ch = buffer[index];
|
||||||
|
const sub = expected - ch;
|
||||||
|
const result: u32 = sub;
|
||||||
|
return #cast(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
const foo = fn (buffer: &[2]u8, index: usize, ch: u8) void {
|
||||||
|
buffer[index] = ch;
|
||||||
|
}
|
9
test/standalone/array_store/main.nat
Normal file
9
test/standalone/array_store/main.nat
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
const main = fn () s32 {
|
||||||
|
const ch = 'a';
|
||||||
|
var buffer: [1]u8 = undefined;
|
||||||
|
var index: usize = 0;
|
||||||
|
buffer[index] = ch;
|
||||||
|
const sub: u8 = buffer[index] - ch;
|
||||||
|
const result: u32 = sub;
|
||||||
|
return #cast(result);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user