mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Remove string literals.
This commit is contained in:
@@ -210,7 +210,6 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
|
||||
case TYPE_VOID:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_SUBARRAY:
|
||||
case CT_TYPES:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
|
||||
@@ -148,7 +148,7 @@ typedef struct
|
||||
struct
|
||||
{
|
||||
const char *chars;
|
||||
uint32_t len;
|
||||
ArraySize len;
|
||||
} string;
|
||||
Decl *enum_val;
|
||||
Decl *err_val;
|
||||
@@ -1526,7 +1526,7 @@ extern Type *poisoned_type;
|
||||
extern TypeInfo *poisoned_type_info;
|
||||
|
||||
|
||||
extern Type *type_bool, *type_void, *type_compstr, *type_voidptr;
|
||||
extern Type *type_bool, *type_void, *type_voidptr;
|
||||
extern Type *type_half, *type_float, *type_double, *type_quad;
|
||||
extern Type *type_ichar, *type_short, *type_int, *type_long, *type_isize;
|
||||
extern Type *type_char, *type_ushort, *type_uint, *type_ulong, *type_usize;
|
||||
|
||||
@@ -549,7 +549,6 @@ typedef enum
|
||||
TYPE_BITSTRUCT,
|
||||
TYPE_ERRTYPE,
|
||||
TYPE_TYPEDEF,
|
||||
TYPE_STRLIT,
|
||||
TYPE_DISTINCT,
|
||||
TYPE_ARRAY,
|
||||
TYPE_SUBARRAY,
|
||||
|
||||
@@ -112,8 +112,6 @@ static void header_print_type(FILE *file, Type *type)
|
||||
break;
|
||||
case TYPE_TYPEDEF:
|
||||
break;
|
||||
case TYPE_STRLIT:
|
||||
UNREACHABLE
|
||||
case TYPE_ARRAY:
|
||||
break;
|
||||
case TYPE_ANY:
|
||||
|
||||
@@ -339,8 +339,6 @@ void llvm_emit_ptr_from_array(GenContext *c, BEValue *value)
|
||||
llvm_value_set_address_align(value, member.value, type_get_ptr(value->type->array.base), type_abi_alignment(value->type->array.base));
|
||||
return;
|
||||
}
|
||||
case TYPE_STRLIT:
|
||||
return;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
@@ -398,7 +398,6 @@ static void x64_classify(Type *type, ByteSize offset_base, X64Class *lo_class, X
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_DISTINCT:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_ERRTYPE:
|
||||
case TYPE_BITSTRUCT:
|
||||
@@ -588,7 +587,6 @@ AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_ty
|
||||
case TYPE_FUNC:
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_DISTINCT:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_ERRTYPE:
|
||||
case TYPE_BITSTRUCT:
|
||||
|
||||
@@ -113,7 +113,6 @@ static bool x86_should_return_type_in_reg(Type *type)
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_DISTINCT:
|
||||
case TYPE_ENUM:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_ERRTYPE:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_ANYERR:
|
||||
@@ -595,7 +594,6 @@ static ABIArgInfo *x86_classify_argument(CallABI call, Regs *regs, Type *type)
|
||||
case TYPE_FUNC:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_BITSTRUCT:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_FAILABLE:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case CT_TYPES:
|
||||
|
||||
@@ -495,7 +495,6 @@ static inline LLVMMetadataRef llvm_get_debug_type_internal(GenContext *c, Type *
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_STRLIT:
|
||||
case CT_TYPES:
|
||||
UNREACHABLE
|
||||
case TYPE_FAILABLE:
|
||||
|
||||
@@ -514,11 +514,6 @@ static inline void llvm_emit_subscript_addr_with_base(GenContext *c, BEValue *re
|
||||
llvm_value_set_address_align(result, ptr, type->array.base, type_abi_alignment(type->array.base));
|
||||
}
|
||||
return;
|
||||
case TYPE_STRLIT:
|
||||
// TODO insert trap on overflow.
|
||||
llvm_value_set_address_align(result, llvm_emit_pointer_inbounds_gep_raw(c, llvm_get_type(c, type_char), parent->value, index->value),
|
||||
type_char, type_abi_alignment(type_char));
|
||||
return;
|
||||
default:
|
||||
UNREACHABLE
|
||||
|
||||
@@ -2131,9 +2126,6 @@ void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_l
|
||||
case TYPE_ARRAY:
|
||||
llvm_value_set(be_value, llvm_const_int(c, type_usize, expr_to_len->type->array.len), type_usize);
|
||||
break;
|
||||
case TYPE_STRLIT:
|
||||
TODO
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
@@ -2206,8 +2198,6 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
|
||||
case TYPE_ARRAY:
|
||||
parent_base = parent_addr;
|
||||
break;
|
||||
case TYPE_STRLIT:
|
||||
TODO
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
@@ -2236,8 +2226,6 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
|
||||
case TYPE_ARRAY:
|
||||
llvm_value_set_int(c, &len, type_usize, parent_type->array.len);
|
||||
break;
|
||||
case TYPE_STRLIT:
|
||||
TODO
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
@@ -3129,7 +3117,6 @@ void llvm_emit_derived_backend_type(GenContext *c, Type *type)
|
||||
case TYPE_TYPEDEF:
|
||||
original_type = original_type->canonical;
|
||||
continue;
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
@@ -3787,7 +3774,7 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
expr->const_expr.string.len,
|
||||
0));
|
||||
llvm_set_alignment(global_name, 1);
|
||||
global_name = LLVMConstBitCast(global_name, LLVMPointerType(llvm_get_type(c, type_char), 0));
|
||||
global_name = LLVMConstBitCast(global_name, llvm_get_ptr_type(c, type_get_array(type_char, expr->const_expr.string.len)));
|
||||
llvm_value_set(be_value, global_name, type);
|
||||
return;
|
||||
}
|
||||
@@ -3867,7 +3854,6 @@ static void llvm_expand_type_to_args(GenContext *context, Type *param_type, LLVM
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_DISTINCT:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_ENUM:
|
||||
case TYPE_ERRTYPE:
|
||||
case TYPE_ANYERR:
|
||||
|
||||
@@ -351,8 +351,6 @@ LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
|
||||
return any_type->backend_type = LLVMIntTypeInContext(c->context, 8U);
|
||||
case TYPE_POINTER:
|
||||
return any_type->backend_type = llvm_type_from_ptr(c, any_type);
|
||||
case TYPE_STRLIT:
|
||||
return any_type->backend_type = LLVMPointerType(llvm_get_type(c, type_char), 0);
|
||||
case TYPE_ARRAY:
|
||||
return any_type->backend_type = llvm_type_from_array(c, any_type);
|
||||
case TYPE_SUBARRAY:
|
||||
|
||||
@@ -1425,7 +1425,6 @@ static Expr *parse_string_literal(Context *context, Expr *left)
|
||||
{
|
||||
assert(!left && "Had left hand side");
|
||||
Expr *expr_string = EXPR_NEW_TOKEN(EXPR_CONST, context->tok);
|
||||
expr_string->type = type_compstr;
|
||||
|
||||
TokenData *data = TOKDATA(context->tok);
|
||||
const char *str = data->string;
|
||||
@@ -1454,7 +1453,7 @@ static Expr *parse_string_literal(Context *context, Expr *left)
|
||||
assert(str);
|
||||
expr_string->const_expr.string.chars = str;
|
||||
expr_string->const_expr.string.len = (uint32_t)len;
|
||||
expr_string->type = type_compstr;
|
||||
expr_string->type = type_get_ptr(type_get_array(type_char, len));
|
||||
expr_string->const_expr.const_kind = CONST_STRING;
|
||||
return expr_string;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,10 @@ bool pointer_to_pointer(Expr* expr, Type *type)
|
||||
{
|
||||
if (insert_runtime_cast_unless_const(expr, CAST_PTRPTR, type)) return true;
|
||||
|
||||
if (expr->const_expr.const_kind == CONST_STRING)
|
||||
{
|
||||
return insert_cast(expr, CAST_PTRPTR, type);
|
||||
}
|
||||
// Must have been a null
|
||||
expr->type = type;
|
||||
expr->const_expr.narrowable = false;
|
||||
@@ -374,7 +378,6 @@ CastKind cast_to_bool_kind(Type *type)
|
||||
case TYPE_VOID:
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_ENUM:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_ARRAY:
|
||||
@@ -492,10 +495,6 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
|
||||
FALLTHROUGH;
|
||||
case TYPE_UNION:
|
||||
return type_is_structurally_equivalent(from_type, to_type);
|
||||
case TYPE_STRLIT:
|
||||
if (to_kind == TYPE_POINTER) return true;
|
||||
if (to_kind == TYPE_SUBARRAY && (to_type->array.base == type_char || to_type->array.base == type_ichar)) return true;
|
||||
return false;
|
||||
case TYPE_SUBARRAY:
|
||||
return to_kind == TYPE_POINTER;
|
||||
case TYPE_VECTOR:
|
||||
@@ -604,9 +603,6 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool
|
||||
return type_is_subtype(to->pointer, from->pointer);
|
||||
}
|
||||
|
||||
// 4c. Assigning a compile time string to char* is fine. TODO fix correct later
|
||||
if (from->type_kind == TYPE_STRLIT && to->pointer == type_char) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -621,10 +617,6 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool
|
||||
{
|
||||
// 5a. char[] foo = "test"
|
||||
Type *base = to->array.base;
|
||||
if (from->type_kind == TYPE_STRLIT && (base->type_kind == TYPE_I8 || base->type_kind == TYPE_U8))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 5b. Assign sized array pointer int[] = int[4]*
|
||||
if (type_is_pointer(from))
|
||||
@@ -635,15 +627,6 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool
|
||||
}
|
||||
|
||||
|
||||
// 7. In the case of distinct types, we allow implicit conversion from literal types.
|
||||
if (to->type_kind == TYPE_DISTINCT)
|
||||
{
|
||||
if (from->type_kind == TYPE_STRLIT)
|
||||
{
|
||||
return cast_may_implicit(from, type_flatten(to), is_simple_expr, failable_allowed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 8. Check if we may cast this to bool. It is safe for many types.
|
||||
if (to->type_kind == TYPE_BOOL)
|
||||
@@ -1016,12 +999,30 @@ static void sema_error_const_int_out_of_range(Expr *expr, Expr *problem, Type *t
|
||||
SEMA_ERROR(problem, "The value '%s' is out of range for %s, so you need an explicit cast to truncate the value.", error_value,
|
||||
type_quoted_error_string(to_type));
|
||||
}
|
||||
|
||||
static inline bool cast_maybe_string_lit_to_char_array(Expr *expr, Type *expr_canonical, Type *to_canonical)
|
||||
{
|
||||
if (expr->expr_kind != EXPR_CONST || expr->const_expr.const_kind != CONST_STRING) return false;
|
||||
if (expr_canonical->type_kind != TYPE_POINTER) return false;
|
||||
if (to_canonical->type_kind != TYPE_ARRAY && to_canonical->type_kind != TYPE_INFERRED_ARRAY) return false;
|
||||
if (to_canonical->array.base != type_char) return false;
|
||||
Type *pointer = expr_canonical->pointer;
|
||||
if (pointer->type_kind != TYPE_ARRAY) return false;
|
||||
if (pointer->array.base != type_char) return false;
|
||||
expr_insert_deref(expr);
|
||||
return true;
|
||||
}
|
||||
bool cast_implicit(Expr *expr, Type *to_type)
|
||||
{
|
||||
assert(!type_is_failable(to_type));
|
||||
Type *expr_type = expr->type;
|
||||
Type *expr_canonical = expr_type->canonical;
|
||||
Type *to_canonical = to_type->canonical;
|
||||
if (cast_maybe_string_lit_to_char_array(expr, expr_canonical, to_canonical))
|
||||
{
|
||||
expr_type = expr->type;
|
||||
expr_canonical = expr_type->canonical;
|
||||
}
|
||||
if (expr_canonical == to_canonical) return true;
|
||||
bool is_simple = expr_is_simple(expr);
|
||||
if (!cast_may_implicit(expr_canonical, to_canonical, is_simple, true))
|
||||
@@ -1268,11 +1269,6 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type)
|
||||
return insert_cast(expr, CAST_STST, to_type);
|
||||
} // Starting in a little while...
|
||||
break;
|
||||
case TYPE_STRLIT:
|
||||
to = type_flatten(to);
|
||||
if (to->type_kind == TYPE_POINTER) return insert_cast(expr, CAST_STRPTR, to_type);
|
||||
if (to->type_kind == TYPE_SUBARRAY) return string_literal_to_subarray(expr, to_type);
|
||||
break;
|
||||
case TYPE_SUBARRAY:
|
||||
if (to->type_kind == TYPE_POINTER) return insert_cast(expr, CAST_SAPTR, to);
|
||||
if (to->type_kind == TYPE_BOOL) return subarray_to_bool(expr);
|
||||
|
||||
@@ -683,7 +683,6 @@ static inline bool sema_analyse_distinct(Context *context, Decl *decl)
|
||||
decl->distinct_decl.base_type = base;
|
||||
switch (base->type_kind)
|
||||
{
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_DISTINCT:
|
||||
@@ -1166,7 +1165,7 @@ AttributeType sema_analyse_attribute(Context *context, Attr *attr, AttributeDoma
|
||||
return ATTRIBUTE_NONE;
|
||||
}
|
||||
if (!sema_analyse_expr(context, attr->expr)) return false;
|
||||
if (attr->expr->expr_kind != EXPR_CONST || attr->expr->type->canonical != type_compstr)
|
||||
if (attr->expr->expr_kind != EXPR_CONST || attr->expr->const_expr.const_kind != CONST_STRING)
|
||||
{
|
||||
SEMA_ERROR(attr->expr, "Expected a constant string value as argument.");
|
||||
return ATTRIBUTE_NONE;
|
||||
|
||||
@@ -2326,7 +2326,6 @@ static bool expr_check_index_in_range(Context *context, Type *type, Expr *index_
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_SUBARRAY:
|
||||
// If not from end, just check the negative values.
|
||||
if (!from_end) break;
|
||||
@@ -2610,9 +2609,10 @@ static inline void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *str
|
||||
expr_to_rewrite->expr_kind = EXPR_CONST;
|
||||
expr_to_rewrite->const_expr.const_kind = CONST_STRING;
|
||||
expr_to_rewrite->const_expr.string.chars = (char *)string;
|
||||
expr_to_rewrite->const_expr.string.len = (uint32_t)strlen(string);
|
||||
ArraySize len = (ArraySize)strlen(string);
|
||||
expr_to_rewrite->const_expr.string.len = len;
|
||||
expr_to_rewrite->resolve_status = RESOLVE_DONE;
|
||||
expr_to_rewrite->type = type_compstr;
|
||||
expr_to_rewrite->type = type_get_ptr(type_get_array(type_char, len));
|
||||
}
|
||||
|
||||
|
||||
@@ -2972,11 +2972,6 @@ CHECK_DEEPER:
|
||||
// 9. Fix hard coded function `len` on subarrays and arrays
|
||||
if (!is_macro && kw == kw_len)
|
||||
{
|
||||
if (flat_type->type_kind == TYPE_STRLIT)
|
||||
{
|
||||
expr_rewrite_to_int_const(expr, type_isize, parent->const_expr.string.len, true);
|
||||
return true;
|
||||
}
|
||||
if (flat_type->type_kind == TYPE_SUBARRAY)
|
||||
{
|
||||
expr->expr_kind = EXPR_LEN;
|
||||
|
||||
@@ -2099,7 +2099,7 @@ bool sema_analyse_ct_assert_stmt(Context *context, Ast *statement)
|
||||
if (message)
|
||||
{
|
||||
if (!sema_analyse_expr(context, message)) return false;
|
||||
if (message->type->type_kind != TYPE_STRLIT)
|
||||
if (message->expr_kind != EXPR_CONST || message->const_expr.const_kind != CONST_STRING)
|
||||
{
|
||||
SEMA_ERROR(message, "Expected a string as the error message.");
|
||||
}
|
||||
@@ -2175,7 +2175,7 @@ bool sema_analyse_assert_stmt(Context *context, Ast *statement)
|
||||
if (message)
|
||||
{
|
||||
if (!sema_analyse_expr(context, message)) return false;
|
||||
if (message->type->type_kind != TYPE_STRLIT)
|
||||
if (message->expr_kind != EXPR_CONST || message->const_expr.const_kind != CONST_STRING)
|
||||
{
|
||||
SEMA_ERROR(message, "Expected a string as the error message.");
|
||||
}
|
||||
|
||||
@@ -193,7 +193,6 @@ bool sema_resolve_type(Context *context, Type *type)
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_ANY:
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
|
||||
@@ -12,7 +12,7 @@ static struct
|
||||
Type f16, f32, f64, f128, fxx;
|
||||
Type usz, isz, uptr, iptr, uptrdiff, iptrdiff;
|
||||
Type voidstar, typeid, anyerr, typeinfo, ctlist;
|
||||
Type str, any, anyfail;
|
||||
Type any, anyfail;
|
||||
} t;
|
||||
|
||||
Type *type_bool = &t.u1;
|
||||
@@ -41,7 +41,6 @@ Type *type_u128 = &t.u128;
|
||||
Type *type_uptr = &t.uptr;
|
||||
Type *type_uptrdiff = &t.uptrdiff;
|
||||
Type *type_usize = &t.usz;
|
||||
Type *type_compstr = &t.str;
|
||||
Type *type_anyerr = &t.anyerr;
|
||||
Type *type_complist = &t.ctlist;
|
||||
Type *type_anyfail = &t.anyfail;
|
||||
@@ -146,8 +145,6 @@ const char *type_to_error_string(Type *type)
|
||||
if (!type->failable) return "void!";
|
||||
asprintf(&buffer, "%s!", type_to_error_string(type->failable));
|
||||
return buffer;
|
||||
case TYPE_STRLIT:
|
||||
return "string literal";
|
||||
case TYPE_ARRAY:
|
||||
asprintf(&buffer, "%s[%llu]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
|
||||
return buffer;
|
||||
@@ -235,7 +232,6 @@ RETRY:
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_ANY:
|
||||
return type->builtin.bytesize;
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_POINTER:
|
||||
return t.iptr.canonical->builtin.bytesize;
|
||||
@@ -306,7 +302,6 @@ bool type_is_abi_aggregate(Type *type)
|
||||
case TYPE_POINTER:
|
||||
case TYPE_ENUM:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_ERRTYPE:
|
||||
@@ -447,7 +442,6 @@ AlignSize type_abi_alignment(Type *type)
|
||||
return type->builtin.abi_alignment;
|
||||
case TYPE_FUNC:
|
||||
case TYPE_POINTER:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_TYPEID:
|
||||
return t.iptr.canonical->builtin.abi_alignment;
|
||||
case TYPE_ARRAY:
|
||||
@@ -724,8 +718,6 @@ Type *type_get_indexed_type(Type *type)
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
return type->array.base;
|
||||
case TYPE_STRLIT:
|
||||
return type_char;
|
||||
case TYPE_DISTINCT:
|
||||
type = type->decl->distinct_decl.base_type;
|
||||
goto RETRY;
|
||||
@@ -925,7 +917,6 @@ static void type_append_name_to_scratch(Type *type)
|
||||
case TYPE_VECTOR:
|
||||
scratch_buffer_append(type->name);
|
||||
break;
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_TYPEINFO:
|
||||
@@ -1017,7 +1008,6 @@ void type_setup(PlatformTarget *target)
|
||||
|
||||
type_init_int("void", &t.u0, TYPE_VOID, BITS8);
|
||||
|
||||
type_init("string", &t.str, TYPE_STRLIT, target->width_pointer, target->align_pointer);
|
||||
|
||||
|
||||
type_create("typeinfo", &t.typeinfo, TYPE_TYPEINFO, 1, 1, 1);
|
||||
@@ -1092,7 +1082,6 @@ bool type_is_scalar(Type *type)
|
||||
case TYPE_BOOL:
|
||||
case ALL_INTS:
|
||||
case ALL_FLOATS:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_POINTER:
|
||||
case TYPE_ENUM:
|
||||
@@ -1314,6 +1303,20 @@ static inline Type *type_find_max_ptr_type(Type *type, Type *other)
|
||||
}
|
||||
|
||||
|
||||
Type *type_decay_array_pointer(Type *type)
|
||||
{
|
||||
assert(type->type_kind == TYPE_POINTER);
|
||||
Type *ptr = type->pointer;
|
||||
switch (ptr->type_kind)
|
||||
{
|
||||
case TYPE_ARRAY:
|
||||
return type_get_ptr(ptr->array.base->canonical);
|
||||
case TYPE_VECTOR:
|
||||
return type_get_ptr(ptr->vector.base->canonical);
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
Type *type_find_max_type(Type *type, Type *other)
|
||||
{
|
||||
if (type == type_anyfail)
|
||||
@@ -1361,6 +1364,28 @@ Type *type_find_max_type(Type *type, Type *other)
|
||||
if (other->type_kind == TYPE_DISTINCT && type_is_float(other->decl->distinct_decl.base_type)) return other;
|
||||
return type_find_max_num_type(type, other);
|
||||
case TYPE_POINTER:
|
||||
if (type->pointer->type_kind == TYPE_ARRAY)
|
||||
{
|
||||
Type *array_base = type->pointer->array.base->canonical;
|
||||
if (other->type_kind == TYPE_SUBARRAY &&
|
||||
array_base == other->array.base->canonical)
|
||||
{
|
||||
return other;
|
||||
}
|
||||
}
|
||||
if (type->pointer->type_kind == TYPE_VECTOR)
|
||||
{
|
||||
Type *vector_base = type->pointer->vector.base->canonical;
|
||||
if (other->type_kind == TYPE_SUBARRAY && vector_base == other->array.base->canonical)
|
||||
{
|
||||
return other;
|
||||
}
|
||||
}
|
||||
// We need to decay the pointer
|
||||
type = type_decay_array_pointer(type);
|
||||
// And possibly the other pointer as well
|
||||
if (other->type_kind == TYPE_POINTER) other = type_decay_array_pointer(other);
|
||||
|
||||
return type_find_max_ptr_type(type, other);
|
||||
case TYPE_ENUM:
|
||||
// IMPROVE: should there be implicit conversion between one enum and the other in
|
||||
@@ -1378,17 +1403,6 @@ Type *type_find_max_type(Type *type, Type *other)
|
||||
TODO
|
||||
case TYPE_TYPEDEF:
|
||||
UNREACHABLE
|
||||
case TYPE_STRLIT:
|
||||
if (other->type_kind == TYPE_DISTINCT)
|
||||
{
|
||||
// In this case we only react to the flattened type.
|
||||
Type *flatten_other = type_flatten(other);
|
||||
if (flatten_other->type_kind == TYPE_SUBARRAY && flatten_other->array.base->type_kind == TYPE_U8) return other;
|
||||
if (flatten_other->type_kind == TYPE_POINTER && flatten_other->pointer->type_kind == TYPE_U8) return other;
|
||||
}
|
||||
if (other->type_kind == TYPE_SUBARRAY && other->array.base->type_kind == TYPE_U8) return other;
|
||||
if (other->type_kind == TYPE_POINTER && other->pointer->type_kind == TYPE_U8) return other;
|
||||
return NULL;
|
||||
case TYPE_DISTINCT:
|
||||
return NULL;
|
||||
case TYPE_ARRAY:
|
||||
|
||||
@@ -49,17 +49,15 @@ fn void main()
|
||||
@.str.7 = private constant [14 x i8] c"donnowifprime\00", align 1
|
||||
@.str.8 = private constant [4 x i8] c"%s\0A\00", align 1
|
||||
@.str.9 = private constant [14 x i8] c"donnowifprime\00", align 1
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @printf(i8*, ...) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @main() #0 {
|
||||
entry:
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.3, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.4, i32 0, i32 0), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.6, i32 0, i32 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.7, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.8, i32 0, i32 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.9, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), [5 x i8]* bitcast ([6 x i8]* @.str.1 to [5 x i8]*))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), [9 x i8]* bitcast ([10 x i8]* @.str.3 to [9 x i8]*))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.4, i32 0, i32 0), [9 x i8]* bitcast ([10 x i8]* @.str.5 to [9 x i8]*))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.6, i32 0, i32 0), [13 x i8]* bitcast ([14 x i8]* @.str.7 to [13 x i8]*))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.8, i32 0, i32 0), [13 x i8]* bitcast ([14 x i8]* @.str.9 to [13 x i8]*))
|
||||
ret void
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ declare void @printf(i8*, ...) #0
|
||||
; Function Attrs: nounwind
|
||||
define void @main() #0 {
|
||||
entry:
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.3, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.4, i32 0, i32 0), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), [3 x i8]* bitcast ([4 x i8]* @.str.1 to [3 x i8]*))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), [6 x i8]* bitcast ([7 x i8]* @.str.3 to [6 x i8]*))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.4, i32 0, i32 0), [9 x i8]* bitcast ([10 x i8]* @.str.5 to [9 x i8]*))
|
||||
ret void
|
||||
}
|
||||
@@ -43,13 +43,13 @@ fn void main()
|
||||
define void @main()
|
||||
%help = alloca i32, align 4
|
||||
store i32 0, i32* %help, align 4
|
||||
%0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0))
|
||||
%1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.3, i32 0, i32 0))
|
||||
%2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.4, i32 0, i32 0), i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.5, i32 0, i32 0))
|
||||
%3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.7, i32 0, i32 0))
|
||||
%4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.8, i32 0, i32 0), i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.9, i32 0, i32 0))
|
||||
%5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.10, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.11, i32 0, i32 0))
|
||||
%6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.12, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.13, i32 0, i32 0))
|
||||
%7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.14, i32 0, i32 0), i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.15, i32 0, i32 0))
|
||||
%8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.16, i32 0, i32 0), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.17, i32 0, i32 0))
|
||||
%0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), [6 x i8]* bitcast ([7 x i8]* @.str.1 to [6 x i8]*))
|
||||
%1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.2, i32 0, i32 0), [17 x i8]* bitcast ([18 x i8]* @.str.3 to [17 x i8]*))
|
||||
%2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.4, i32 0, i32 0), [15 x i8]* bitcast ([16 x i8]* @.str.5 to [15 x i8]*))
|
||||
%3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), [4 x i8]* bitcast ([5 x i8]* @.str.7 to [4 x i8]*))
|
||||
%4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.8, i32 0, i32 0), [12 x i8]* bitcast ([13 x i8]* @.str.9 to [12 x i8]*))
|
||||
%5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.10, i32 0, i32 0), [1 x i8]* bitcast ([2 x i8]* @.str.11 to [1 x i8]*))
|
||||
%6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.12, i32 0, i32 0), [4 x i8]* bitcast ([5 x i8]* @.str.13 to [4 x i8]*))
|
||||
%7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.14, i32 0, i32 0), [15 x i8]* bitcast ([16 x i8]* @.str.15 to [15 x i8]*))
|
||||
%8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.16, i32 0, i32 0), [9 x i8]* bitcast ([10 x i8]* @.str.17 to [9 x i8]*))
|
||||
ret void
|
||||
|
||||
24
test/test_suite/strings/string_to_array.c3t
Normal file
24
test/test_suite/strings/string_to_array.c3t
Normal file
@@ -0,0 +1,24 @@
|
||||
// #target: x64-darwin
|
||||
module foo;
|
||||
|
||||
fn void main()
|
||||
{
|
||||
char[2] x = "ab";
|
||||
char[*] y = "abc";
|
||||
}
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
@.str = private constant [3 x i8] c"ab\00", align 1
|
||||
@.str.1 = private constant [4 x i8] c"abc\00", align 1
|
||||
|
||||
define void @main() #0 {
|
||||
entry:
|
||||
%x = alloca [2 x i8], align 1
|
||||
%y = alloca [3 x i8], align 1
|
||||
%0 = bitcast [2 x i8]* %x to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %0, i8* align 8 getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i32 2, i1 false)
|
||||
%1 = bitcast [3 x i8]* %y to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %1, i8* align 8 getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i32 0, i32 0), i32 3, i1 false)
|
||||
ret void
|
||||
}
|
||||
@@ -125,7 +125,7 @@ fn void test16()
|
||||
|
||||
fn void test17()
|
||||
{
|
||||
int a = "test"; // #error: 'string literal' into 'int'
|
||||
int a = "test"; // #error: 'char[4]*' into 'int'
|
||||
}
|
||||
|
||||
fn void test18()
|
||||
|
||||
@@ -12,6 +12,6 @@ fn int foo()
|
||||
enum State
|
||||
{
|
||||
A = foo(), // #error: Expected a constant expression for enum
|
||||
B = "hello", // #error: 'string literal' into 'int'
|
||||
B = "hello", // #error: 'char[5]*' into 'int'
|
||||
C = true, // #error: 'bool' to 'int'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user