mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
#load(path, type)
where `type` can be `string` or `[]T` where `T` is a simple type
This commit is contained in:
+40
-5
@@ -1169,11 +1169,11 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
|
|||||||
String name = bd->name.string;
|
String name = bd->name.string;
|
||||||
GB_ASSERT(name == "load");
|
GB_ASSERT(name == "load");
|
||||||
|
|
||||||
if (ce->args.count != 1) {
|
if (ce->args.count != 1 && ce->args.count != 2) {
|
||||||
if (ce->args.count == 0) {
|
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 {
|
} 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;
|
return LoadDirective_Error;
|
||||||
@@ -1183,13 +1183,13 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
|
|||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr(c, &o, arg);
|
check_expr(c, &o, arg);
|
||||||
if (o.mode != Addressing_Constant) {
|
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;
|
return LoadDirective_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_type_string(o.type)) {
|
if (!is_type_string(o.type)) {
|
||||||
gbString str = type_to_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);
|
gb_string_free(str);
|
||||||
return LoadDirective_Error;
|
return LoadDirective_Error;
|
||||||
}
|
}
|
||||||
@@ -1197,9 +1197,44 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
|
|||||||
GB_ASSERT(o.value.kind == ExactValue_String);
|
GB_ASSERT(o.value.kind == ExactValue_String);
|
||||||
|
|
||||||
operand->type = t_u8_slice;
|
operand->type = t_u8_slice;
|
||||||
|
if (ce->args.count == 1) {
|
||||||
if (type_hint && is_type_string(type_hint)) {
|
if (type_hint && is_type_string(type_hint)) {
|
||||||
operand->type = 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;
|
operand->mode = Addressing_Constant;
|
||||||
|
|
||||||
LoadFileCache *cache = nullptr;
|
LoadFileCache *cache = nullptr;
|
||||||
|
|||||||
@@ -391,8 +391,8 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
|||||||
|
|
||||||
if (is_type_slice(type)) {
|
if (is_type_slice(type)) {
|
||||||
if (value.kind == ExactValue_String) {
|
if (value.kind == ExactValue_String) {
|
||||||
GB_ASSERT(is_type_u8_slice(type));
|
GB_ASSERT(is_type_slice(type));
|
||||||
res.value = lb_find_or_add_entity_string_byte_slice(m, value.value_string).value;
|
res.value = lb_find_or_add_entity_string_byte_slice_with_type(m, value.value_string, original_type).value;
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
ast_node(cl, CompoundLit, value.value_compound);
|
ast_node(cl, CompoundLit, value.value_compound);
|
||||||
|
|||||||
@@ -2523,8 +2523,56 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str)
|
|||||||
res.type = t_u8_slice;
|
res.type = t_u8_slice;
|
||||||
return res;
|
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) {
|
lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *expr) {
|
||||||
|
|||||||
@@ -2398,6 +2398,57 @@ bool is_type_simple_compare(Type *t) {
|
|||||||
return false;
|
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) {
|
String lookup_subtype_polymorphic_field(Type *dst, Type *src) {
|
||||||
Type *prev_src = src;
|
Type *prev_src = src;
|
||||||
// Type *prev_dst = dst;
|
// Type *prev_dst = dst;
|
||||||
|
|||||||
Reference in New Issue
Block a user