Trailing zeroes
This commit is contained in:
parent
c5712d4f3a
commit
03e2d6798f
@ -3670,6 +3670,7 @@ pub const Instruction = union(enum) {
|
||||
integer_compare: IntegerCompare,
|
||||
integer_binary_operation: Instruction.IntegerBinaryOperation,
|
||||
jump: Jump,
|
||||
leading_zeroes: V,
|
||||
load: Load,
|
||||
memcpy: Memcpy,
|
||||
umin: Min,
|
||||
@ -3683,6 +3684,7 @@ pub const Instruction = union(enum) {
|
||||
store: Store,
|
||||
syscall: Syscall,
|
||||
@"switch": Switch,
|
||||
trailing_zeroes: V,
|
||||
trap,
|
||||
@"unreachable",
|
||||
|
||||
@ -4375,11 +4377,13 @@ pub const IntrinsicId = enum {
|
||||
@"error",
|
||||
int_to_pointer,
|
||||
import,
|
||||
leading_zeroes,
|
||||
min,
|
||||
name,
|
||||
size,
|
||||
sign_extend,
|
||||
syscall,
|
||||
trailing_zeroes,
|
||||
trap,
|
||||
zero_extend,
|
||||
};
|
||||
@ -4964,6 +4968,36 @@ pub const Builder = struct {
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
},
|
||||
.trailing_zeroes => {
|
||||
assert(argument_node_list.len == 1);
|
||||
const argument = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, argument_node_list[0], .right);
|
||||
const trailing_zeroes = try unit.instructions.append(context.my_allocator, .{
|
||||
.trailing_zeroes = argument,
|
||||
});
|
||||
try builder.appendInstruction(unit, context, trailing_zeroes);
|
||||
|
||||
return V{
|
||||
.type = argument.type,
|
||||
.value = .{
|
||||
.runtime = trailing_zeroes,
|
||||
},
|
||||
};
|
||||
},
|
||||
.leading_zeroes => {
|
||||
assert(argument_node_list.len == 1);
|
||||
const argument = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, argument_node_list[0], .right);
|
||||
const leading_zeroes = try unit.instructions.append(context.my_allocator, .{
|
||||
.leading_zeroes = argument,
|
||||
});
|
||||
try builder.appendInstruction(unit, context, leading_zeroes);
|
||||
|
||||
return V{
|
||||
.type = argument.type,
|
||||
.value = .{
|
||||
.runtime = leading_zeroes,
|
||||
},
|
||||
};
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
}
|
||||
@ -8667,6 +8701,7 @@ pub const Builder = struct {
|
||||
const field_node = unit.getNode(field_node_index);
|
||||
const identifier = switch (unit.getTokenId(field_node.token)) {
|
||||
.identifier => unit.getExpectedTokenBytes(field_node.token, .identifier),
|
||||
.string_literal => try unit.fixupStringLiteral(context, field_node.token),
|
||||
.discard => try std.mem.concat(context.allocator, u8, &.{ "_", &.{'0' + b: {
|
||||
const ch = '0' + ignore_field_count;
|
||||
ignore_field_count += 1;
|
||||
@ -15060,8 +15095,11 @@ pub const Builder = struct {
|
||||
fn resolveFieldAccess(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, node_index: Node.Index, side: Side, new_parameters: []const V.Comptime) !V {
|
||||
const node = unit.getNode(node_index);
|
||||
const right_node = unit.getNode(node.right);
|
||||
assert(right_node.id == .identifier);
|
||||
const identifier = unit.getExpectedTokenBytes(right_node.token, .identifier);
|
||||
const identifier = switch (right_node.id) {
|
||||
.identifier => unit.getExpectedTokenBytes(right_node.token, .identifier),
|
||||
.string_literal => try unit.fixupStringLiteral(context, right_node.token),
|
||||
else => |t| @panic(@tagName(t)),
|
||||
};
|
||||
const identifier_hash = try unit.processIdentifier(context, identifier);
|
||||
|
||||
const left_node_index = node.left;
|
||||
|
@ -3110,6 +3110,15 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
||||
const intrinsic_call = try llvm.callIntrinsic("llvm.sadd.with.overflow", ¶meter_types, &arguments);
|
||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, intrinsic_call);
|
||||
},
|
||||
.trailing_zeroes => |v| {
|
||||
const intrinsic_type = try llvm.getType(unit, context, v.type);
|
||||
const parameter_types = [_]*LLVM.Type{intrinsic_type};
|
||||
const value = try llvm.emitRightValue(unit, context, v);
|
||||
const is_poison = llvm.context.getConstantInt(1, 0, false) orelse unreachable;
|
||||
const arguments = [_]*LLVM.Value{ value, is_poison.toValue() };
|
||||
const intrinsic_call = try llvm.callIntrinsic("llvm.cttz", ¶meter_types, &arguments);
|
||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, intrinsic_call);
|
||||
},
|
||||
.@"switch" => |switch_expression| {
|
||||
const condition = try llvm.emitRightValue(unit, context, switch_expression.condition);
|
||||
const else_block: ?*LLVM.Value.BasicBlock = if (switch_expression.else_block != .null) b: {
|
||||
|
@ -1208,6 +1208,7 @@ const Analyzer = struct {
|
||||
.discard,
|
||||
.fixed_keyword_test,
|
||||
.fixed_keyword_break,
|
||||
.fixed_keyword_while,
|
||||
=> break,
|
||||
.operator_compare_equal => .compare_equal,
|
||||
.operator_compare_not_equal => .compare_not_equal,
|
||||
@ -2276,6 +2277,24 @@ const Analyzer = struct {
|
||||
.right = Node.Index.null,
|
||||
}),
|
||||
}),
|
||||
.string_literal => try analyzer.addNode(.{
|
||||
.id = .field_access,
|
||||
.token = blk: {
|
||||
analyzer.consumeToken();
|
||||
break :blk token;
|
||||
},
|
||||
.left = left,
|
||||
.right = try analyzer.addNode(.{
|
||||
.id = .string_literal,
|
||||
.token = blk: {
|
||||
const t = analyzer.token_i;
|
||||
analyzer.consumeToken();
|
||||
break :blk t;
|
||||
},
|
||||
.left = Node.Index.null,
|
||||
.right = Node.Index.null,
|
||||
}),
|
||||
}),
|
||||
.operator_ampersand => try analyzer.addNode(.{
|
||||
.id = .address_of,
|
||||
.token = blk: {
|
||||
|
@ -53,10 +53,12 @@ fn runStandalone(allocator: Allocator, args: struct {
|
||||
for (test_names) |test_name| {
|
||||
std.debug.print("{s}... ", .{test_name});
|
||||
const source_file_path = try std.mem.concat(allocator, u8, &.{ args.directory_path, "/", test_name, "/main.nat" });
|
||||
const argv: []const []const u8 = &.{ args.compiler_path, if (args.is_test) "test" else "exe", "-main_source_file", source_file_path };
|
||||
// if (std.mem.eql(u8, args.compiler_path, "nat/compiler_lightly_optimize_for_speed")) @breakpoint();
|
||||
const compile_run = try std.ChildProcess.run(.{
|
||||
.allocator = allocator,
|
||||
// TODO: delete -main_source_file?
|
||||
.argv = &.{ args.compiler_path, if (args.is_test) "test" else "exe", "-main_source_file", source_file_path },
|
||||
.argv = argv,
|
||||
.max_output_bytes = std.math.maxInt(u64),
|
||||
});
|
||||
ran_compilation_count += 1;
|
||||
@ -85,7 +87,6 @@ fn runStandalone(allocator: Allocator, args: struct {
|
||||
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name });
|
||||
const test_run = try std.ChildProcess.run(.{
|
||||
.allocator = allocator,
|
||||
// TODO: delete -main_source_file?
|
||||
.argv = &.{test_path},
|
||||
.max_output_bytes = std.math.maxInt(u64),
|
||||
});
|
||||
|
18
src/main.nat
18
src/main.nat
@ -20,15 +20,31 @@ const lex = fn (arena: &Arena, bytes: []const u8) *!void {
|
||||
// var i = index;
|
||||
// const top = index + max_initial_keyword_len + 1;
|
||||
// var space: u32 = 0;
|
||||
|
||||
// while (i < top) {
|
||||
// const is_space = bytes[i] == ' ';
|
||||
// space |= #cast(
|
||||
// const is_space_int: u32 = #cast(is_space);
|
||||
// const space_mask = 0 -% is_space_int;
|
||||
// space |= (1 << i) & space_mask;
|
||||
// i += 1;
|
||||
// }
|
||||
|
||||
// if (space == 0) {
|
||||
// unreachable;
|
||||
// }
|
||||
|
||||
// const word_byte_count = #trailing_zeroes(space);
|
||||
// const word = bytes[index..][0..word_byte_count];
|
||||
|
||||
// if (byte_equal(word, #name(FileStartToken."comptime"))) {
|
||||
// } else if (byte_equal(word, #name(FileStartToken."test"))) {
|
||||
// } else if (byte_equal(word, #name(FileStartToken."const"))) {
|
||||
// } else if (byte_equal(word, #name(FileStartToken."var"))) {
|
||||
// } else {
|
||||
// print("Wrong file declaration start\n");
|
||||
// }
|
||||
|
||||
// break;
|
||||
//}
|
||||
}
|
||||
|
||||
|
8
test/standalone/trailing_zeroes/main.nat
Normal file
8
test/standalone/trailing_zeroes/main.nat
Normal file
@ -0,0 +1,8 @@
|
||||
const std = #import("std");
|
||||
const expect = std.testing.expect;
|
||||
const main = fn () *!void {
|
||||
var a: u32 = 7;
|
||||
try expect(#trailing_zeroes(a) == 0);
|
||||
a = 8;
|
||||
try expect(#trailing_zeroes(a) == 3);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user