Added levenshtein.c3 to working files. Fixes to reverse indexing. Added min/max functions. Tentatively removed "opaque"

This commit is contained in:
Christoffer Lerno
2022-01-26 17:39:30 +01:00
parent 8eb295bf5b
commit e5bcb74822
21 changed files with 223 additions and 134 deletions

View File

@@ -0,0 +1,26 @@
module levenshtein;
import std::math;
// This levenshtein exercises C3 subarrays.
fn int levenshtein(char[] s, char[] t)
{
// if either string is empty, difference is inserting all chars
// from the other
if (!s.len) return t.len;
if (!t.len) return s.len;
// if last letters are the same, the difference is whatever is
// required to edit the rest of the strings
if (s[^1] == t[^1]) return levenshtein(s[0..^2], t[0..^2]);
// else try:
// changing last letter of s to that of t; or
// remove last letter of s; or
// remove last letter of t,
// any of which is 1 edit plus editing the rest of the strings
int a = levenshtein(s[0..^2], t[0..^2]);
int b = levenshtein(s, t[0..^2]);
int c = levenshtein(s[0..^2], t);
return @min(@min(a, b), c) + 1;
}

View File

@@ -1,24 +0,0 @@
module levenshtein;
fn int levenshtein(String s, String t)
{
// if either string is empty, difference is inserting all chars
// from the other
if (!s.len) return t.len;
if (!t.len) return s.len;
// if last letters are the same, the difference is whatever is
// required to edit the rest of the strings
if (s[^1] == t[^1]) return levenshtein(s[0..^2], t[0..^2]);
// else try:
// changing last letter of s to that of t; or
// remove last letter of s; or
// remove last letter of t,
// any of which is 1 edit plus editing the rest of the strings
int a = levenshtein(s[0..^2], t[0..^2]);
int b = levenshtein(s, t[0..^2]);
int c = levenshtein(s[0..^2], t);
return @max(@max(a, b), c) + 1;
}

View File

