#load(path, type)

where `type` can be `string` or `[]T` where `T` is a simple type
This commit is contained in:
gingerBill
2022-08-11 14:30:14 +01:00
parent 70dc0c15fd
commit a7c3906003
4 changed files with 143 additions and 9 deletions
+42 -7
View File
@@ -1169,11 +1169,11 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
String name = bd->name.string;
GB_ASSERT(name == "load");
if (ce->args.count != 1) {
if (ce->args.count != 1 && ce->args.count != 2) {
if (ce->args.count == 0) {
error(ce->close, "'#load' expects 1 argument, got 0");
error(ce->close, "'#%.*s' expects 1 or 2 arguments, got 0", LIT(name));
} else {
error(ce->args[0], "'#load' expects 1 argument, got %td", ce->args.count);
error(ce->args[0], "'#%.*s' expects 1 or 2 arguments, got %td", LIT(name), ce->args.count);
}
return LoadDirective_Error;
@@ -1183,13 +1183,13 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
Operand o = {};
check_expr(c, &o, arg);
if (o.mode != Addressing_Constant) {
error(arg, "'#load' expected a constant string argument");
error(arg, "'#%.*s' expected a constant string argument", LIT(name));
return LoadDirective_Error;
}
if (!is_type_string(o.type)) {
gbString str = type_to_string(o.type);
error(arg, "'#load' expected a constant string, got %s", str);
error(arg, "'#%.*s' expected a constant string, got %s", LIT(name), str);
gb_string_free(str);
return LoadDirective_Error;
}
@@ -1197,8 +1197,43 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
GB_ASSERT(o.value.kind == ExactValue_String);
operand->type = t_u8_slice;
if (type_hint && is_type_string(type_hint)) {
operand->type = type_hint;
if (ce->args.count == 1) {
if (type_hint && is_type_string(type_hint)) {
operand->type = type_hint;
}
} else if (ce->args.count == 2) {
bool failed = false;
Ast *arg_type = ce->args[1];
Type *type = check_type(c, arg_type);
if (type != nullptr && type != t_invalid) {
if (is_type_string(type)) {
operand->type = type;
} else if (is_type_slice(type) /*|| is_type_array(type) || is_type_enumerated_array(type)*/) {
Type *elem = nullptr;
Type *bt = base_type(type);
if (bt->kind == Type_Slice) {
elem = bt->Slice.elem;
} else if (bt->kind == Type_Array) {
elem = bt->Array.elem;
} else if (bt->kind == Type_EnumeratedArray) {
elem = bt->EnumeratedArray.elem;
}
GB_ASSERT(elem != nullptr);
if (is_type_load_safe(elem)) {
operand->type = type;
} else {
failed = true;
}
} else {
failed = true;
}
}
if (failed) {
gbString type_str = type_to_string(type);
error(arg_type, "'#%.*s' invalid type, expected a string, or slice of simple types, got %s", LIT(name), type_str);
gb_string_free(type_str);
}
}
operand->mode = Addressing_Constant;
+2 -2
View File
@@ -391,8 +391,8 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
if (is_type_slice(type)) {
if (value.kind == ExactValue_String) {
GB_ASSERT(is_type_u8_slice(type));
res.value = lb_find_or_add_entity_string_byte_slice(m, value.value_string).value;
GB_ASSERT(is_type_slice(type));
res.value = lb_find_or_add_entity_string_byte_slice_with_type(m, value.value_string, original_type).value;
return res;
} else {
ast_node(cl, CompoundLit, value.value_compound);
+48
View File
@@ -2523,8 +2523,56 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str)
res.type = t_u8_slice;
return res;
}
lbValue lb_find_or_add_entity_string_byte_slice_with_type(lbModule *m, String const &str, Type *slice_type) {
GB_ASSERT(is_type_slice(slice_type));
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
LLVMValueRef data = LLVMConstStringInContext(m->ctx,
cast(char const *)str.text,
cast(unsigned)str.len,
false);
char *name = nullptr;
{
isize max_len = 7+8+1;
name = gb_alloc_array(permanent_allocator(), char, max_len);
u32 id = m->gen->global_array_index.fetch_add(1);
isize len = gb_snprintf(name, max_len, "csbs$%x", id);
len -= 1;
}
LLVMTypeRef type = LLVMTypeOf(data);
LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name);
LLVMSetInitializer(global_data, data);
LLVMSetLinkage(global_data, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr);
LLVMSetAlignment(global_data, 1);
LLVMSetGlobalConstant(global_data, true);
i64 data_len = str.len;
LLVMValueRef ptr = nullptr;
if (data_len != 0) {
ptr = LLVMConstInBoundsGEP2(type, global_data, indices, 2);
} else {
ptr = LLVMConstNull(lb_type(m, t_u8_ptr));
}
if (!is_type_u8_slice(slice_type)) {
Type *bt = base_type(slice_type);
Type *elem = bt->Slice.elem;
i64 sz = type_size_of(elem);
GB_ASSERT(sz > 0);
ptr = LLVMConstPointerCast(ptr, lb_type(m, alloc_type_pointer(elem)));
data_len /= sz;
}
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), data_len, true);
LLVMValueRef values[2] = {ptr, len};
lbValue res = {};
res.value = llvm_const_named_struct(m, slice_type, values, 2);
res.type = slice_type;
return res;
}
lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *expr) {
+51
View File
@@ -2398,6 +2398,57 @@ bool is_type_simple_compare(Type *t) {
return false;
}
bool is_type_load_safe(Type *type) {
GB_ASSERT(type != nullptr);
type = core_type(core_array_type(type));
switch (type->kind) {
case Type_Basic:
return (type->Basic.flags & (BasicFlag_Boolean|BasicFlag_Numeric|BasicFlag_Rune)) != 0;
case Type_BitSet:
if (type->BitSet.underlying) {
return is_type_load_safe(type->BitSet.underlying);
}
return true;
case Type_RelativePointer:
case Type_RelativeSlice:
return true;
case Type_Pointer:
case Type_MultiPointer:
case Type_Slice:
case Type_DynamicArray:
case Type_Proc:
case Type_SoaPointer:
return false;
case Type_Enum:
case Type_EnumeratedArray:
case Type_Array:
case Type_SimdVector:
case Type_Matrix:
GB_PANIC("should never be hit");
return false;
case Type_Struct:
for_array(i, type->Struct.fields) {
if (!is_type_load_safe(type->Struct.fields[i]->type)) {
return false;
}
}
return type_size_of(type) > 0;
case Type_Union:
for_array(i, type->Union.variants) {
if (!is_type_load_safe(type->Union.variants[i])) {
return false;
}
}
return type_size_of(type) > 0;
}
return false;
}
String lookup_subtype_polymorphic_field(Type *dst, Type *src) {
Type *prev_src = src;
// Type *prev_dst = dst;