Implement 'add' and 'sub'
This commit is contained in:
parent
1d52b9abdc
commit
69e6fba3fe
@ -282,55 +282,93 @@ const Parser = struct{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_typed_expression(parser: *Parser, analyzer: *Analyzer, thread: *Thread, file: *File, ty: *Type, side: Side) *Value {
|
fn parse_constant_integer(parser: *Parser, thread: *Thread, file: *File, ty: *Type) *ConstantInt {
|
||||||
_ = side; // autofix
|
|
||||||
_ = &analyzer;
|
|
||||||
const src = file.source_code;
|
const src = file.source_code;
|
||||||
assert(ty.sema.id != .unresolved);
|
const starting_index = parser.i;
|
||||||
const starting_ch = src[parser.i];
|
const starting_ch = src[starting_index];
|
||||||
|
if (starting_ch == '0') {
|
||||||
|
const follow_up_character = src[parser.i + 1];
|
||||||
|
const is_hex_start = follow_up_character == 'x';
|
||||||
|
const is_octal_start = follow_up_character == 'o';
|
||||||
|
const is_bin_start = follow_up_character == 'b';
|
||||||
|
const is_prefixed_start = is_hex_start or is_octal_start or is_bin_start;
|
||||||
|
const follow_up_alpha = is_alphabetic(follow_up_character);
|
||||||
|
const follow_up_digit = is_decimal_digit(follow_up_character);
|
||||||
|
const is_valid_after_zero = is_space(follow_up_character) or (!follow_up_digit and !follow_up_alpha);
|
||||||
|
|
||||||
|
if (is_prefixed_start) {
|
||||||
|
exit(1);
|
||||||
|
} else if (is_valid_after_zero) {
|
||||||
|
parser.i += 1;
|
||||||
|
const constant_int = thread.constant_ints.append(.{
|
||||||
|
.value = .{
|
||||||
|
.sema = .{
|
||||||
|
.thread = thread.get_index(),
|
||||||
|
.resolved = true,
|
||||||
|
.id = .constant_int,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.n = 0,
|
||||||
|
.type = ty,
|
||||||
|
});
|
||||||
|
return constant_int;
|
||||||
|
} else {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (is_decimal_digit(src[parser.i])) {
|
||||||
|
parser.i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const character_count = parser.i - starting_index;
|
||||||
|
const slice = src[starting_index..][0..character_count];
|
||||||
|
var i = character_count;
|
||||||
|
var integer: u64 = 0;
|
||||||
|
var factor: u64 = 1;
|
||||||
|
|
||||||
|
while (i > 0) {
|
||||||
|
i -= 1;
|
||||||
|
const ch = slice[i];
|
||||||
|
const int = ch - '0';
|
||||||
|
const extra = int * factor;
|
||||||
|
integer += extra;
|
||||||
|
factor *= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
const constant_int = thread.constant_ints.append(.{
|
||||||
|
.value = .{
|
||||||
|
.sema = .{
|
||||||
|
.thread = thread.get_index(),
|
||||||
|
.resolved = true,
|
||||||
|
.id = .constant_int,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.n = integer,
|
||||||
|
.type = ty,
|
||||||
|
});
|
||||||
|
|
||||||
|
return constant_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_single_expression(parser: *Parser, analyzer: *Analyzer, thread: *Thread, file: *File, maybe_type: ?*Type, side: Side) *Value {
|
||||||
|
_ = side; // autofix
|
||||||
|
const src = file.source_code;
|
||||||
|
const starting_index = parser.i;
|
||||||
|
const starting_ch = src[starting_index];
|
||||||
const is_digit_start = is_decimal_digit(starting_ch);
|
const is_digit_start = is_decimal_digit(starting_ch);
|
||||||
const is_alpha_start = is_alphabetic(starting_ch);
|
const is_alpha_start = is_alphabetic(starting_ch);
|
||||||
|
|
||||||
if (is_digit_start) {
|
if (is_digit_start) {
|
||||||
|
const ty = maybe_type orelse exit(1);
|
||||||
switch (ty.sema.id) {
|
switch (ty.sema.id) {
|
||||||
.integer => {
|
.integer => {
|
||||||
if (starting_ch == '0') {
|
const constant_int = parser.parse_constant_integer(thread, file, ty);
|
||||||
const follow_up_character = src[parser.i + 1];
|
return &constant_int.value;
|
||||||
const is_hex_start = follow_up_character == 'x';
|
|
||||||
const is_octal_start = follow_up_character == 'o';
|
|
||||||
const is_bin_start = follow_up_character == 'b';
|
|
||||||
const is_prefixed_start = is_hex_start or is_octal_start or is_bin_start;
|
|
||||||
const follow_up_alpha = is_alphabetic(follow_up_character);
|
|
||||||
const follow_up_digit = is_decimal_digit(follow_up_character);
|
|
||||||
const is_valid_after_zero = is_space(follow_up_character) or (!follow_up_digit and !follow_up_alpha);
|
|
||||||
|
|
||||||
if (is_prefixed_start) {
|
|
||||||
exit(1);
|
|
||||||
} else if (is_valid_after_zero) {
|
|
||||||
parser.i += 1;
|
|
||||||
const constant_int = thread.constant_ints.append(.{
|
|
||||||
.value = .{
|
|
||||||
.sema = .{
|
|
||||||
.thread = thread.get_index(),
|
|
||||||
.resolved = true,
|
|
||||||
.id = .constant_int,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.n = 0,
|
|
||||||
.type = ty,
|
|
||||||
});
|
|
||||||
return &constant_int.value;
|
|
||||||
} else {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit(0);
|
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
} else if (is_alpha_start) {
|
} else if (is_alpha_start) {
|
||||||
var resolved = true;
|
var resolved = true;
|
||||||
_ = &resolved; // autofix
|
|
||||||
const identifier = parser.parse_identifier(thread, src);
|
const identifier = parser.parse_identifier(thread, src);
|
||||||
|
|
||||||
if (analyzer.current_scope.get_declaration(identifier)) |lookup_result| {
|
if (analyzer.current_scope.get_declaration(identifier)) |lookup_result| {
|
||||||
@ -375,7 +413,7 @@ const Parser = struct{
|
|||||||
.resolved = false,
|
.resolved = false,
|
||||||
.id = .instruction,
|
.id = .instruction,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.id = .call,
|
.id = .call,
|
||||||
},
|
},
|
||||||
.callable = &lazy_expression.value,
|
.callable = &lazy_expression.value,
|
||||||
@ -393,36 +431,37 @@ const Parser = struct{
|
|||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
exit(1);
|
|
||||||
},
|
},
|
||||||
';' => {
|
' ', ';' => {
|
||||||
switch (lookup_result.declaration.*.id) {
|
switch (lookup_result.declaration.*.id) {
|
||||||
.local => {
|
.local => {
|
||||||
const local_declaration = lookup_result.declaration.*.get_payload(.local);
|
const local_declaration = lookup_result.declaration.*.get_payload(.local);
|
||||||
const local_symbol = local_declaration.to_symbol();
|
const local_symbol = local_declaration.to_symbol();
|
||||||
|
|
||||||
switch (typecheck(ty, local_symbol.type)) {
|
if (maybe_type) |ty| {
|
||||||
.success => {
|
switch (typecheck(ty, local_symbol.type)) {
|
||||||
const load = thread.loads.append(.{
|
.success => {},
|
||||||
.instruction = .{
|
}
|
||||||
.value = .{
|
|
||||||
.sema = .{
|
|
||||||
.thread = thread.get_index(),
|
|
||||||
.resolved = true,
|
|
||||||
.id = .instruction,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.id = .load,
|
|
||||||
},
|
|
||||||
.value = &local_symbol.instruction.value,
|
|
||||||
.type = local_symbol.type,
|
|
||||||
.alignment = local_symbol.type.alignment,
|
|
||||||
.is_volatile = false,
|
|
||||||
});
|
|
||||||
_ = analyzer.current_basic_block.instructions.append(&load.instruction);
|
|
||||||
return &load.instruction.value;
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const load = thread.loads.append(.{
|
||||||
|
.instruction = .{
|
||||||
|
.value = .{
|
||||||
|
.sema = .{
|
||||||
|
.thread = thread.get_index(),
|
||||||
|
.resolved = true,
|
||||||
|
.id = .instruction,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.id = .load,
|
||||||
|
},
|
||||||
|
.value = &local_symbol.instruction.value,
|
||||||
|
.type = local_symbol.type,
|
||||||
|
.alignment = local_symbol.type.alignment,
|
||||||
|
.is_volatile = false,
|
||||||
|
});
|
||||||
|
_ = analyzer.current_basic_block.instructions.append(&load.instruction);
|
||||||
|
return &load.instruction.value;
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
@ -434,6 +473,88 @@ const Parser = struct{
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CurrentOperation = enum{
|
||||||
|
none,
|
||||||
|
add,
|
||||||
|
add_assign,
|
||||||
|
sub,
|
||||||
|
sub_assign,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn parse_expression(parser: *Parser, analyzer: *Analyzer, thread: *Thread, file: *File, ty: ?*Type, side: Side) *Value {
|
||||||
|
const src = file.source_code;
|
||||||
|
|
||||||
|
var current_operation = CurrentOperation.none;
|
||||||
|
var previous_value: *Value = undefined;
|
||||||
|
while (true) {
|
||||||
|
const current_value = parser.parse_single_expression(analyzer, thread, file, ty, side);
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
switch (current_operation) {
|
||||||
|
.none => {
|
||||||
|
previous_value = current_value;
|
||||||
|
},
|
||||||
|
.add, .sub => {
|
||||||
|
const add = thread.integer_binary_operations.append(.{
|
||||||
|
.instruction = .{
|
||||||
|
.value = .{
|
||||||
|
.sema = .{
|
||||||
|
.thread = thread.get_index(),
|
||||||
|
.resolved = true,
|
||||||
|
.id = .instruction,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.id = .integer_binary_operation,
|
||||||
|
},
|
||||||
|
.left = previous_value,
|
||||||
|
.right = current_value,
|
||||||
|
.id = switch (current_operation) {
|
||||||
|
.none, .add_assign, .sub_assign => unreachable,
|
||||||
|
inline else => |co| @field(IntegerBinaryOperation.Id, @tagName(co)),
|
||||||
|
},
|
||||||
|
.type = if (ty) |t| t else current_value.get_type(),
|
||||||
|
});
|
||||||
|
_ = analyzer.current_basic_block.instructions.append(&add.instruction);
|
||||||
|
previous_value = &add.instruction.value;
|
||||||
|
},
|
||||||
|
.add_assign, .sub_assign => unreachable,
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (src[parser.i]) {
|
||||||
|
';' => return previous_value,
|
||||||
|
'+' => {
|
||||||
|
current_operation = .add;
|
||||||
|
parser.i += 1;
|
||||||
|
|
||||||
|
switch (src[parser.i]) {
|
||||||
|
'=' => {
|
||||||
|
current_operation = .add_assign;
|
||||||
|
parser.i += 1;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
},
|
||||||
|
'-' => {
|
||||||
|
current_operation = .sub;
|
||||||
|
parser.i += 1;
|
||||||
|
|
||||||
|
switch (src[parser.i]) {
|
||||||
|
'=' => {
|
||||||
|
current_operation = .sub_assign;
|
||||||
|
parser.i += 1;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
},
|
||||||
|
else => @panic((src.ptr + parser.i)[0..1]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const LazyExpression = struct {
|
const LazyExpression = struct {
|
||||||
@ -494,20 +615,6 @@ const LazyExpression = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// fn Descriptor(comptime Id: type, comptime Integer: type) type {
|
|
||||||
// return packed struct(Integer) {
|
|
||||||
// index: @Type(.{
|
|
||||||
// .Int = .{
|
|
||||||
// .signedness = .unsigned,
|
|
||||||
// .bits = @typeInfo(Integer).Int.bits - @typeInfo(@typeInfo(Id).Enum.tag_type).Int.bits,
|
|
||||||
// },
|
|
||||||
// }),
|
|
||||||
// id: Id,
|
|
||||||
//
|
|
||||||
// pub const Index = PinnedArray(@This()).Index;
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
const Value = struct {
|
const Value = struct {
|
||||||
llvm: ?*LLVM.Value = null,
|
llvm: ?*LLVM.Value = null,
|
||||||
sema: packed struct(u32) {
|
sema: packed struct(u32) {
|
||||||
@ -535,6 +642,26 @@ const Value = struct {
|
|||||||
assert(value.sema.id == id);
|
assert(value.sema.id == id);
|
||||||
return @fieldParentPtr("value", value);
|
return @fieldParentPtr("value", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_type(value: *Value) *Type {
|
||||||
|
return switch (value.sema.id) {
|
||||||
|
.instruction => blk: {
|
||||||
|
const instruction = value.get_payload(.instruction);
|
||||||
|
break :blk switch (instruction.id) {
|
||||||
|
.integer_binary_operation => block: {
|
||||||
|
const bin_op = instruction.get_payload(.integer_binary_operation);
|
||||||
|
break :block bin_op.type;
|
||||||
|
},
|
||||||
|
.load => block: {
|
||||||
|
const load = instruction.get_payload(.load);
|
||||||
|
break :block load.type;
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Type = struct {
|
const Type = struct {
|
||||||
@ -747,11 +874,18 @@ const Function = struct{
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ConstantInt = struct{
|
||||||
|
value: Value,
|
||||||
|
n: u64,
|
||||||
|
type: *Type,
|
||||||
|
};
|
||||||
|
|
||||||
const Instruction = struct{
|
const Instruction = struct{
|
||||||
value: Value,
|
value: Value,
|
||||||
id: Id,
|
id: Id,
|
||||||
|
|
||||||
const Id = enum{
|
const Id = enum{
|
||||||
|
integer_binary_operation,
|
||||||
call,
|
call,
|
||||||
load,
|
load,
|
||||||
local_symbol,
|
local_symbol,
|
||||||
@ -762,6 +896,7 @@ const Instruction = struct{
|
|||||||
|
|
||||||
const id_to_instruction_map = std.EnumArray(Id, type).init(.{
|
const id_to_instruction_map = std.EnumArray(Id, type).init(.{
|
||||||
.call = Call,
|
.call = Call,
|
||||||
|
.integer_binary_operation = IntegerBinaryOperation,
|
||||||
.local_symbol = LocalSymbol,
|
.local_symbol = LocalSymbol,
|
||||||
.load = Load,
|
.load = Load,
|
||||||
.ret = Return,
|
.ret = Return,
|
||||||
@ -775,10 +910,17 @@ const Instruction = struct{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const ConstantInt = struct{
|
const IntegerBinaryOperation = struct {
|
||||||
value: Value,
|
instruction: Instruction,
|
||||||
n: u64,
|
left: *Value,
|
||||||
|
right: *Value,
|
||||||
type: *Type,
|
type: *Type,
|
||||||
|
id: Id,
|
||||||
|
|
||||||
|
const Id = enum{
|
||||||
|
add,
|
||||||
|
sub,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const Call = struct{
|
const Call = struct{
|
||||||
@ -839,6 +981,7 @@ const Thread = struct{
|
|||||||
debug_info_file_map: PinnedHashMap(u32, LLVMFile) = .{},
|
debug_info_file_map: PinnedHashMap(u32, LLVMFile) = .{},
|
||||||
// pending_values_per_file: PinnedArray(PinnedArray(*Value)) = .{},
|
// pending_values_per_file: PinnedArray(PinnedArray(*Value)) = .{},
|
||||||
calls: PinnedArray(Call) = .{},
|
calls: PinnedArray(Call) = .{},
|
||||||
|
integer_binary_operations: PinnedArray(IntegerBinaryOperation) = .{},
|
||||||
loads: PinnedArray(Load) = .{},
|
loads: PinnedArray(Load) = .{},
|
||||||
stores: PinnedArray(Store) = .{},
|
stores: PinnedArray(Store) = .{},
|
||||||
returns: PinnedArray(Return) = .{},
|
returns: PinnedArray(Return) = .{},
|
||||||
@ -1991,15 +2134,12 @@ fn worker_thread(thread_index: u32, cpu_count: *u32) void {
|
|||||||
|
|
||||||
for (nat_entry_basic_block.instructions.slice()) |instruction| {
|
for (nat_entry_basic_block.instructions.slice()) |instruction| {
|
||||||
const value: *LLVM.Value = switch (instruction.id) {
|
const value: *LLVM.Value = switch (instruction.id) {
|
||||||
.call => block: {
|
.store => block: {
|
||||||
const call = instruction.get_payload(.call);
|
const store = instruction.get_payload(.store);
|
||||||
const callee = llvm_get_value(thread, call.callable);
|
const destination = llvm_get_value(thread, store.destination);
|
||||||
const callee_function = callee.toFunction() orelse unreachable;
|
const source = llvm_get_value(thread, store.source);
|
||||||
const function_type = callee_function.getType();
|
const store_instruction = builder.createStore(source, destination, store.is_volatile, store.alignment);
|
||||||
|
break :block store_instruction.toValue();
|
||||||
const arguments: []const *LLVM.Value = &.{};
|
|
||||||
const call_i = thread.llvm.builder.createCall(function_type, callee, arguments.ptr, arguments.len, "", "".len, null);
|
|
||||||
break :block call_i.toValue();
|
|
||||||
},
|
},
|
||||||
.load => block: {
|
.load => block: {
|
||||||
const load = instruction.get_payload(.load);
|
const load = instruction.get_payload(.load);
|
||||||
@ -2009,19 +2149,34 @@ fn worker_thread(thread_index: u32, cpu_count: *u32) void {
|
|||||||
const load_instruction = builder.createLoad(load_type, load_value, load.is_volatile, "", "".len, load.alignment);
|
const load_instruction = builder.createLoad(load_type, load_value, load.is_volatile, "", "".len, load.alignment);
|
||||||
break :block load_instruction.toValue();
|
break :block load_instruction.toValue();
|
||||||
},
|
},
|
||||||
.store => block: {
|
|
||||||
const store = instruction.get_payload(.store);
|
|
||||||
const destination = llvm_get_value(thread, store.destination);
|
|
||||||
const source = llvm_get_value(thread, store.source);
|
|
||||||
const store_instruction = builder.createStore(source, destination, store.is_volatile, store.alignment);
|
|
||||||
break :block store_instruction.toValue();
|
|
||||||
},
|
|
||||||
.ret => block: {
|
.ret => block: {
|
||||||
const return_instruction = instruction.get_payload(.ret);
|
const return_instruction = instruction.get_payload(.ret);
|
||||||
const return_value = llvm_get_value(thread, return_instruction.value);
|
const return_value = llvm_get_value(thread, return_instruction.value);
|
||||||
const ret = thread.llvm.builder.createRet(return_value);
|
const ret = thread.llvm.builder.createRet(return_value);
|
||||||
break :block ret.toValue();
|
break :block ret.toValue();
|
||||||
},
|
},
|
||||||
|
.integer_binary_operation => block: {
|
||||||
|
const integer_binary_operation = instruction.get_payload(.integer_binary_operation);
|
||||||
|
const left = llvm_get_value(thread, integer_binary_operation.left);
|
||||||
|
const right = llvm_get_value(thread, integer_binary_operation.right);
|
||||||
|
const integer_type = integer_binary_operation.type.get_payload(.integer);
|
||||||
|
const no_unsigned_wrapping = integer_type.signedness == .unsigned;
|
||||||
|
const no_signed_wrapping = integer_type.signedness == .signed;
|
||||||
|
break :block switch (integer_binary_operation.id) {
|
||||||
|
.add => builder.createAdd(left, right, "", "".len, no_unsigned_wrapping, no_signed_wrapping),
|
||||||
|
.sub => builder.createSub(left, right, "", "".len, no_unsigned_wrapping, no_signed_wrapping),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.call => block: {
|
||||||
|
const call = instruction.get_payload(.call);
|
||||||
|
const callee = llvm_get_value(thread, call.callable);
|
||||||
|
const callee_function = callee.toFunction() orelse unreachable;
|
||||||
|
const function_type = callee_function.getType();
|
||||||
|
|
||||||
|
const arguments: []const *LLVM.Value = &.{};
|
||||||
|
const call_i = thread.llvm.builder.createCall(function_type, callee, arguments.ptr, arguments.len, "", "".len, null);
|
||||||
|
break :block call_i.toValue();
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2056,12 +2211,14 @@ fn worker_thread(thread_index: u32, cpu_count: *u32) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const verify_module = true;
|
const verify_module = true;
|
||||||
|
const print_module_at_failure = true;
|
||||||
|
const print_module = false;
|
||||||
|
|
||||||
if (verify_module) {
|
if (verify_module) {
|
||||||
var verification_message: []const u8 = undefined;
|
var verification_message: []const u8 = undefined;
|
||||||
const verification_success = thread.llvm.module.verify(&verification_message.ptr, &verification_message.len);
|
const verification_success = thread.llvm.module.verify(&verification_message.ptr, &verification_message.len);
|
||||||
if (!verification_success) {
|
if (!verification_success) {
|
||||||
const print_module = true;
|
if (print_module_at_failure) {
|
||||||
if (print_module) {
|
|
||||||
var module_content: []const u8 = undefined;
|
var module_content: []const u8 = undefined;
|
||||||
thread.llvm.module.toString(&module_content.ptr, &module_content.len);
|
thread.llvm.module.toString(&module_content.ptr, &module_content.len);
|
||||||
write(module_content);
|
write(module_content);
|
||||||
@ -2072,6 +2229,13 @@ fn worker_thread(thread_index: u32, cpu_count: *u32) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (print_module) {
|
||||||
|
var module_content: []const u8 = undefined;
|
||||||
|
thread.llvm.module.toString(&module_content.ptr, &module_content.len);
|
||||||
|
write(module_content);
|
||||||
|
write("\n");
|
||||||
|
}
|
||||||
|
|
||||||
thread.add_control_work(.{
|
thread.add_control_work(.{
|
||||||
.id = .llvm_notify_ir_done,
|
.id = .llvm_notify_ir_done,
|
||||||
});
|
});
|
||||||
@ -2316,7 +2480,7 @@ pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser
|
|||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
if (function.declaration.return_type.sema.id != .unresolved) {
|
if (function.declaration.return_type.sema.id != .unresolved) {
|
||||||
const return_value = parser.parse_typed_expression(analyzer, thread, file, function.declaration.return_type, .right);
|
const return_value = parser.parse_expression(analyzer, thread, file, function.declaration.return_type, .right);
|
||||||
parser.expect_character(src, ';');
|
parser.expect_character(src, ';');
|
||||||
|
|
||||||
const return_expression = thread.returns.append(.{
|
const return_expression = thread.returns.append(.{
|
||||||
@ -2362,20 +2526,51 @@ pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser
|
|||||||
exit_with_error("TODO: local attributes");
|
exit_with_error("TODO: local attributes");
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.expect_character(src, ':');
|
|
||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
const local_type = parser.parse_type_expression(thread, src);
|
const LocalResult = struct {
|
||||||
|
initial_value: *Value,
|
||||||
|
type: *Type,
|
||||||
|
};
|
||||||
|
const result: LocalResult = switch (src[parser.i]) {
|
||||||
|
':' => block: {
|
||||||
|
parser.i += 1;
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
const local_type = parser.parse_type_expression(thread, src);
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
parser.expect_character(src, '=');
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
const local_initial_value = parser.parse_expression(analyzer, thread, file, local_type, .right);
|
||||||
|
|
||||||
|
break :block .{
|
||||||
|
.initial_value = local_initial_value,
|
||||||
|
.type = local_type,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
'=' => block: {
|
||||||
|
parser.i += 1;
|
||||||
|
|
||||||
|
parser.skip_space(src);
|
||||||
|
|
||||||
|
const local_initial_value = parser.parse_expression(analyzer, thread, file, null, .right);
|
||||||
|
|
||||||
|
const local_type = local_initial_value.get_type();
|
||||||
|
|
||||||
|
break :block .{
|
||||||
|
.initial_value = local_initial_value,
|
||||||
|
.type = local_type,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => exit(1),
|
||||||
|
};
|
||||||
|
|
||||||
parser.skip_space(src);
|
parser.skip_space(src);
|
||||||
|
|
||||||
parser.expect_character(src, '=');
|
|
||||||
|
|
||||||
parser.skip_space(src);
|
|
||||||
|
|
||||||
const local_initial_value = parser.parse_typed_expression(analyzer, thread, file, local_type, .right);
|
|
||||||
|
|
||||||
parser.expect_character(src, ';');
|
parser.expect_character(src, ';');
|
||||||
|
|
||||||
const local_symbol = thread.local_symbols.append(.{
|
const local_symbol = thread.local_symbols.append(.{
|
||||||
@ -2384,19 +2579,19 @@ pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser
|
|||||||
.id = .local,
|
.id = .local,
|
||||||
.name = local_name,
|
.name = local_name,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.type = local_type,
|
.type = result.type,
|
||||||
.instruction = .{
|
.instruction = .{
|
||||||
.value = .{
|
.value = .{
|
||||||
.sema = .{
|
.sema = .{
|
||||||
.thread = thread.get_index(),
|
.thread = thread.get_index(),
|
||||||
.resolved = local_type.sema.resolved and local_initial_value.sema.resolved,
|
.resolved = result.type.sema.resolved and result.initial_value.sema.resolved,
|
||||||
.id = .instruction,
|
.id = .instruction,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.id = .local_symbol,
|
.id = .local_symbol,
|
||||||
},
|
},
|
||||||
.alignment = local_type.alignment,
|
.alignment = result.type.alignment,
|
||||||
});
|
});
|
||||||
|
|
||||||
_ = analyzer.current_function.stack_slots.append(local_symbol);
|
_ = analyzer.current_function.stack_slots.append(local_symbol);
|
||||||
@ -2409,11 +2604,11 @@ pub fn analyze_local_block(thread: *Thread, analyzer: *Analyzer, parser: *Parser
|
|||||||
.resolved = true,
|
.resolved = true,
|
||||||
.id = .instruction,
|
.id = .instruction,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.id = .store,
|
.id = .store,
|
||||||
},
|
},
|
||||||
.destination = &local_symbol.instruction.value,
|
.destination = &local_symbol.instruction.value,
|
||||||
.source = local_initial_value,
|
.source = result.initial_value,
|
||||||
.alignment = local_symbol.alignment,
|
.alignment = local_symbol.alignment,
|
||||||
.is_volatile = false,
|
.is_volatile = false,
|
||||||
});
|
});
|
||||||
|
8
retest/standalone/add_sub/main.nat
Normal file
8
retest/standalone/add_sub/main.nat
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fn [cc(.c)] main [export]() s32 {
|
||||||
|
>a: s32 = 1;
|
||||||
|
>b: s32 = 2;
|
||||||
|
>c = a + b;
|
||||||
|
>d: s32 = 3;
|
||||||
|
>e = d - c;
|
||||||
|
return e;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user