Hello world string
This commit is contained in:
parent
200cc7b76e
commit
610faec907
@ -670,23 +670,34 @@ const Parser = struct{
|
||||
|
||||
parser.skip_space(src);
|
||||
|
||||
const element_count = parser.parse_constant_expression(thread, file, null);
|
||||
switch (element_count.sema.id) {
|
||||
.constant_int => {
|
||||
const constant_int = element_count.get_payload(.constant_int);
|
||||
parser.skip_space(src);
|
||||
parser.expect_character(src, ']');
|
||||
parser.skip_space(src);
|
||||
if (src[parser.i] == ']') {
|
||||
// Slice
|
||||
parser.i += 1;
|
||||
|
||||
const element_type = parser.parse_type_expression(thread, file, current_scope);
|
||||
const array_type = get_array_type(thread, .{
|
||||
.element_type = element_type,
|
||||
.element_count = constant_int.n,
|
||||
});
|
||||
return array_type;
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
const element_type = parser.parse_type_expression(thread, file, current_scope);
|
||||
const slice_type = get_slice_type(thread, element_type);
|
||||
return slice_type;
|
||||
} else {
|
||||
// Array
|
||||
const element_count = parser.parse_constant_expression(thread, file, null);
|
||||
switch (element_count.sema.id) {
|
||||
.constant_int => {
|
||||
const constant_int = element_count.get_payload(.constant_int);
|
||||
parser.skip_space(src);
|
||||
parser.expect_character(src, ']');
|
||||
parser.skip_space(src);
|
||||
|
||||
const element_type = parser.parse_type_expression(thread, file, current_scope);
|
||||
const array_type = get_array_type(thread, .{
|
||||
.element_type = element_type,
|
||||
.element_count = constant_int.n,
|
||||
});
|
||||
return array_type;
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const identifier = parser.parse_identifier(thread, src);
|
||||
@ -858,6 +869,13 @@ const Parser = struct{
|
||||
};
|
||||
}
|
||||
|
||||
fn get_escape_character(ch: u8) u8 {
|
||||
return switch (ch) {
|
||||
'n' => '\n',
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
fn parse_single_expression(parser: *Parser, analyzer: *Analyzer, thread: *Thread, file: *File, maybe_type: ?*Type, side: Side) *Value {
|
||||
const src = file.source_code;
|
||||
const Unary = enum{
|
||||
@ -878,10 +896,7 @@ const Parser = struct{
|
||||
parser.i += 1;
|
||||
parser.expect_character(src, '\'');
|
||||
const ch = switch (is_escape) {
|
||||
true => switch (potential_ch) {
|
||||
'n' => '\n',
|
||||
else => unreachable,
|
||||
},
|
||||
true => get_escape_character(potential_ch),
|
||||
false => potential_ch,
|
||||
};
|
||||
const character_literal = create_constant_int(thread, .{
|
||||
@ -890,6 +905,148 @@ const Parser = struct{
|
||||
});
|
||||
return &character_literal.value;
|
||||
},
|
||||
'"' => {
|
||||
// String literal
|
||||
parser.i += 1;
|
||||
|
||||
const string_start = parser.i;
|
||||
var hash: u64 = library.fnv_offset;
|
||||
var escape_character_count: u64 = 0;
|
||||
while (parser.i < src.len) {
|
||||
if (src[parser.i] == '"') {
|
||||
break;
|
||||
}
|
||||
|
||||
const is_escape = src[parser.i] == '\\';
|
||||
parser.i += @intFromBool(is_escape);
|
||||
escape_character_count += @intFromBool(is_escape);
|
||||
const potential_ch = src[parser.i];
|
||||
parser.i += 1;
|
||||
if (is_escape) {
|
||||
hash ^= '\\';
|
||||
hash *%= library.fnv_prime;
|
||||
}
|
||||
hash ^= potential_ch;
|
||||
hash *%= library.fnv_prime;
|
||||
}
|
||||
const string_end = parser.i;
|
||||
parser.i += 1;
|
||||
|
||||
const StringKind = enum{
|
||||
array,
|
||||
global,
|
||||
};
|
||||
|
||||
const kind: StringKind = if (maybe_type) |ty| switch (ty.sema.id) {
|
||||
// TODO: typecheck
|
||||
.slice => .global,
|
||||
else => |t| @panic(@tagName(t)),
|
||||
} else .array;
|
||||
|
||||
switch (kind) {
|
||||
.global => {
|
||||
const truncated_hash: u32 = @truncate(hash);
|
||||
const string = if (thread.global_strings.get_pointer(truncated_hash)) |string| string
|
||||
else blk: {
|
||||
const expected_length: u32 = @intCast((string_end + 1) - (string_start + escape_character_count));
|
||||
const string_content = thread.string_buffer.add_slice(expected_length);
|
||||
var source_index: usize = string_start;
|
||||
var destination_index: usize = 0;
|
||||
|
||||
while (source_index < string_end) {
|
||||
const is_escape = src[source_index] == '\\';
|
||||
source_index += @intFromBool(is_escape);
|
||||
const ch = switch (is_escape) {
|
||||
true => get_escape_character(src[source_index]),
|
||||
false => src[source_index],
|
||||
};
|
||||
string_content[destination_index] = ch;
|
||||
|
||||
destination_index += 1;
|
||||
source_index += 1;
|
||||
}
|
||||
|
||||
string_content[destination_index] = 0;
|
||||
|
||||
const string = thread.global_strings.put_no_clobber(truncated_hash, .{
|
||||
.value = .{
|
||||
.sema = .{
|
||||
.thread = thread.get_index(),
|
||||
.resolved = true,
|
||||
.id = .global_string_literal,
|
||||
},
|
||||
},
|
||||
.content = string_content,
|
||||
.source_file_hash = truncated_hash,
|
||||
.emit = false,
|
||||
});
|
||||
break :blk string;
|
||||
};
|
||||
|
||||
var values = PinnedArray(*Value){};
|
||||
_ = values.append(&string.value);
|
||||
_ = values.append(&create_constant_int(thread, .{
|
||||
.n = string.content.len,
|
||||
.type = &thread.integers[63].type,
|
||||
}).value);
|
||||
|
||||
const constant_struct = thread.constant_structs.append(.{
|
||||
.value = .{
|
||||
.sema = .{
|
||||
.thread = thread.get_index(),
|
||||
.resolved = true,
|
||||
.id = .constant_struct,
|
||||
},
|
||||
},
|
||||
.type = maybe_type orelse unreachable,
|
||||
.values = values.const_slice(),
|
||||
});
|
||||
|
||||
return &constant_struct.value;
|
||||
},
|
||||
.array => {
|
||||
const truncated_hash: u32 = @truncate(hash);
|
||||
if (thread.constant_strings.get_pointer(truncated_hash)) |string| {
|
||||
return &string.value;
|
||||
} else {
|
||||
const expected_length: u32 = @intCast((string_end + 1) - (string_start + escape_character_count));
|
||||
const string_content = thread.string_buffer.add_slice(expected_length);
|
||||
var source_index: usize = string_start;
|
||||
var destination_index: usize = 0;
|
||||
|
||||
while (source_index < string_end) {
|
||||
const is_escape = src[source_index] == '\\';
|
||||
source_index += @intFromBool(is_escape);
|
||||
const ch = switch (is_escape) {
|
||||
true => get_escape_character(src[source_index]),
|
||||
false => src[source_index],
|
||||
};
|
||||
string_content[destination_index] = ch;
|
||||
|
||||
destination_index += 1;
|
||||
source_index += 1;
|
||||
}
|
||||
|
||||
string_content[destination_index] = 0;
|
||||
|
||||
const string = thread.constant_strings.put_no_clobber(truncated_hash, .{
|
||||
.value = .{
|
||||
.sema = .{
|
||||
.thread = thread.get_index(),
|
||||
.resolved = true,
|
||||
.id = .constant_string_literal,
|
||||
},
|
||||
},
|
||||
.content = string_content,
|
||||
.source_file_hash = truncated_hash,
|
||||
.emit = false,
|
||||
});
|
||||
return &string.value;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
'-' => block: {
|
||||
parser.i += 1;
|
||||
break :block .negation;
|
||||
@ -1960,6 +2117,46 @@ const Parser = struct{
|
||||
fail_term("Array access must only be 'length', got", array_field_access_id);
|
||||
}
|
||||
},
|
||||
.slice => {
|
||||
const slice_field_access_id = parser.parse_raw_identifier(src);
|
||||
if (byte_equal(slice_field_access_id, "pointer")) {
|
||||
const slice_type = ty.get_payload(.slice);
|
||||
const load = emit_load(analyzer, thread, .{
|
||||
.value = value,
|
||||
.type = get_typed_pointer(thread, .{
|
||||
.pointee = slice_type.element_type,
|
||||
}),
|
||||
.scope = analyzer.current_scope,
|
||||
.line = 0,
|
||||
.column = 0,
|
||||
});
|
||||
return &load.instruction.value;
|
||||
} else if (byte_equal(slice_field_access_id, "length")) {
|
||||
const gep = emit_gep(thread, analyzer, .{
|
||||
.line = 0,
|
||||
.column = 0,
|
||||
.scope = analyzer.current_scope,
|
||||
.pointer = value,
|
||||
.index = &create_constant_int(thread, .{
|
||||
.n = 1,
|
||||
.type = &thread.integers[31].type,
|
||||
}).value,
|
||||
.aggregate_type = ty,
|
||||
.type = &thread.integers[63].type,
|
||||
.is_struct = true,
|
||||
});
|
||||
const load = emit_load(analyzer, thread, .{
|
||||
.value = &gep.instruction.value,
|
||||
.type = &thread.integers[63].type,
|
||||
.scope = analyzer.current_scope,
|
||||
.line = 0,
|
||||
.column = 0,
|
||||
});
|
||||
return &load.instruction.value;
|
||||
} else {
|
||||
fail_term("Slice access must be either 'pointer' or 'length', got", slice_field_access_id);
|
||||
}
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
}
|
||||
@ -2559,6 +2756,8 @@ const Value = struct {
|
||||
global_symbol,
|
||||
lazy_expression,
|
||||
local_lazy_expression,
|
||||
constant_string_literal,
|
||||
global_string_literal,
|
||||
undefined,
|
||||
};
|
||||
|
||||
@ -2573,6 +2772,8 @@ const Value = struct {
|
||||
.instruction = Instruction,
|
||||
.lazy_expression = LazyExpression,
|
||||
.local_lazy_expression = LocalLazyExpression,
|
||||
.constant_string_literal = String,
|
||||
.global_string_literal = String,
|
||||
.undefined = Undefined,
|
||||
});
|
||||
|
||||
@ -2656,6 +2857,25 @@ const Value = struct {
|
||||
const constant_struct = value.get_payload(.constant_struct);
|
||||
return constant_struct.type;
|
||||
},
|
||||
.constant_string_literal => {
|
||||
const string_literal = value.get_payload(.constant_string_literal);
|
||||
const thread = &instance.threads[string_literal.value.sema.thread];
|
||||
const array_type = get_array_type(thread, .{
|
||||
.element_type = &thread.integers[8 - 1].type,
|
||||
.element_count = string_literal.content.len,
|
||||
});
|
||||
return array_type;
|
||||
},
|
||||
.global_string_literal => {
|
||||
unreachable;
|
||||
// const string_literal = value.get_payload(.string_literal);
|
||||
// const thread = &instance.threads[string_literal.value.sema.thread];
|
||||
// const array_type = get_array_type(thread, .{
|
||||
// .element_type = &thread.integers[8 - 1].type,
|
||||
// .element_count = string_literal.content.len,
|
||||
// });
|
||||
// return array_type;
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
};
|
||||
}
|
||||
@ -2687,6 +2907,7 @@ const Type = struct {
|
||||
@"struct",
|
||||
bitfield,
|
||||
anonymous_struct,
|
||||
slice,
|
||||
};
|
||||
|
||||
const Integer = struct {
|
||||
@ -2751,6 +2972,11 @@ const Type = struct {
|
||||
};
|
||||
};
|
||||
|
||||
const Slice = struct{
|
||||
type: Type,
|
||||
element_type: *Type,
|
||||
};
|
||||
|
||||
const id_to_type_map = std.EnumArray(Id, type).init(.{
|
||||
.unresolved = void,
|
||||
.void = void,
|
||||
@ -2763,6 +2989,7 @@ const Type = struct {
|
||||
.bitfield = Type.Bitfield,
|
||||
.typed_pointer = TypedPointer,
|
||||
.anonymous_struct = AnonymousStruct,
|
||||
.slice = Slice,
|
||||
});
|
||||
|
||||
fn get_payload(ty: *Type, comptime id: Id) *id_to_type_map.get(id) {
|
||||
@ -2850,7 +3077,7 @@ const Type = struct {
|
||||
result.llvm = null;
|
||||
result.sema.thread = args.destination_thread.get_index();
|
||||
|
||||
args.destination_thread.cloned_types.put_no_clobber(ty, result);
|
||||
_ = args.destination_thread.cloned_types.put_no_clobber(ty, result);
|
||||
|
||||
break :blk result;
|
||||
};
|
||||
@ -2873,7 +3100,7 @@ const Type = struct {
|
||||
.bitfield,
|
||||
=>
|
||||
false,
|
||||
.@"struct", .anonymous_struct => true,
|
||||
.@"struct", .anonymous_struct, .slice => true,
|
||||
};
|
||||
}
|
||||
|
||||
@ -3555,6 +3782,16 @@ const DebugArgument = struct{
|
||||
argument: *ArgumentSymbol,
|
||||
};
|
||||
|
||||
const String = struct{
|
||||
value: Value,
|
||||
content: []const u8,
|
||||
// This hash amounts to the source file bytes, not the actual string bytes
|
||||
// in the final object
|
||||
source_file_hash: u32,
|
||||
null_terminate: bool = true,
|
||||
emit: bool,
|
||||
};
|
||||
|
||||
const Thread = struct{
|
||||
arena: *Arena = undefined,
|
||||
functions: PinnedArray(Function) = .{},
|
||||
@ -3599,6 +3836,7 @@ const Thread = struct{
|
||||
array_type_map: PinnedHashMap(Type.Array.Descriptor, *Type) = .{},
|
||||
typed_pointer_type_map: PinnedHashMap(Type.TypedPointer.Descriptor, *Type) = .{},
|
||||
array_types: PinnedArray(Type.Array) = .{},
|
||||
slice_types: PinnedHashMap(*Type, Type.Slice) = .{},
|
||||
typed_pointer_types: PinnedArray(Type.TypedPointer) = .{},
|
||||
structs: PinnedArray(Type.Struct) = .{},
|
||||
anonymous_structs: PinnedArray(Type.AnonymousStruct) = .{},
|
||||
@ -3606,6 +3844,9 @@ const Thread = struct{
|
||||
fields: PinnedArray(Type.AggregateField) = .{},
|
||||
bitfields: PinnedArray(Type.Bitfield) = .{},
|
||||
cloned_types: PinnedHashMap(*Type, *Type) = .{},
|
||||
constant_strings: PinnedHashMap(u32, String) = .{},
|
||||
global_strings: PinnedHashMap(u32, String) = .{},
|
||||
string_buffer: PinnedArray(u8) = .{},
|
||||
analyzed_file_count: u32 = 0,
|
||||
assigned_file_count: u32 = 0,
|
||||
llvm: struct {
|
||||
@ -3618,6 +3859,8 @@ const Thread = struct{
|
||||
fixed_intrinsic_functions: std.EnumArray(LLVMFixedIntrinsic, *LLVM.Value.Constant.Function),
|
||||
intrinsic_id_map: PinnedHashMap([]const u8, LLVM.Value.IntrinsicID) = .{},
|
||||
intrinsic_function_map: PinnedHashMap(LLVMIntrinsic.Parameters, *LLVM.Value.Constant.Function) = .{},
|
||||
pointer: *LLVM.Type,
|
||||
slice: *LLVM.Type,
|
||||
} = undefined,
|
||||
integers: [128]Type.Integer = blk: {
|
||||
var integers: [128]Type.Integer = undefined;
|
||||
@ -4683,7 +4926,7 @@ fn intern_identifier(pool: *PinnedHashMap(u32, []const u8), identifier: []const
|
||||
const start_index = @intFromBool(identifier[0] == '"');
|
||||
const end_index = identifier.len - start_index;
|
||||
const hash = hash_bytes(identifier[start_index..end_index]);
|
||||
pool.put(hash, identifier);
|
||||
_ = pool.put(hash, identifier);
|
||||
|
||||
return hash;
|
||||
}
|
||||
@ -4993,6 +5236,9 @@ fn worker_thread(thread_index: u32, cpu_count: *u32) void {
|
||||
module.setTargetMachineDataLayout(target_machine);
|
||||
module.setTargetTriple(target_triple.ptr, target_triple.len);
|
||||
|
||||
const pointer_type = context.getPointerType(address_space);
|
||||
const usize_type = context.getIntegerType(64);
|
||||
const slice_types: []const *LLVM.Type = &.{pointer_type.toType(), usize_type.toType()};
|
||||
|
||||
thread.llvm = .{
|
||||
.context = context,
|
||||
@ -5009,8 +5255,14 @@ fn worker_thread(thread_index: u32, cpu_count: *u32) void {
|
||||
.types = &.{},
|
||||
}),
|
||||
}),
|
||||
.slice = context.getStructType(slice_types.ptr, slice_types.len, false).toType(),
|
||||
.pointer = pointer_type.toType(),
|
||||
};
|
||||
|
||||
for (thread.global_strings.values()) |*string| {
|
||||
string.value.llvm = builder.createGlobalString(string.content.ptr, string.content.len, string.content.ptr, string.content.len, address_space, module).toValue();
|
||||
}
|
||||
|
||||
for (thread.external_functions.slice()) |*nat_function| {
|
||||
llvm_emit_function_declaration(thread, nat_function);
|
||||
}
|
||||
@ -6264,6 +6516,10 @@ fn llvm_get_value(thread: *Thread, value: *Value) *LLVM.Value {
|
||||
const poison = ty.getPoison();
|
||||
break :b poison.toValue();
|
||||
},
|
||||
.constant_string_literal => b: {
|
||||
const string_literal = value.get_payload(.constant_string_literal);
|
||||
break :b thread.llvm.context.getConstantString(string_literal.content.ptr, string_literal.content.len, false).toValue();
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
};
|
||||
|
||||
@ -6482,6 +6738,55 @@ fn llvm_get_debug_type(thread: *Thread, builder: *LLVM.DebugInfo.Builder, ty: *T
|
||||
builder.replaceCompositeTypes(struct_type, member_types.pointer, member_types.length);
|
||||
break :block struct_type.toType();
|
||||
},
|
||||
.slice => block: {
|
||||
const nat_slice_type = ty.get_payload(.slice);
|
||||
const file_struct = llvm_get_file(thread, 0);
|
||||
const element_type = llvm_get_debug_type(thread, builder, nat_slice_type.element_type);
|
||||
const usize_type = llvm_get_debug_type(thread, builder, &thread.integers[63].type);
|
||||
const flags = LLVM.DebugInfo.Node.Flags{
|
||||
.visibility = .none,
|
||||
.forward_declaration = false,
|
||||
.apple_block = false,
|
||||
.block_by_ref_struct = false,
|
||||
.virtual = false,
|
||||
.artificial = false,
|
||||
.explicit = false,
|
||||
.prototyped = false,
|
||||
.objective_c_class_complete = false,
|
||||
.object_pointer = false,
|
||||
.vector = false,
|
||||
.static_member = false,
|
||||
.lvalue_reference = false,
|
||||
.rvalue_reference = false,
|
||||
.reserved = false,
|
||||
.inheritance = .none,
|
||||
.introduced_virtual = false,
|
||||
.bit_field = false,
|
||||
.no_return = false,
|
||||
.type_pass_by_value = false,
|
||||
.type_pass_by_reference = false,
|
||||
.enum_class = false,
|
||||
.thunk = false,
|
||||
.non_trivial = false,
|
||||
.big_endian = false,
|
||||
.little_endian = false,
|
||||
.all_calls_described = false,
|
||||
};
|
||||
const file = file_struct.file;
|
||||
const name = "[]";
|
||||
const line = 0;
|
||||
|
||||
const bitsize = nat_slice_type.type.size * 8;
|
||||
const alignment = nat_slice_type.type.alignment;
|
||||
|
||||
const pointer_name = "pointer";
|
||||
const length_name = "length";
|
||||
const members = [_]*LLVM.DebugInfo.Type{builder.createMemberType(null, pointer_name, pointer_name.len, null, line, 64, 8, 0, flags, element_type).toType(), builder.createMemberType(null, length_name, length_name.len, null, line, 64, 8, 0, flags, usize_type).toType()};
|
||||
|
||||
const struct_type = builder.createStructType(file.toScope(), name.ptr, name.len, file, line, bitsize, alignment, flags, null, &members, members.len, null);
|
||||
|
||||
break :block struct_type.toType();
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
};
|
||||
|
||||
@ -6512,10 +6817,8 @@ fn llvm_get_type(thread: *Thread, ty: *Type) *LLVM.Type {
|
||||
const array_type = LLVM.Type.Array.get(element_type, array_ty.descriptor.element_count);
|
||||
break :b array_type.toType();
|
||||
},
|
||||
.opaque_pointer, .typed_pointer => b: {
|
||||
const pointer_type = thread.llvm.context.getPointerType(address_space);
|
||||
break :b pointer_type.toType();
|
||||
},
|
||||
.opaque_pointer, .typed_pointer => thread.llvm.pointer,
|
||||
.slice => thread.llvm.slice,
|
||||
.function => b: {
|
||||
const nat_function_type = ty.get_payload(.function);
|
||||
const return_type = llvm_get_type(thread, nat_function_type.abi.abi_return_type);
|
||||
@ -6593,13 +6896,11 @@ fn llvm_get_file(thread: *Thread, file_index: u32) *LLVMFile {
|
||||
const sdk = "";
|
||||
const compile_unit = builder.createCompileUnit(LLVM.DebugInfo.Language.c11, llvm_file, producer, producer.len, is_optimized, flags, flags.len, runtime_version, splitname, splitname.len, debug_info_kind, DWOId, split_debug_inlining, debug_info_for_profiling, name_table_kind, ranges_base_address, sysroot, sysroot.len, sdk, sdk.len);
|
||||
|
||||
thread.debug_info_file_map.put_no_clobber(file_index, .{
|
||||
return thread.debug_info_file_map.put_no_clobber(file_index, .{
|
||||
.file = llvm_file,
|
||||
.compile_unit = compile_unit,
|
||||
.builder = builder,
|
||||
});
|
||||
|
||||
return thread.debug_info_file_map.get_pointer(file_index).?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7902,7 +8203,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
||||
.initial_value = global_initial_value,
|
||||
});
|
||||
|
||||
file.scope.scope.declarations.put_no_clobber(global_name, &global_variable.global_symbol.global_declaration.declaration);
|
||||
_ = file.scope.scope.declarations.put_no_clobber(global_name, &global_variable.global_symbol.global_declaration.declaration);
|
||||
},
|
||||
'b' => {
|
||||
const identifier = parser.parse_raw_identifier(src);
|
||||
@ -7947,7 +8248,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
||||
.fields = &.{},
|
||||
.backing_type = backing_type,
|
||||
});
|
||||
file.scope.scope.declarations.put_no_clobber(bitfield_name, &bitfield_type.declaration);
|
||||
_ = file.scope.scope.declarations.put_no_clobber(bitfield_name, &bitfield_type.declaration);
|
||||
|
||||
parser.skip_space(src);
|
||||
|
||||
@ -8692,7 +8993,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
||||
},
|
||||
.entry_block = entry_block,
|
||||
};
|
||||
file.scope.scope.declarations.put_no_clobber(function.declaration.global_symbol.global_declaration.declaration.name, &function.declaration.global_symbol.global_declaration.declaration);
|
||||
_ = file.scope.scope.declarations.put_no_clobber(function.declaration.global_symbol.global_declaration.declaration.name, &function.declaration.global_symbol.global_declaration.declaration);
|
||||
var analyzer = Analyzer{
|
||||
.current_function = function,
|
||||
.current_basic_block = entry_block,
|
||||
@ -8905,7 +9206,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
||||
};
|
||||
|
||||
if (argument.name != 0) {
|
||||
analyzer.current_scope.declarations.put_no_clobber(argument.name, &argument_symbol.argument_declaration.declaration);
|
||||
_ = analyzer.current_scope.declarations.put_no_clobber(argument.name, &argument_symbol.argument_declaration.declaration);
|
||||
if (thread.generate_debug_information) {
|
||||
emit_debug_argument(&analyzer, thread, .{
|
||||
.argument_symbol = argument_symbol,
|
||||
@ -8957,7 +9258,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
||||
function_declaration_data.global_symbol.id = .function_declaration;
|
||||
|
||||
const function_declaration = thread.external_functions.append(function_declaration_data);
|
||||
file.scope.scope.declarations.put_no_clobber(function_declaration.global_symbol.global_declaration.declaration.name, &function_declaration.global_symbol.global_declaration.declaration);
|
||||
_ = file.scope.scope.declarations.put_no_clobber(function_declaration.global_symbol.global_declaration.declaration.name, &function_declaration.global_symbol.global_declaration.declaration);
|
||||
},
|
||||
else => fail_message("Unexpected character to close function declaration"),
|
||||
}
|
||||
@ -9013,8 +9314,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
||||
});
|
||||
_ = import.files.append(file);
|
||||
_ = file.imports.append(import);
|
||||
file.scope.scope.declarations.put_no_clobber(filename_without_extension_hash, &import.global_declaration.declaration);
|
||||
const global_declaration_reference: **GlobalDeclaration = @ptrCast(file.scope.scope.declarations.get_pointer(filename_without_extension_hash) orelse unreachable);
|
||||
const global_declaration_reference: **GlobalDeclaration = @ptrCast(file.scope.scope.declarations.put_no_clobber(filename_without_extension_hash, &import.global_declaration.declaration));
|
||||
const import_values = file.values_per_import.append(.{});
|
||||
const lazy_expression = thread.lazy_expressions.append(LazyExpression.init(global_declaration_reference, thread));
|
||||
_ = import_values.append(&lazy_expression.value);
|
||||
@ -9056,7 +9356,7 @@ pub fn analyze_file(thread: *Thread, file_index: u32) void {
|
||||
},
|
||||
.fields = &.{},
|
||||
});
|
||||
file.scope.scope.declarations.put_no_clobber(struct_name, &struct_type.declaration);
|
||||
_ = file.scope.scope.declarations.put_no_clobber(struct_name, &struct_type.declaration);
|
||||
|
||||
parser.skip_space(src);
|
||||
|
||||
@ -9404,7 +9704,7 @@ fn emit_local_symbol(analyzer: *Analyzer, thread: *Thread, args: struct{
|
||||
_ = analyzer.current_function.stack_slots.append(local_symbol);
|
||||
|
||||
if (args.name != 0) {
|
||||
analyzer.current_scope.declarations.put_no_clobber(args.name, &local_symbol.local_declaration.declaration);
|
||||
_ = analyzer.current_scope.declarations.put_no_clobber(args.name, &local_symbol.local_declaration.declaration);
|
||||
if (thread.generate_debug_information) {
|
||||
emit_debug_local(analyzer, thread, .{
|
||||
.local_symbol = local_symbol,
|
||||
@ -9691,7 +9991,7 @@ fn get_typed_pointer(thread: *Thread, descriptor: Type.TypedPointer.Descriptor)
|
||||
.descriptor = descriptor,
|
||||
});
|
||||
|
||||
thread.typed_pointer_type_map.put_no_clobber(descriptor, &typed_pointer_type.type);
|
||||
_ = thread.typed_pointer_type_map.put_no_clobber(descriptor, &typed_pointer_type.type);
|
||||
return &typed_pointer_type.type;
|
||||
}
|
||||
}
|
||||
@ -9736,12 +10036,30 @@ fn get_anonymous_two_field_struct(thread: *Thread, types: [2]*Type) *Type {
|
||||
.fields = fields,
|
||||
};
|
||||
|
||||
thread.two_struct_map.put_no_clobber(types, &anonymous_struct.type);
|
||||
_ = thread.two_struct_map.put_no_clobber(types, &anonymous_struct.type);
|
||||
|
||||
return &anonymous_struct.type;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_slice_type(thread: *Thread, ty: *Type) *Type {
|
||||
if (thread.slice_types.get_pointer(ty)) |slice_type| return &slice_type.type else {
|
||||
const slice_type = thread.slice_types.put_no_clobber(ty, .{
|
||||
.element_type = ty,
|
||||
.type = .{
|
||||
.sema = .{
|
||||
.thread = thread.get_index(),
|
||||
.resolved = true,
|
||||
.id = .slice,
|
||||
},
|
||||
.size = 2 * 8,
|
||||
.bit_size = 2 * 8 * 8,
|
||||
.alignment = 8,
|
||||
},
|
||||
});
|
||||
return &slice_type.type;
|
||||
}
|
||||
}
|
||||
fn get_array_type(thread: *Thread, descriptor: Type.Array.Descriptor) *Type {
|
||||
assert(descriptor.element_type.sema.resolved);
|
||||
if (thread.array_type_map.get(descriptor)) |result| return result else {
|
||||
@ -9759,7 +10077,7 @@ fn get_array_type(thread: *Thread, descriptor: Type.Array.Descriptor) *Type {
|
||||
.descriptor = descriptor,
|
||||
});
|
||||
|
||||
thread.array_type_map.put_no_clobber(descriptor, &array_type.type);
|
||||
_ = thread.array_type_map.put_no_clobber(descriptor, &array_type.type);
|
||||
return &array_type.type;
|
||||
}
|
||||
}
|
||||
@ -9817,7 +10135,7 @@ pub const LLVM = struct {
|
||||
const create = bindings.NativityLLVMCreateContext;
|
||||
const createBasicBlock = bindings.NativityLLVMCreateBasicBlock;
|
||||
const getConstantInt = bindings.NativityLLVMContextGetConstantInt;
|
||||
const getConstString = bindings.NativityLLVMContextGetConstString;
|
||||
const getConstantString = bindings.NativityLLVMContextGetConstantString;
|
||||
const getVoidType = bindings.NativityLLVMGetVoidType;
|
||||
const getIntegerType = bindings.NativityLLVMGetIntegerType;
|
||||
const getPointerType = bindings.NativityLLVMGetPointerType;
|
||||
|
@ -258,11 +258,24 @@ pub fn PinnedArrayAdvanced(comptime T: type, comptime MaybeIndex: ?type, comptim
|
||||
return ptr;
|
||||
}
|
||||
|
||||
pub fn add_many_with_capacity(array: *Array, count: u32) []T {
|
||||
const index = array.length;
|
||||
assert((index + count) * @sizeOf(T) < pinned_array_max_size);
|
||||
array.length += count;
|
||||
const ptr = array.pointer[index..][0..count];
|
||||
return ptr;
|
||||
}
|
||||
|
||||
pub fn add_one(array: *Array) *T{
|
||||
array.ensure_capacity(1);
|
||||
return array.add_one_with_capacity();
|
||||
}
|
||||
|
||||
pub fn add_slice(array: *Array, count: u32) []T {
|
||||
array.ensure_capacity(count);
|
||||
return array.add_many_with_capacity(count);
|
||||
}
|
||||
|
||||
pub fn append_with_capacity(array: *Array, item: T) *T {
|
||||
const ptr = array.add_one_with_capacity();
|
||||
ptr.* = item;
|
||||
@ -359,9 +372,9 @@ fn JointEnum(comptime enums: []const type, comptime backing_type: ?type) type {
|
||||
});
|
||||
}
|
||||
|
||||
pub const fnv_offset = 14695981039346656037;
|
||||
pub const fnv_prime = 1099511628211;
|
||||
pub fn my_hash(bytes: []const u8) u32 {
|
||||
const fnv_offset = 14695981039346656037;
|
||||
const fnv_prime = 1099511628211;
|
||||
var result: u64 = fnv_offset;
|
||||
|
||||
for (bytes) |byte| {
|
||||
@ -466,28 +479,30 @@ pub fn PinnedHashMapAdvanced(comptime K: type, comptime V: type, comptime granul
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put(map: *@This(), key: K, value: V) void {
|
||||
pub fn put(map: *@This(), key: K, value: V) *V {
|
||||
if (map.get_pointer(key)) |value_pointer| {
|
||||
value_pointer.* = value;
|
||||
return value_pointer;
|
||||
} else {
|
||||
const len = map.length;
|
||||
map.ensure_capacity(len + 1);
|
||||
map.put_at_with_capacity(len, key, value);
|
||||
return map.put_at_with_capacity(len, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put_no_clobber(map: *@This(), key: K, value: V) void {
|
||||
pub fn put_no_clobber(map: *@This(), key: K, value: V) *V {
|
||||
assert(map.get_pointer(key) == null);
|
||||
const len = map.length;
|
||||
map.ensure_capacity(len + 1);
|
||||
map.put_at_with_capacity(len, key, value);
|
||||
return map.put_at_with_capacity(len, key, value);
|
||||
}
|
||||
|
||||
fn put_at_with_capacity(map: *@This(), index: u64, key: K, value: V) void {
|
||||
fn put_at_with_capacity(map: *@This(), index: u64, key: K, value: V) *V {
|
||||
map.length += 1;
|
||||
assert(index < map.length);
|
||||
map.key_pointer[index] = key;
|
||||
map.value_pointer[index] = value;
|
||||
return &map.value_pointer[index];
|
||||
}
|
||||
|
||||
fn ensure_capacity(map: *Map, additional: u64) void {
|
||||
|
9
retest/standalone/hello_world_string/main.nat
Normal file
9
retest/standalone/hello_world_string/main.nat
Normal file
@ -0,0 +1,9 @@
|
||||
fn [cc(.c)] write[extern](file_descriptor: s32, byte_pointer: *u8, byte_count: u64) s64;
|
||||
|
||||
fn[cc(.c)] main[export]() s32 {
|
||||
>local_string = "Hello world from local string!\n";
|
||||
write(1, local_string&, local_string.length);
|
||||
>global_string: []u8 = "Hello world from global string!\n";
|
||||
write(1, global_string.pointer, global_string.length);
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user