Basic array
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 46s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 44s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 53s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 1m15s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 42s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 41s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 49s
CI / ci (Debug, ubuntu-latest) (push) Successful in 1m9s
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 46s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 44s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 53s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 1m15s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 42s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 41s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 49s
CI / ci (Debug, ubuntu-latest) (push) Successful in 1m9s
This commit is contained in:
parent
73cf2ad30b
commit
ef0f70bae3
@ -13,6 +13,20 @@ pub const OperatingSystem = enum {
|
|||||||
linux,
|
linux,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn array_type_name(arena: *Arena, element_type: *Type, element_count: u64) [:0]const u8 {
|
||||||
|
var buffer: [256]u8 = undefined;
|
||||||
|
var i: u64 = 0;
|
||||||
|
buffer[i] = left_bracket;
|
||||||
|
i += 1;
|
||||||
|
i += lib.string_format.integer_decimal(buffer[i..], element_count);
|
||||||
|
buffer[i] = right_bracket;
|
||||||
|
i += 1;
|
||||||
|
const element_name = element_type.name;
|
||||||
|
@memcpy(buffer[i..][0..element_name.len], element_name);
|
||||||
|
i += element_name.len;
|
||||||
|
return arena.duplicate_string(buffer[0..i]);
|
||||||
|
}
|
||||||
|
|
||||||
pub const BuildMode = enum {
|
pub const BuildMode = enum {
|
||||||
debug_none,
|
debug_none,
|
||||||
debug_fast,
|
debug_fast,
|
||||||
@ -200,7 +214,7 @@ pub const Type = struct {
|
|||||||
bits,
|
bits,
|
||||||
pointer: Type.Pointer,
|
pointer: Type.Pointer,
|
||||||
function: Type.Function,
|
function: Type.Function,
|
||||||
array,
|
array: Type.Array,
|
||||||
structure: Type.Struct,
|
structure: Type.Struct,
|
||||||
vector,
|
vector,
|
||||||
},
|
},
|
||||||
@ -223,6 +237,7 @@ pub const Type = struct {
|
|||||||
// Consider function types later since we need to deal with ABI
|
// Consider function types later since we need to deal with ABI
|
||||||
.function => null,
|
.function => null,
|
||||||
.pointer => module.llvm.pointer_type,
|
.pointer => module.llvm.pointer_type,
|
||||||
|
.array => |array| array.element_type.resolve(module).handle.get_array_type(array.element_count).to_type(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
ty.llvm.handle = llvm_type;
|
ty.llvm.handle = llvm_type;
|
||||||
@ -251,6 +266,7 @@ pub const Type = struct {
|
|||||||
break :b subroutine_type.to_type();
|
break :b subroutine_type.to_type();
|
||||||
},
|
},
|
||||||
.pointer => |pointer| module.llvm.di_builder.create_pointer_type(pointer.type.resolve(module).debug, 64, 64, 0, ty.name).to_type(),
|
.pointer => |pointer| module.llvm.di_builder.create_pointer_type(pointer.type.resolve(module).debug, 64, 64, 0, ty.name).to_type(),
|
||||||
|
.array => |array| module.llvm.di_builder.create_array_type(array.element_count, 0, array.element_type.llvm.debug.?, &.{}).to_type(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
} else null;
|
} else null;
|
||||||
ty.llvm.debug = debug_type;
|
ty.llvm.debug = debug_type;
|
||||||
@ -289,6 +305,11 @@ pub const Type = struct {
|
|||||||
fields: []Field,
|
fields: []Field,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Array = struct {
|
||||||
|
element_type: *Type,
|
||||||
|
element_count: u64,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Buffer = struct {
|
pub const Buffer = struct {
|
||||||
buffer: lib.VirtualBuffer(Type),
|
buffer: lib.VirtualBuffer(Type),
|
||||||
|
|
||||||
@ -368,6 +389,7 @@ pub const Type = struct {
|
|||||||
.integer => |integer| @intCast(@min(@divExact(@max(8, lib.next_power_of_two(integer.bit_count)), 8), 16)),
|
.integer => |integer| @intCast(@min(@divExact(@max(8, lib.next_power_of_two(integer.bit_count)), 8), 16)),
|
||||||
.pointer => 8,
|
.pointer => 8,
|
||||||
.function => 1,
|
.function => 1,
|
||||||
|
.array => |array| array.element_type.get_byte_alignment(),
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
@ -523,11 +545,23 @@ pub const Value = struct {
|
|||||||
dereference: *Value,
|
dereference: *Value,
|
||||||
call: Call,
|
call: Call,
|
||||||
infer_or_ignore,
|
infer_or_ignore,
|
||||||
|
array_initialization: ArrayInitialization,
|
||||||
|
array_expression: ArrayExpression,
|
||||||
},
|
},
|
||||||
type: ?*Type = null,
|
type: ?*Type = null,
|
||||||
llvm: ?*llvm.Value = null,
|
llvm: ?*llvm.Value = null,
|
||||||
kind: Kind = .right,
|
kind: Kind = .right,
|
||||||
|
|
||||||
|
pub const ArrayExpression = struct {
|
||||||
|
array_like: *Value,
|
||||||
|
index: *Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ArrayInitialization = struct {
|
||||||
|
values: []const *Value,
|
||||||
|
is_constant: bool,
|
||||||
|
};
|
||||||
|
|
||||||
const Intrinsic = union(Id) {
|
const Intrinsic = union(Id) {
|
||||||
byte_size: *Type,
|
byte_size: *Type,
|
||||||
cast,
|
cast,
|
||||||
@ -1074,6 +1108,60 @@ pub const Module = struct {
|
|||||||
});
|
});
|
||||||
return pointer_type;
|
return pointer_type;
|
||||||
},
|
},
|
||||||
|
left_bracket => {
|
||||||
|
module.offset += 1;
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
const is_slice = module.consume_character_if_match(right_bracket);
|
||||||
|
switch (is_slice) {
|
||||||
|
true => {
|
||||||
|
@trap();
|
||||||
|
},
|
||||||
|
false => {
|
||||||
|
var length_inferred = false;
|
||||||
|
const offset = module.offset;
|
||||||
|
if (module.consume_character_if_match('_')) {
|
||||||
|
module.skip_space();
|
||||||
|
if (module.consume_character_if_match(']')) {
|
||||||
|
length_inferred = true;
|
||||||
|
} else {
|
||||||
|
module.offset = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const element_count: u64 = switch (length_inferred) {
|
||||||
|
true => 0,
|
||||||
|
false => @trap(),
|
||||||
|
};
|
||||||
|
if (!length_inferred) {
|
||||||
|
module.skip_space();
|
||||||
|
module.expect_character(right_bracket);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
const element_type = module.parse_type();
|
||||||
|
|
||||||
|
const array_type = switch (element_count) {
|
||||||
|
0 => blk: {
|
||||||
|
const array_type = module.types.append(.{
|
||||||
|
.name = "",
|
||||||
|
.bb = .{
|
||||||
|
.array = .{
|
||||||
|
.element_type = element_type,
|
||||||
|
.element_count = element_count,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break :blk array_type;
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return array_type;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1363,6 +1451,26 @@ pub const Module = struct {
|
|||||||
};
|
};
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
|
r[@intFromEnum(Token.Id.@"[")] = .{
|
||||||
|
.before = rule_before_bracket,
|
||||||
|
.after = rule_after_bracket,
|
||||||
|
.precedence = .postfix,
|
||||||
|
};
|
||||||
|
count += 1;
|
||||||
|
r[@intFromEnum(Token.Id.@"]")] = .{
|
||||||
|
.before = null,
|
||||||
|
.after = null,
|
||||||
|
.precedence = .none,
|
||||||
|
};
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
r[@intFromEnum(Token.Id.@",")] = .{
|
||||||
|
.before = null,
|
||||||
|
.after = null,
|
||||||
|
.precedence = .none,
|
||||||
|
};
|
||||||
|
count += 1;
|
||||||
|
|
||||||
assert(count == r.len);
|
assert(count == r.len);
|
||||||
break :blk r;
|
break :blk r;
|
||||||
};
|
};
|
||||||
@ -1565,14 +1673,26 @@ pub const Module = struct {
|
|||||||
};
|
};
|
||||||
break :blk token;
|
break :blk token;
|
||||||
},
|
},
|
||||||
'(' => blk: {
|
left_parenthesis => blk: {
|
||||||
module.offset += 1;
|
module.offset += 1;
|
||||||
break :blk .@"(";
|
break :blk .@"(";
|
||||||
},
|
},
|
||||||
')' => blk: {
|
right_parenthesis => blk: {
|
||||||
module.offset += 1;
|
module.offset += 1;
|
||||||
break :blk .@")";
|
break :blk .@")";
|
||||||
},
|
},
|
||||||
|
left_bracket => blk: {
|
||||||
|
module.offset += 1;
|
||||||
|
break :blk .@"[";
|
||||||
|
},
|
||||||
|
right_bracket => blk: {
|
||||||
|
module.offset += 1;
|
||||||
|
break :blk .@"]";
|
||||||
|
},
|
||||||
|
',' => blk: {
|
||||||
|
module.offset += 1;
|
||||||
|
break :blk .@",";
|
||||||
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1580,6 +1700,7 @@ pub const Module = struct {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Rule = struct {
|
const Rule = struct {
|
||||||
before: ?*const Rule.Function,
|
before: ?*const Rule.Function,
|
||||||
after: ?*const Rule.Function,
|
after: ?*const Rule.Function,
|
||||||
@ -1859,7 +1980,11 @@ pub const Module = struct {
|
|||||||
.bb = .{
|
.bb = .{
|
||||||
.variable_reference = variable,
|
.variable_reference = variable,
|
||||||
},
|
},
|
||||||
.kind = value_builder.kind,
|
.kind = if (variable.type) |t| switch (t.bb) {
|
||||||
|
.array, .function => .left,
|
||||||
|
.integer, .pointer => value_builder.kind,
|
||||||
|
else => @trap(),
|
||||||
|
} else value_builder.kind,
|
||||||
// if (variable.type != null and variable.type.?.bb == .function) .left else value_builder.kind,
|
// if (variable.type != null and variable.type.?.bb == .function) .left else value_builder.kind,
|
||||||
};
|
};
|
||||||
return value;
|
return value;
|
||||||
@ -2038,6 +2163,59 @@ pub const Module = struct {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Array initialization
|
||||||
|
fn rule_before_bracket(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
|
assert(value_builder.left == null);
|
||||||
|
|
||||||
|
var value_buffer: [64]*Value = undefined;
|
||||||
|
_ = &value_buffer;
|
||||||
|
var element_count: u64 = 0;
|
||||||
|
|
||||||
|
while (true) : (element_count += 1) {
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
if (module.consume_character_if_match(right_bracket)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const v = module.parse_value(.{});
|
||||||
|
value_buffer[element_count] = v;
|
||||||
|
|
||||||
|
_ = module.consume_character_if_match(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
const values = module.arena.allocate(*Value, element_count);
|
||||||
|
@memcpy(values, value_buffer[0..element_count]);
|
||||||
|
|
||||||
|
const value = module.values.add();
|
||||||
|
value.* = .{
|
||||||
|
.bb = .{
|
||||||
|
.array_initialization = .{
|
||||||
|
.values = values,
|
||||||
|
.is_constant = false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Array subscript
|
||||||
|
fn rule_after_bracket(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
|
const left = value_builder.left orelse module.report_error();
|
||||||
|
const index = module.parse_value(.{});
|
||||||
|
module.expect_character(right_bracket);
|
||||||
|
const value = module.values.add();
|
||||||
|
value.* = .{
|
||||||
|
.bb = .{
|
||||||
|
.array_expression = .{
|
||||||
|
.array_like = left,
|
||||||
|
.index = index,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
fn rule_before_parenthesis(noalias module: *Module, value_builder: Value.Builder) *Value {
|
fn rule_before_parenthesis(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
_ = module;
|
_ = module;
|
||||||
_ = value_builder;
|
_ = value_builder;
|
||||||
@ -3463,6 +3641,43 @@ pub const Module = struct {
|
|||||||
else => @trap(),
|
else => @trap(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.array_initialization => |array_initialization| switch (array_initialization.is_constant) {
|
||||||
|
true => blk: {
|
||||||
|
var llvm_value_buffer: [64]*llvm.Constant = undefined;
|
||||||
|
const element_count = array_initialization.values.len;
|
||||||
|
const llvm_values = llvm_value_buffer[0..element_count];
|
||||||
|
for (array_initialization.values, llvm_values) |v, *llvm_value| {
|
||||||
|
module.emit_value(function, v);
|
||||||
|
llvm_value.* = v.llvm.?.to_constant();
|
||||||
|
}
|
||||||
|
const array_value = value_type.bb.array.element_type.resolve(module).handle.get_constant_array(llvm_values);
|
||||||
|
break :blk array_value.to_value();
|
||||||
|
},
|
||||||
|
false => @trap(),
|
||||||
|
},
|
||||||
|
.array_expression => |array_expression| switch (array_expression.array_like.type.?.bb) {
|
||||||
|
.pointer => |pointer| switch (pointer.type.bb) {
|
||||||
|
.array => |array| blk: {
|
||||||
|
const zero_index = module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(0, @intFromBool(false)).to_value();
|
||||||
|
module.emit_value(function, array_expression.array_like);
|
||||||
|
module.emit_value(function, array_expression.index);
|
||||||
|
const gep = module.llvm.builder.create_gep(.{
|
||||||
|
.type = pointer.type.llvm.handle.?,
|
||||||
|
.aggregate = array_expression.array_like.llvm.?,
|
||||||
|
.indices = &.{ zero_index, array_expression.index.llvm.? },
|
||||||
|
});
|
||||||
|
|
||||||
|
const v = switch (value.kind) {
|
||||||
|
.left => gep,
|
||||||
|
.right => module.create_load(.{ .type = array.element_type, .value = gep }),
|
||||||
|
};
|
||||||
|
|
||||||
|
break :blk v;
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3626,6 +3841,54 @@ pub const Module = struct {
|
|||||||
module.report_error();
|
module.report_error();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.array_initialization => |*array_initialization| {
|
||||||
|
switch (expected_type.bb) {
|
||||||
|
.array => |*array| {
|
||||||
|
if (array.element_count == 0) {
|
||||||
|
array.element_count = array_initialization.values.len;
|
||||||
|
assert(lib.string.equal(expected_type.name, ""));
|
||||||
|
expected_type.name = array_type_name(module.arena, array.element_type, array.element_count);
|
||||||
|
} else {
|
||||||
|
if (array.element_count != array_initialization.values.len) {
|
||||||
|
module.report_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var is_constant = true;
|
||||||
|
for (array_initialization.values) |v| {
|
||||||
|
module.analyze_value_type(function, v, .{
|
||||||
|
.type = array.element_type,
|
||||||
|
});
|
||||||
|
is_constant = is_constant and v.is_constant();
|
||||||
|
}
|
||||||
|
|
||||||
|
array_initialization.is_constant = is_constant;
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.array_expression => |array_expression| {
|
||||||
|
module.analyze_value_type(function, array_expression.index, .{
|
||||||
|
.type = module.integer_type(64, false),
|
||||||
|
});
|
||||||
|
if (array_expression.array_like.kind != .left) {
|
||||||
|
module.report_error();
|
||||||
|
}
|
||||||
|
module.analyze_value_type(function, array_expression.array_like, .{});
|
||||||
|
const element_type = switch (array_expression.array_like.type.?.bb) {
|
||||||
|
.pointer => |pointer| switch (pointer.type.bb) {
|
||||||
|
.array => |array| array.element_type,
|
||||||
|
else => @trap(),
|
||||||
|
},
|
||||||
|
else => module.report_error(),
|
||||||
|
};
|
||||||
|
switch (value.kind) {
|
||||||
|
.left => @trap(),
|
||||||
|
.right => if (element_type != expected_type) {
|
||||||
|
module.report_error();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3945,7 +4208,26 @@ pub const Module = struct {
|
|||||||
.alignment = pointer_type.bb.pointer.alignment,
|
.alignment = pointer_type.bb.pointer.alignment,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.aggregate => @trap(),
|
.aggregate => switch (right.bb) {
|
||||||
|
.array_initialization => |array_initialization| switch (array_initialization.is_constant) {
|
||||||
|
true => {
|
||||||
|
module.emit_value(function, right);
|
||||||
|
const global_variable = module.llvm.module.create_global_variable(.{
|
||||||
|
.linkage = .InternalLinkage,
|
||||||
|
.name = "constarray", // TODO: format properly
|
||||||
|
.initial_value = right.llvm.?.to_constant(),
|
||||||
|
.type = value_type.resolve(module).handle,
|
||||||
|
});
|
||||||
|
global_variable.set_unnamed_address(.global);
|
||||||
|
const element_type = value_type.bb.array.element_type;
|
||||||
|
const alignment = element_type.get_byte_alignment();
|
||||||
|
global_variable.to_value().set_alignment(alignment);
|
||||||
|
_ = module.llvm.builder.create_memcpy(left.llvm.?, pointer_type.bb.pointer.alignment, global_variable.to_value(), alignment, module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(array_initialization.values.len * pointer_type.bb.pointer.type.bb.array.element_type.get_byte_size(), @intFromBool(false)).to_value());
|
||||||
|
},
|
||||||
|
false => @trap(),
|
||||||
|
},
|
||||||
|
else => @trap(),
|
||||||
|
},
|
||||||
.complex => @trap(),
|
.complex => @trap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4153,6 +4435,11 @@ const Token = union(Id) {
|
|||||||
// Parenthesis
|
// Parenthesis
|
||||||
@"(",
|
@"(",
|
||||||
@")",
|
@")",
|
||||||
|
// Bracket
|
||||||
|
@"[",
|
||||||
|
@"]",
|
||||||
|
|
||||||
|
@",",
|
||||||
|
|
||||||
const Id = enum {
|
const Id = enum {
|
||||||
none,
|
none,
|
||||||
@ -4205,6 +4492,11 @@ const Token = union(Id) {
|
|||||||
// Parenthesis
|
// Parenthesis
|
||||||
@"(",
|
@"(",
|
||||||
@")",
|
@")",
|
||||||
|
// Bracket
|
||||||
|
@"[",
|
||||||
|
@"]",
|
||||||
|
|
||||||
|
@",",
|
||||||
};
|
};
|
||||||
|
|
||||||
const Integer = struct {
|
const Integer = struct {
|
||||||
|
@ -203,4 +203,5 @@ const names = &[_][]const u8{
|
|||||||
"extern",
|
"extern",
|
||||||
"byte_size",
|
"byte_size",
|
||||||
"basic_branch",
|
"basic_branch",
|
||||||
|
"basic_array",
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user