@@ -373,7 +373,7 @@ fn void Parser.expect(Parser* p, TokenKind k)
const u32 MaxDiag = 128;
public struct TomlReader @opaque
public struct TomlReader
{
char[MaxDiag] message;
Blocks* blocks;

View File

@@ -67,6 +67,16 @@ const QUAD_MIN_EXP = -16481;
const QUAD_EPSILON = 1.92592994438723585305597794258492732e-34;
*/
macro max(x, y) @autoimport
{
return x > y ? x : y;
}
macro min(x, y) @autoimport
{
return x < y ? x : y;
}
fn double log10(double x) @inline
{
return $$log10(x);

View File

@@ -6,7 +6,7 @@ macro max(a, b)
}
// Horribly bad implementation of BigInt with add/sub.
public struct BigInt @opaque
public struct BigInt
{
byte* number;
uint length;

View File

@@ -6,7 +6,7 @@ macro @max(a, b)
}
// Horribly bad implementation of BigInt with add/sub.
public struct BigInt @opaque
public struct BigInt
{
byte& number;
uint length;

View File

@@ -274,8 +274,8 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
if (type->type_kind == TYPE_VECTOR)
{
// Widen the type with elements.
unsigned vec_elements = type_size(type) / type_size(type->vector.base);
*base = type_get_vector(type->vector.base, vec_elements);
unsigned vec_elements = type_size(type) / type_size(type->array.base);
*base = type_get_vector(type->array.base, vec_elements);
}
}
// One is vector - other isn't => failure

View File

@@ -272,14 +272,12 @@ struct Type_
Decl *decl;
// int, float, bool
TypeBuiltin builtin;
// Type[], Type[*], Type[123]
// Type[], Type[*], Type[123], Type[<123>] or Type<[123]>
TypeArray array;
// func Type1(Type2, Type3, ...) throws Err1, Err2, ...
TypeFunc func;
// Type*
Type *pointer;
// Type[<123>] or Type<[123]>
TypeVector vector;
// Failable
Type *failable;
// Bitstruct
@@ -583,7 +581,6 @@ typedef struct Decl_
Visibility visibility : 3;
ResolveStatus resolve_status : 3;
bool is_packed : 1;
bool is_opaque : 1;
bool needs_additional_pad : 1;
bool is_substruct : 1;
bool has_variable_array : 1;
@@ -1786,7 +1783,7 @@ static inline bool type_may_negate(Type *type)
switch (type->type_kind)
{
case TYPE_VECTOR:
type = type->vector.base;
type = type->array.base;
goto RETRY;
case ALL_FLOATS:
case ALL_INTS:
@@ -2391,7 +2388,7 @@ static inline bool type_is_char_array(Type *type)
static Type *type_vector_type(Type *type)
{
Type *flatten = type_flatten(type);
return flatten->type_kind == TYPE_VECTOR ? flatten->vector.base : NULL;
return flatten->type_kind == TYPE_VECTOR ? flatten->array.base : NULL;
}
static inline bool type_is_builtin(TypeKind kind) { return kind >= TYPE_VOID && kind <= TYPE_TYPEID; }

View File

@@ -641,7 +641,6 @@ typedef enum
{
ATTRIBUTE_INLINE,
ATTRIBUTE_NOINLINE,
ATTRIBUTE_OPAQUE,
ATTRIBUTE_BIGENDIAN,
ATTRIBUTE_LITTLEENDIAN,
ATTRIBUTE_NORETURN,

View File

@@ -77,7 +77,7 @@ static bool x64_type_is_illegal_vector(Type *type)
if (platform_target.x64.pass_int128_vector_in_mem)
{
// Illegal if i128/u128
TypeKind kind = type->vector.base->type_kind;
TypeKind kind = type->array.base->type_kind;
return kind == TYPE_I128 || kind == TYPE_U128;
}
// Otherwise fine!
@@ -344,7 +344,7 @@ void x64_classify_vector(Type *type, ByteSize offset_base, X64Class *current, X6
}
if (size == 8)
{
Type *element = type->vector.base;
Type *element = type->array.base;
// 1 x double passed in memory (by gcc)
if (element->type_kind == TYPE_F64) return;
@@ -628,7 +628,7 @@ static AbiType x64_get_byte_vector_type(Type *type)
// If vector
if (type->type_kind == TYPE_VECTOR)
{
Type *element = type->vector.base->canonical;
Type *element = type->array.base->canonical;
if (platform_target.x64.pass_int128_vector_in_mem && type_is_int128(element))
{
// Convert to u64

View File

@@ -187,7 +187,7 @@ ABIArgInfo *x86_classify_return(CallABI call, Regs *regs, Type *type)
}
// Always return in register if it fits in a general purpose
// register, or if it is 64 bits and has a single field.
if (size == 1 || size == 2 || size == 4 || (size == 8 && type->vector.len == 1))
if (size == 1 || size == 2 || size == 4 || (size == 8 && type->array.len == 1))
{
return abi_arg_new_direct_coerce_type(type_int_unsigned_by_bitsize(size * 8));
}
@@ -273,8 +273,8 @@ static inline bool x86_is_mmxtype(Type *type)
{
// Return true if the type is an MMX type <2 x i32>, <4 x i16>, or <8 x i8>.
if (type->type_kind != TYPE_VECTOR) return false;
if (type_size(type->vector.base) >= 8) return false;
if (!type_is_integer(type->vector.base)) return false;
if (type_size(type->array.base) >= 8) return false;
if (!type_is_integer(type->array.base)) return false;
return type_size(type) == 8;
}
@@ -442,7 +442,7 @@ static inline ABIArgInfo *x86_classify_vector(Regs *regs, Type *type)
// it as an i8/i16/i32/i64.
if (platform_target.x86.is_darwin_vector_abi)
{
if ((size == 1 || size == 2 || size == 4) || (size == 8 && type->vector.len == 1))
if ((size == 1 || size == 2 || size == 4) || (size == 8 && type->array.len == 1))
{
return abi_arg_new_direct_coerce_type(type_int_unsigned_by_bitsize(size * 8));
}

View File

@@ -455,8 +455,8 @@ static LLVMMetadataRef llvm_debug_vector_type(GenContext *c, Type *type)
Type *current_type = type;
while (current_type->canonical->type_kind == TYPE_VECTOR)
{
vec_add(ranges, LLVMDIBuilderGetOrCreateSubrange(c->debug.builder, 0, current_type->canonical->vector.len));
current_type = current_type->canonical->vector.base;
vec_add(ranges, LLVMDIBuilderGetOrCreateSubrange(c->debug.builder, 0, current_type->canonical->array.len));
current_type = current_type->canonical->array.base;
}
return LLVMDIBuilderCreateVectorType(
c->debug.builder,

View File

@@ -495,11 +495,6 @@ static inline LLVMValueRef llvm_emit_sub_int(GenContext *c, Type *type, LLVMValu
return LLVMBuildSub(c->builder, left, right, "sub");
}
static inline void llvm_emit_subscript_addr_base(GenContext *context, BEValue *value, Expr *parent)
{
llvm_emit_expr(context, value, parent);
llvm_emit_ptr_from_array(context, value);
}
static void llvm_emit_array_bounds_check(GenContext *c, BEValue *index, LLVMValueRef array_max_index, SourceLocation *loc)
{
@@ -527,13 +522,11 @@ static inline void llvm_emit_subscript_addr_with_base(GenContext *c, BEValue *re
switch (type->type_kind)
{
case TYPE_POINTER:
llvm_value_set_address_abi_aligned(result,
llvm_emit_pointer_inbounds_gep_raw(c,
llvm_get_pointee_type(c,
parent->type),
parent->value,
index->value),
type->pointer);
llvm_value_set_address_abi_aligned(result, llvm_emit_pointer_inbounds_gep_raw(
c,
llvm_get_pointee_type(c, parent->type),
parent->value,
index->value), type->pointer);
return;
case TYPE_FLEXIBLE_ARRAY:
{
@@ -542,24 +535,17 @@ static inline void llvm_emit_subscript_addr_with_base(GenContext *c, BEValue *re
llvm_value_set_address(result, ptr, type->array.base, alignment);
return;
}
case TYPE_ARRAY:
case TYPE_VECTOR:
UNREACHABLE
case TYPE_ARRAY:
{
// TODO vector
if (active_target.feature.safe_mode)
{
llvm_emit_array_bounds_check(c, index, llvm_const_int(c, index->type, type->array.len), loc);
}
{
AlignSize alignment;
LLVMValueRef ptr = llvm_emit_array_gep_raw_index(c, parent->value, llvm_get_type(c, type), index->value, parent->alignment, &alignment);
llvm_value_set_address(result, ptr, type->array.base, alignment);
}
AlignSize alignment;
LLVMValueRef ptr = llvm_emit_array_gep_raw_index(c, parent->value, llvm_get_type(c, type), index->value, parent->alignment, &alignment);
llvm_value_set_address(result, ptr, type->array.base, alignment);
return;
}
case TYPE_SUBARRAY:
if (active_target.feature.safe_mode)
{
// TODO insert trap on overflow.
}
{
LLVMValueRef ptr = llvm_emit_pointer_inbounds_gep_raw(c, llvm_get_type(c, type->array.base), parent->value, index->value);
llvm_value_set_address(result, ptr, type->array.base, type_abi_alignment(type->array.base));
@@ -575,11 +561,17 @@ static inline void llvm_emit_vector_subscript(GenContext *c, BEValue *value, Exp
{
llvm_emit_expr(c, value, expr->subscript_expr.expr);
llvm_value_rvalue(c, value);
Type *element = value->type->array.base;
Type *vec = value->type;
assert(vec->type_kind == TYPE_VECTOR);
Type *element = vec->array.base;
LLVMValueRef vector = value->value;
llvm_emit_expr(c, value, expr->subscript_expr.index);
llvm_value_rvalue(c, value);
LLVMValueRef index = value->value;
if (expr->subscript_expr.from_back)
{
index = LLVMBuildNUWSub(c->builder, llvm_const_int(c, value->type, vec->array.len), index, "");
}
if (LLVMIsAConstant(index) && LLVMIsAConstant(vector))
{
llvm_value_set(value, LLVMConstExtractElement(vector, index), element);
@@ -597,24 +589,55 @@ static inline void llvm_emit_vector_subscript(GenContext *c, BEValue *value, Exp
static inline void gencontext_emit_subscript(GenContext *c, BEValue *value, Expr *expr)
{
bool is_value = expr->expr_kind == EXPR_SUBSCRIPT;
if (is_value && type_lowering(expr->subscript_expr.expr->type)->type_kind == TYPE_VECTOR)
Type *parent_type = type_lowering(expr->subscript_expr.expr->type);
if (is_value && parent_type->type_kind == TYPE_VECTOR)
{
llvm_emit_vector_subscript(c, value, expr);
return;
}
BEValue ref;
// First, get thing being subscripted.
llvm_emit_subscript_addr_base(c, &ref, expr->subscript_expr.expr);
// It needs to be an address.
llvm_value_addr(c, &ref);
llvm_emit_expr(c, value, expr->subscript_expr.expr);
BEValue len = { .value = NULL };
TypeKind parent_type_kind = parent_type->type_kind;
// See if we need the length.
bool needs_len = false;
Expr *index_expr = expr->subscript_expr.index;
if (parent_type_kind == TYPE_SUBARRAY)
{
needs_len = active_target.feature.safe_mode || expr->subscript_expr.from_back;
}
else if (parent_type_kind == TYPE_ARRAY)
{
// From back should always be folded.
assert(expr->expr_kind != EXPR_CONST || !expr->subscript_expr.from_back);
needs_len = (active_target.feature.safe_mode && expr->expr_kind != EXPR_CONST) || expr->subscript_expr.from_back;
}
if (needs_len)
{
llvm_emit_len_for_expr(c, &len, value);
llvm_value_rvalue(c, &len);
}
llvm_emit_ptr_from_array(c, value);
assert(llvm_value_is_addr(value));
// Now calculate the index:
BEValue index;
llvm_emit_expr(c, &index, expr->subscript_expr.index);
llvm_emit_expr(c, &index, index_expr);
// It needs to be an rvalue.
llvm_value_rvalue(c, &index);
llvm_emit_subscript_addr_with_base(c, value, &ref, &index, TOKLOC(expr->subscript_expr.index->span.loc));
if (expr->subscript_expr.from_back)
{
assert(needs_len);
index.value = LLVMBuildNUWSub(c->builder, llvm_zext_trunc(c, len.value, llvm_get_type(c, index.type)), index.value, "");
}
if (needs_len && active_target.feature.safe_mode)
{
llvm_emit_array_bounds_check(c, &index, len.value, TOKLOC(expr->subscript_expr.index->span.loc));
}
llvm_emit_subscript_addr_with_base(c, value, value, &index, TOKLOC(expr->subscript_expr.index->span.loc));
if (!is_value)
{
assert(llvm_value_is_addr(value));
@@ -1121,7 +1144,7 @@ void llvm_emit_array_to_vector_cast(GenContext *c, BEValue *value, Type *to_type
LLVMTypeRef vector_type = llvm_get_type(c, to_type);
LLVMValueRef vector = LLVMGetUndef(vector_type);
bool is_const = LLVMIsConstant(value->value);
for (unsigned i = 0; i < to_type->vector.len; i++)
for (unsigned i = 0; i < to_type->array.len; i++)
{
LLVMValueRef element = llvm_emit_extract_value(c, value->value, i);
if (is_const)
@@ -1971,7 +1994,7 @@ static inline void llvm_emit_inc_dec_change(GenContext *c, bool use_mod, BEValue
}
case TYPE_VECTOR:
{
Type *element = type->vector.base;
Type *element = type->array.base;
LLVMValueRef diff_value;
bool is_integer = type_is_integer(element);
if (is_integer)
@@ -1982,7 +2005,7 @@ static inline void llvm_emit_inc_dec_change(GenContext *c, bool use_mod, BEValue
{
diff_value = LLVMConstReal(llvm_get_type(c, element), diff);
}
ArraySize width = type->vector.len;
ArraySize width = type->array.len;
LLVMValueRef val = LLVMGetUndef(llvm_get_type(c, type));
for (ArraySize i = 0; i < width; i++)
{
@@ -2165,22 +2188,27 @@ static void gencontext_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr
void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_len)
{
llvm_value_addr(c, expr_to_len);
switch (expr_to_len->type->type_kind)
{
case TYPE_SUBARRAY:
{
LLVMTypeRef subarray_type = llvm_get_type(c, expr_to_len->type);
AlignSize alignment;
LLVMValueRef len_addr = llvm_emit_struct_gep_raw(c,
expr_to_len->value,
subarray_type,
1,
expr_to_len->alignment,
&alignment);
llvm_value_set_address(be_value, len_addr, type_usize, alignment);
llvm_value_fold_failable(c, be_value);
if (expr_to_len->kind == BE_VALUE)
{
llvm_value_set(be_value, LLVMBuildExtractValue(c->builder, expr_to_len->value, 1, ""), type_usize);
}
else
{
LLVMTypeRef subarray_type = llvm_get_type(c, expr_to_len->type);
AlignSize alignment;
LLVMValueRef len_addr = llvm_emit_struct_gep_raw(c,
expr_to_len->value,
subarray_type,
1,
expr_to_len->alignment,
&alignment);
llvm_value_set_address(be_value, len_addr, type_usize, alignment);
}
break;
}
case TYPE_ARRAY:
llvm_value_set(be_value, llvm_const_int(c, type_usize, expr_to_len->type->array.len), type_usize);
break;
@@ -2298,7 +2326,6 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
// Check that index does not extend beyond the length.
if (parent_type->type_kind != TYPE_POINTER && active_target.feature.safe_mode)
{
assert(len.value);
BEValue exceeds_size;
llvm_emit_int_comparison(c, &exceeds_size, &start_index, &len, BINARYOP_GE);
@@ -3016,7 +3043,7 @@ void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValu
Type *lhs_type = lhs.type;
Type *rhs_type = rhs.type;
Type *vector_type = lhs_type->type_kind == TYPE_VECTOR ? lhs_type->vector.base : NULL;
Type *vector_type = lhs_type->type_kind == TYPE_VECTOR ? lhs_type->array.base : NULL;
bool is_float = type_is_float(lhs_type) || (vector_type && type_is_float(vector_type));
LLVMValueRef val = NULL;
LLVMValueRef lhs_value = lhs.value;
@@ -3164,7 +3191,7 @@ void llvm_emit_derived_backend_type(GenContext *c, Type *type)
original_type = type->failable;
continue;
case TYPE_VECTOR:
original_type = type->vector.base;
original_type = type->array.base;
continue;
case TYPE_ARRAY:
case TYPE_SUBARRAY:
@@ -5120,7 +5147,7 @@ static inline LLVMValueRef llvm_update_vector(GenContext *c, LLVMValueRef vector
static inline void llvm_emit_vector_initializer_list(GenContext *c, BEValue *value, Expr *expr)
{
Type *type = type_lowering(expr->type);
Type *element_type = type->vector.base;
Type *element_type = type->array.base;
LLVMTypeRef llvm_type = llvm_get_type(c, type);

View File

@@ -375,7 +375,7 @@ LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
return any_type->backend_type = virtual_type;
}
case TYPE_VECTOR:
return any_type->backend_type = LLVMVectorType(llvm_get_type(c, any_type->vector.base), any_type->vector.len);
return any_type->backend_type = LLVMVectorType(llvm_get_type(c, any_type->array.base), any_type->array.len);
}
UNREACHABLE;
}

View File

@@ -494,7 +494,7 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
case TYPE_ARRAY:
if (to_kind == TYPE_VECTOR)
{
return to_type->array.len == from_type->vector.len && to_type->array.base == from_type->array.base;
return to_type->array.len == from_type->array.len && to_type->array.base == from_type->array.base;
}
FALLTHROUGH;
case TYPE_STRUCT:
@@ -508,7 +508,7 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
case TYPE_SUBARRAY:
return to_kind == TYPE_POINTER;
case TYPE_VECTOR:
return type_is_structurally_equivalent(type_get_array(from_type->vector.base, (uint32_t)from_type->vector.len), to_type);
return type_is_structurally_equivalent(type_get_array(from_type->array.base, (uint32_t)from_type->array.len), to_type);
case TYPE_UNTYPED_LIST:
REMINDER("Look at untyped list explicit conversions");
return false;

View File

@@ -389,10 +389,6 @@ static bool sema_analyse_struct_union(SemaContext *context, Decl *decl)
had = decl->is_packed;
decl->is_packed = true;
break;
case ATTRIBUTE_OPAQUE:
had = decl->is_opaque;
decl->is_opaque = true;
break;
default:
UNREACHABLE
}
@@ -550,10 +546,6 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl)
case ATTRIBUTE_OVERLAP:
SET_ATTR(overlap);
break;
case ATTRIBUTE_OPAQUE:
had = decl->is_opaque;
decl->is_opaque = true;
break;
case ATTRIBUTE_BIGENDIAN:
if (decl->bitstruct.little_endian)
{
@@ -1143,7 +1135,6 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute
[ATTRIBUTE_ALIGN] = ATTR_FUNC | ATTR_CONST | ATTR_LOCAL | ATTR_GLOBAL | ATTR_STRUCT | ATTR_UNION | ATTR_MEMBER,
[ATTRIBUTE_INLINE] = ATTR_FUNC | ATTR_CALL,
[ATTRIBUTE_NOINLINE] = ATTR_FUNC | ATTR_CALL,
[ATTRIBUTE_OPAQUE] = ATTR_STRUCT | ATTR_UNION | ATTR_BITSTRUCT,
[ATTRIBUTE_BIGENDIAN] = ATTR_BITSTRUCT,
[ATTRIBUTE_LITTLEENDIAN] = ATTR_BITSTRUCT,
[ATTRIBUTE_USED] = (AttributeDomain)~ATTR_CALL,

View File

@@ -32,9 +32,8 @@ static bool sema_decay_array_pointers(Expr *expr)
switch (expr_type->pointer->type_kind)
{
case TYPE_ARRAY:
return cast_implicit(expr, type_get_ptr(expr_type->pointer->array.base));
case TYPE_VECTOR:
return cast_implicit(expr, type_get_ptr(expr_type->pointer->vector.base));
return cast_implicit(expr, type_get_ptr(expr_type->pointer->array.base));
default:
return true;
}
@@ -93,7 +92,7 @@ static inline bool both_any_integer_or_integer_vector(Expr *left, Expr *right)
if (flatten_left->type_kind != TYPE_VECTOR || flatten_right->type_kind != TYPE_VECTOR) return false;
return type_is_integer(flatten_left->vector.base) && type_is_integer(flatten_right->vector.base);
return type_is_integer(flatten_left->array.base) && type_is_integer(flatten_right->array.base);
}
Expr *expr_generate_decl(Decl *decl, Expr *assign)
@@ -2385,7 +2384,7 @@ static void sema_deref_array_pointers(Expr *expr)
}
}
static bool expr_check_index_in_range(SemaContext *context, Type *type, Expr *index_expr, bool end_index, bool from_end)
static bool expr_check_index_in_range(SemaContext *context, Type *type, Expr *index_expr, bool end_index, bool from_end, bool *remove_from_end)
{
assert(type == type->canonical);
if (index_expr->expr_kind != EXPR_CONST) return true;
@@ -2416,6 +2415,8 @@ static bool expr_check_index_in_range(SemaContext *context, Type *type, Expr *in
if (from_end)
{
idx = len - idx;
index_expr->const_expr.ixx.i.low = idx;
*remove_from_end = true;
}
// Checking end can only be done for arrays.
if (end_index && idx >= len)
@@ -2602,7 +2603,9 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
if (!expr_cast_to_index(index)) return false;
// Check range
if (!expr_check_index_in_range(context, current_type, index, false, expr->subscript_expr.from_back)) return false;
bool remove_from_back = false;
if (!expr_check_index_in_range(context, current_type, index, false, expr->subscript_expr.from_back, &remove_from_back)) return false;
if (remove_from_back) expr->subscript_expr.from_back = false;
expr->subscript_expr.expr = current_expr;
if (is_addr) inner_type = type_get_ptr(inner_type);
@@ -2656,8 +2659,12 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr)
return false;
}
}
if (!expr_check_index_in_range(context, type, start, false, expr->slice_expr.start_from_back)) return false;
if (end && !expr_check_index_in_range(context, type, end, true, expr->slice_expr.end_from_back)) return false;
bool remove_from_end = false;
if (!expr_check_index_in_range(context, type, start, false, expr->slice_expr.start_from_back, &remove_from_end)) return false;
if (remove_from_end) expr->slice_expr.start_from_back = false;
remove_from_end = false;
if (end && !expr_check_index_in_range(context, type, end, true, expr->slice_expr.end_from_back, &remove_from_end)) return false;
if (remove_from_end) expr->slice_expr.end_from_back = false;
if (start && end && start->expr_kind == EXPR_CONST && end->expr_kind == EXPR_CONST)
{
@@ -3285,13 +3292,10 @@ static Type *sema_find_type_of_element(SemaContext *context, Type *type, Designa
base = type_flattened->array.base;
break;
case TYPE_ARRAY:
case TYPE_VECTOR:
len = type_flattened->array.len;
base = type_flattened->array.base;
break;
case TYPE_VECTOR:
len = type_flattened->vector.len;
base = type_flattened->vector.base;
break;
default:
return NULL;
}
@@ -5195,7 +5199,7 @@ static bool sema_expr_analyse_comp(SemaContext *context, Expr *expr, Expr *left,
if (left_type->type_kind == TYPE_VECTOR && right_type->type_kind == TYPE_VECTOR)
{
if (left_type->vector.len == right_type->vector.len)
if (left_type->array.len == right_type->array.len)
{
Type *left_vec = type_vector_type(left_type);
Type *right_vec = type_vector_type(right_type);

View File

@@ -194,7 +194,6 @@ void symtab_init(uint32_t capacity)
attribute_list[ATTRIBUTE_INLINE] = kw_inline;
attribute_list[ATTRIBUTE_NOINLINE] = KW_DEF("noinline");
attribute_list[ATTRIBUTE_OPAQUE] = KW_DEF("opaque");
attribute_list[ATTRIBUTE_BIGENDIAN] = KW_DEF("bigendian");
attribute_list[ATTRIBUTE_LITTLEENDIAN] = KW_DEF("littleendian");
attribute_list[ATTRIBUTE_NORETURN] = KW_DEF("noreturn");

View File

@@ -282,7 +282,7 @@ RETRY:
goto RETRY;
case TYPE_VECTOR:
{
TypeSize width = type_size(type->vector.base) * type->vector.len;
TypeSize width = type_size(type->array.base) * type->array.len;
if (width & (width - 1))
{
AlignSize alignment = next_highest_power_of_2((uint32_t) width);
@@ -340,7 +340,7 @@ const char *type_generate_qname(Type *type)
bool type_is_float_or_float_vector(Type *type)
{
type = type_flatten(type);
if (type->type_kind == TYPE_VECTOR) type = type->vector.base;
if (type->type_kind == TYPE_VECTOR) type = type->array.base;
TypeKind kind = type->type_kind;
return kind >= TYPE_FLOAT_FIRST && kind <= TYPE_FLOAT_LAST;
}
@@ -494,7 +494,7 @@ AlignSize type_abi_alignment(Type *type)
goto RETRY;
case TYPE_VECTOR:
{
ByteSize width = type_size(type->vector.base) * (uint32_t)type->vector.len;
ByteSize width = type_size(type->array.base) * (uint32_t)type->array.len;
AlignSize alignment = (AlignSize)(int32_t)width;
if (alignment & (alignment - 1))
{
@@ -865,7 +865,7 @@ static Type *type_create_array(Type *element_type, ArraySize len, bool vector, b
if (vector)
{
if (ptr_vec->type_kind != TYPE_VECTOR) continue;
if (ptr_vec->vector.len == len) return ptr_vec;
if (ptr_vec->array.len == len) return ptr_vec;
}
else
{
@@ -877,8 +877,8 @@ static Type *type_create_array(Type *element_type, ArraySize len, bool vector, b
if (vector)
{
vec_arr = type_new(TYPE_VECTOR, strformat("%s[<%u>]", element_type->name, len));
vec_arr->vector.base = element_type;
vec_arr->vector.len = len;
vec_arr->array.base = element_type;
vec_arr->array.len = len;
}
else
{
@@ -923,8 +923,8 @@ bool type_is_valid_for_vector(Type *type)
Type *type_get_vector_bool(Type *original_type)
{
Type *type = type_flatten(original_type);
ByteSize size = type_size(type->vector.base);
return type_get_vector(type_int_signed_by_bitsize((unsigned)size * 8), (unsigned)original_type->vector.len);
ByteSize size = type_size(type->array.base);
return type_get_vector(type_int_signed_by_bitsize((unsigned)size * 8), (unsigned)original_type->array.len);
}
Type *type_get_vector(Type *vector_type, unsigned len)
@@ -1468,9 +1468,8 @@ Type *type_decay_array_pointer(Type *type)
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);
return type_get_ptr(ptr->array.base->canonical);
default:
return type;
}
@@ -1534,7 +1533,7 @@ Type *type_find_max_type(Type *type, Type *other)
}
if (type->pointer->type_kind == TYPE_VECTOR)
{
Type *vector_base = type->pointer->vector.base->canonical;
Type *vector_base = type->pointer->array.base->canonical;
if (other->type_kind == TYPE_SUBARRAY && vector_base == other->array.base->canonical)
{
return other;

View File

@@ -1 +1 @@
#define COMPILER_VERSION "PRE.19"
#define COMPILER_VERSION "PRE.20"

View File

@@ -0,0 +1,61 @@
// #target: x64-darwin
module test;
fn void test(int[10] x, int[<10>] y)
{
int a = x[4];
int b = x[^2];
int c = y[4];
int d = y[^2];
int j = 3;
int e = y[^j];
int f = x[^j];
}
/* #expect: test.ll
define void @test.test([10 x i32]* byval([10 x i32]) align 8 %0, <10 x i32>* byval(<10 x i32>) align 64 %1) #0 {
entry:
%x = alloca [10 x i32], align 4
%y = alloca <10 x i32>, align 64
%a = alloca i32, align 4
%b = alloca i32, align 4
%c = alloca i32, align 4
%d = alloca i32, align 4
%j = alloca i32, align 4
%e = alloca i32, align 4
%f = alloca i32, align 4
%2 = bitcast [10 x i32]* %x to i8*
%3 = bitcast [10 x i32]* %0 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %2, i8* align 8 %3, i32 40, i1 false)
%4 = bitcast <10 x i32>* %y to i8*
%5 = bitcast <10 x i32>* %1 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 64 %4, i8* align 64 %5, i32 64, i1 false)
%6 = getelementptr inbounds [10 x i32], [10 x i32]* %x, i64 0, i64 4
%7 = load i32, i32* %6, align 4
store i32 %7, i32* %a, align 4
%8 = getelementptr inbounds [10 x i32], [10 x i32]* %x, i64 0, i64 8
%9 = load i32, i32* %8, align 4
store i32 %9, i32* %b, align 4
%10 = load <10 x i32>, <10 x i32>* %y, align 64
%11 = extractelement <10 x i32> %10, i64 4
store i32 %11, i32* %c, align 4
%12 = load <10 x i32>, <10 x i32>* %y, align 64
%13 = extractelement <10 x i32> %12, i64 8
store i32 %13, i32* %d, align 4
store i32 3, i32* %j, align 4
%14 = load <10 x i32>, <10 x i32>* %y, align 64
%15 = load i32, i32* %j, align 4
%sisiext = sext i32 %15 to i64
%16 = sub nuw i64 10, %sisiext
%17 = extractelement <10 x i32> %14, i64 %16
store i32 %17, i32* %e, align 4
%18 = load i32, i32* %j, align 4
%sisiext1 = sext i32 %18 to i64
%19 = sub nuw i64 10, %sisiext1
%20 = getelementptr inbounds [10 x i32], [10 x i32]* %x, i64 0, i64 %19
%21 = load i32, i32* %20, align 4
store i32 %21, i32* %f, align 4
ret void
}