Merge pull request #204 from birth-software/one-complement

One complement
This commit is contained in:
David 2024-06-01 09:19:54 -06:00 committed by GitHub
commit 4d29a31a4a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 111 additions and 18 deletions

View File

@ -450,14 +450,29 @@ const Parser = struct{
} }
fn parse_single_expression(parser: *Parser, analyzer: *Analyzer, thread: *Thread, file: *File, maybe_type: ?*Type, side: Side) *Value { 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 src = file.source_code;
const Unary = enum{
none,
one_complement,
};
const unary: Unary = switch (src[parser.i]) {
'A'...'Z', 'a'...'z', '_' => Unary.none,
'0'...'9' => Unary.none,
'~' => block: {
parser.i += 1;
break :block .one_complement;
},
else => unreachable,
};
_ = side; // autofix
const starting_index = parser.i; const starting_index = parser.i;
const starting_ch = src[starting_index]; 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) {
assert(unary == .none);
const ty = maybe_type orelse exit(1); const ty = maybe_type orelse exit(1);
switch (ty.sema.id) { switch (ty.sema.id) {
.integer => { .integer => {
@ -484,15 +499,32 @@ const Parser = struct{
.function_definition => { .function_definition => {
const function_definition = global.get_payload(.function_definition); const function_definition = global.get_payload(.function_definition);
const declaration_argument_count = function_definition.declaration.argument_types.len; const declaration_argument_count = function_definition.declaration.argument_types.len;
const argument_count: u32 = 0; var argument_values = PinnedArray(*Value){};
while (src[parser.i] != ')') { while (true) {
unreachable; parser.skip_space(src);
}
parser.i += 1;
if (declaration_argument_count != argument_count) { if (src[parser.i] == ')') {
break;
}
const argument_index = argument_values.length;
if (argument_index >= declaration_argument_count) {
exit(1); exit(1);
} }
const expected_argument_type = function_definition.declaration.argument_types[argument_index];
const passed_argument_value = parser.parse_expression(analyzer, thread, file, expected_argument_type, .right);
_ = argument_values.append(passed_argument_value);
parser.skip_space(src);
switch (src[parser.i]) {
',' => parser.i += 1,
')' => {},
else => unreachable,
}
}
parser.i += 1;
const call = thread.calls.append(.{ const call = thread.calls.append(.{
.instruction = .{ .instruction = .{
@ -506,6 +538,7 @@ const Parser = struct{
.id = .call, .id = .call,
}, },
.callable = &function_definition.declaration.value, .callable = &function_definition.declaration.value,
.arguments = argument_values.const_slice(),
}); });
_ = analyzer.current_basic_block.instructions.append(&call.instruction); _ = analyzer.current_basic_block.instructions.append(&call.instruction);
return &call.instruction.value; return &call.instruction.value;
@ -561,6 +594,7 @@ const Parser = struct{
.id = .call, .id = .call,
}, },
.callable = &lazy_expression.value, .callable = &lazy_expression.value,
.arguments = &.{},
}); });
_ = analyzer.current_basic_block.instructions.append(&call.instruction); _ = analyzer.current_basic_block.instructions.append(&call.instruction);
@ -576,9 +610,9 @@ const Parser = struct{
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} }
}, },
' ', ';', ')' => { ' ', ',', ';', ')' => {
switch (lookup_result.declaration.*.id) { const local = switch (lookup_result.declaration.*.id) {
.local => { .local => block: {
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();
@ -605,9 +639,9 @@ const Parser = struct{
.is_volatile = false, .is_volatile = false,
}); });
_ = analyzer.current_basic_block.instructions.append(&load.instruction); _ = analyzer.current_basic_block.instructions.append(&load.instruction);
return &load.instruction.value; break :block &load.instruction.value;
}, },
.argument => { .argument => block: {
const argument_declaration = lookup_result.declaration.*.get_payload(.argument); const argument_declaration = lookup_result.declaration.*.get_payload(.argument);
const argument_symbol = argument_declaration.to_symbol(); const argument_symbol = argument_declaration.to_symbol();
if (maybe_type) |ty| { if (maybe_type) |ty| {
@ -632,10 +666,47 @@ const Parser = struct{
.is_volatile = false, .is_volatile = false,
}); });
_ = analyzer.current_basic_block.instructions.append(&load.instruction); _ = analyzer.current_basic_block.instructions.append(&load.instruction);
return &load.instruction.value; break :block &load.instruction.value;
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} };
const local_type = local.get_type();
return switch (unary) {
.none => local,
.one_complement => block: {
const operand = thread.constant_ints.append(.{
.type = local_type,
.value = .{
.sema = .{
.thread = thread.get_index(),
.resolved = true,
.id = .constant_int,
},
},
.n = std.math.maxInt(u64),
});
const xor = thread.integer_binary_operations.append(.{
.instruction = .{
.value = .{
.sema = .{
.thread = thread.get_index(),
.resolved = true,
.id = .instruction,
},
},
.id = .integer_binary_operation,
},
.left = local,
.right = &operand.value,
.id = .xor,
.type = local_type,
});
_ = analyzer.current_basic_block.instructions.append(&xor.instruction);
break :block &xor.instruction.value;
},
};
}, },
else => exit(1), else => exit(1),
} }
@ -756,7 +827,7 @@ const Parser = struct{
} }
switch (src[parser.i]) { switch (src[parser.i]) {
')', ';' => return previous_value, ')', ';', ',' => return previous_value,
'=' => { '=' => {
current_operation = .assign; current_operation = .assign;
parser.i += 1; parser.i += 1;
@ -1400,6 +1471,7 @@ const Jump = struct {
const Call = struct{ const Call = struct{
instruction: Instruction, instruction: Instruction,
callable: *Value, callable: *Value,
arguments: []const *Value,
}; };
const Load = struct { const Load = struct {
@ -2704,8 +2776,15 @@ fn worker_thread(thread_index: u32, cpu_count: *u32) void {
const callee_function = callee.toFunction() orelse unreachable; const callee_function = callee.toFunction() orelse unreachable;
const function_type = callee_function.getType(); const function_type = callee_function.getType();
const arguments: []const *LLVM.Value = &.{}; var arguments = std.BoundedArray(*LLVM.Value, 512){};
const call_i = thread.llvm.builder.createCall(function_type, callee, arguments.ptr, arguments.len, "", "".len, null); for (call.arguments) |argument| {
const llvm_argument = llvm_get_value(thread, argument);
_ = arguments.appendAssumeCapacity(llvm_argument);
}
const args = arguments.constSlice();
const call_i = thread.llvm.builder.createCall(function_type, callee, args.ptr, args.len, "", "".len, null);
break :block call_i.toValue(); break :block call_i.toValue();
}, },
.integer_compare => block: { .integer_compare => block: {

View File

@ -0,0 +1,14 @@
fn align_forward(value: s32, alignment: s32) s32 {
>mask = alignment - 1;
return (value + mask) & ~mask;
}
fn [cc(.c)] main [export] () s32 {
>a: s32 = 1;
>aligned_a = align_forward(a, 8);
>b: s32 = 9;
>aligned_b = align_forward(b, 8);
>c: s32 = 512;
>aligned_c = align_forward(c, 0x1000);
return (aligned_a - 8) + (aligned_b - 16) + (aligned_c - 0x1000);
}