One complement
This commit is contained in:
parent
7f56a0fe3d
commit
9485bed0a7
@ -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: {
|
||||||
|
14
retest/standalone/one_complement/main.nat
Normal file
14
retest/standalone/one_complement/main.nat
Normal 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);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user