Remove old try-catch. Top down promotion for binary etc. Prevent non-simple widening. Introducing wildcard failable. Move LLVM GEP usage. Regcall test and fix. Optimized slice assign.

This commit is contained in:
Christoffer Lerno
2021-10-22 15:39:20 +02:00
committed by Christoffer Lerno
parent e2a3000c39
commit 29e7af843a
75 changed files with 2890 additions and 2267 deletions

View File

@@ -217,6 +217,63 @@ Decl *decl_new_generated_var(const char *name, Type *type, VarDeclKind kind, Sou
return decl;
}
bool expr_is_simple(Expr *expr)
{
RETRY:
switch (expr->expr_kind)
{
case EXPR_GROUP:
expr = expr->inner_expr;
goto RETRY;
case EXPR_OR_ERROR:
case EXPR_TERNARY:
return false;
case EXPR_RETHROW:
expr = expr->rethrow_expr.inner;
goto RETRY;
default:
return true;
case EXPR_BINARY:
switch (expr->binary_expr.operator)
{
case BINARYOP_AND:
case BINARYOP_OR:
case BINARYOP_GT:
case BINARYOP_GE:
case BINARYOP_LT:
case BINARYOP_LE:
case BINARYOP_NE:
case BINARYOP_EQ:
case BINARYOP_ASSIGN:
case BINARYOP_ADD_ASSIGN:
case BINARYOP_BIT_AND_ASSIGN:
case BINARYOP_BIT_OR_ASSIGN:
case BINARYOP_BIT_XOR_ASSIGN:
case BINARYOP_DIV_ASSIGN:
case BINARYOP_MOD_ASSIGN:
case BINARYOP_MULT_ASSIGN:
case BINARYOP_SHR_ASSIGN:
case BINARYOP_SHL_ASSIGN:
case BINARYOP_SUB_ASSIGN:
return true;
default:
return false;
}
UNREACHABLE
case EXPR_UNARY:
switch (expr->unary_expr.operator)
{
case UNARYOP_NEG:
case UNARYOP_BITNEG:
return false;
default:
return true;
}
UNREACHABLE
}
UNREACHABLE
}
Expr *expr_new(ExprKind kind, SourceSpan start)
{

View File

@@ -463,11 +463,6 @@ typedef struct
FunctionSignature attr_signature;
} AttrDecl;
typedef struct
{
Decl *import;
} AliasDecl;
typedef struct
{
bool is_func : 1;
@@ -631,6 +626,7 @@ typedef struct Decl_
typedef struct
{
bool is_jump : 1;
bool widen : 1;
Expr *expr;
union
{
@@ -651,19 +647,22 @@ typedef struct
Expr *cond;
Expr *then_expr; // May be null for elvis!
Expr *else_expr;
bool widen : 1;
} ExprTernary;
typedef struct
{
Expr *left;
Expr *right;
BinaryOp operator;
BinaryOp operator : 8;
bool widen : 1;
} ExprBinary;
typedef struct
{
Expr* expr;
UnaryOp operator;
UnaryOp operator : 8;
bool widen : 1;
} ExprUnary;
@@ -747,8 +746,6 @@ typedef struct
{
Path *path;
TokenId identifier;
bool is_ref : 1;
bool is_rvalue : 1;
Decl *decl;
} ExprIdentifier;
@@ -849,18 +846,6 @@ typedef struct
AstId defer;
} ExprGuard;
typedef struct
{
bool is_try;
Expr *expr;
} ExprTryExpr;
typedef struct
{
bool is_try : 1;
Expr *expr;
Expr *init;
} ExprTryAssign;
typedef struct
{
@@ -922,37 +907,28 @@ struct Expr_
SourceSpan span;
Type *type;
union {
Expr *group_expr;
ExprLen len_expr;
ExprCast cast_expr;
Expr *typeof_expr;
TypeInfo *type_expr;
ExprConst const_expr;
ExprStructValue struct_value_expr;
ExprGuard rethrow_expr;
Expr *trycatch_expr;
Decl *decl_expr;
ExprOrError or_error_expr;
ExprFlatElement *flatpath_expr;
ExprSliceAssign slice_assign_expr;
ExprBinary binary_expr;
ExprTernary ternary_expr;
ExprUnary unary_expr;
Expr** try_unwrap_chain_expr;
ExprTryUnwrap try_unwrap_expr;
Expr* force_unwrap_expr;
ExprCall call_expr;
ExprSlice slice_expr;
ExprTryExpr try_expr;
ExprTryAssign try_assign_expr;
ExprTryDecl try_decl_expr;
Expr *inner_expr;
ExprCatchUnwrap catch_unwrap_expr;
ExprSubscript subscript_expr;
ExprAccess access_expr;
ExprDesignator designator_expr;
ExprIdentifier identifier_expr;
ExprPlaceholder placeholder_expr;
ExprIdentifier macro_identifier_expr;
ExprIdentifierRaw ct_ident_expr;
ExprCtCall ct_call_expr;
ExprIdentifierRaw ct_macro_ident_expr;
@@ -960,7 +936,6 @@ struct Expr_
ExprIdentifierRaw hash_ident_expr;
TypeInfo *typeid_expr;
ExprBodyExpansion body_expansion_expr;
Decl *expr_enum;
ExprCompoundLiteral expr_compound_literal;
Expr** expression_list;
Expr** initializer_list;
@@ -968,8 +943,6 @@ struct Expr_
ExprScope expr_scope;
ExprFuncBlock expr_block;
ExprMacroBlock macro_block;
Expr* failable_expr;
Expr** cond_expr;
};
};
@@ -1237,7 +1210,6 @@ typedef struct Ast_
Ast** ct_compound_stmt;
Decl *declare_stmt; // 8
Expr *expr_stmt; // 8
Ast *try_stmt;
Decl *var_stmt; // 8
Ast *volatile_stmt; // 8
AstReturnStmt return_stmt; // 16
@@ -1625,33 +1597,6 @@ typedef enum CmpRes_
CMP_GT = 1,
} CmpRes;
typedef enum
{
FLOAT_NAN,
FLOAT_INFINITY,
FLOAT_NORMAL,
FLOAT_ZERO
} FloatCategory;
typedef enum
{
ROUNDING_TOWARD_ZERO,
ROUNDING_NEAREST_TIES_TO_EVEN,
ROUNDING_TOWARD_POSITIVE,
ROUNDING_TOWARD_NEGATIVE,
ROUNDING_NEAREST_TIES_TO_AWAY
} FloatRounding;
typedef struct FloatXX
{
union
{
double f64;
float f32;
};
TypeKind type;
} FloatXX;
void type_setup(PlatformTarget *target);
Float float_add(Float op1, Float op2);
Float float_sub(Float op1, Float op2);
@@ -1761,12 +1706,12 @@ static inline bool type_may_negate(Type *type)
}
bool cast_implicit_ignore_failable(Expr *expr, Type *to_type);
bool cast_implicit(Expr *expr, Type *to_type);
bool cast(Expr *expr, Type *to_type);
bool cast_may_implicit(Type *from_type, Type *to_type);
bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability);
bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool failable_allowed);
bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability, bool is_const);
bool cast_implicit_bit_width(Expr *expr, Type *to_type);
CastKind cast_to_bool_kind(Type *type);
@@ -1849,6 +1794,7 @@ void diag_verror_range(SourceLocation *location, const char *message, va_list ar
#define EXPR_NEW_EXPR(kind_, expr_) expr_new(kind_, (expr_)->span)
#define EXPR_NEW_TOKEN(kind_, tok_) expr_new(kind_, source_span_from_token_id((tok_).id))
Expr *expr_new(ExprKind kind, SourceSpan start);
bool expr_is_simple(Expr *expr);
static inline bool expr_ok(Expr *expr) { return expr == NULL || expr->expr_kind != EXPR_POISONED; }
static inline bool expr_poison(Expr *expr) { expr->expr_kind = EXPR_POISONED; expr->resolve_status = RESOLVE_DONE; return false; }
static inline void expr_replace(Expr *expr, Expr *replacement)
@@ -1934,6 +1880,7 @@ void sema_analysis_pass_ct_assert(Module *module);
void sema_analysis_pass_functions(Module *module);
void sema_analyze_stage(Module *module, AnalysisStage stage);
bool sema_failed_cast(Expr *expr, Type *from, Type *to);
bool sema_add_member(Context *context, Decl *decl);
bool sema_add_local(Context *context, Decl *decl);
bool sema_unwrap_var(Context *context, Decl *decl);
@@ -1941,14 +1888,14 @@ bool sema_rewrap_var(Context *context, Decl *decl);
bool sema_erase_var(Context *context, Decl *decl);
bool sema_erase_unwrapped(Context *context, Decl *decl);
bool sema_analyse_cond_expr(Context *context, Expr *expr);
bool sema_analyse_assigned_expr(Context *context, Type *to, Expr *expr, bool may_be_failable);
bool sema_analyse_expr_of_required_type(Context *context, Type *to, Expr *expr);
bool sema_analyse_expr_rhs(Context *context, Type *to, Expr *expr, bool allow_failable);
ArrayIndex sema_get_initializer_const_array_size(Context *context, Expr *initializer, bool *may_be_array, bool *is_const_size);
bool sema_analyse_expr(Context *context, Expr *expr);
bool sema_analyse_inferred_expr(Context *context, Type *to, Expr *expr);
bool sema_analyse_decl(Context *context, Decl *decl);
bool sema_analyse_var_decl(Context *context, Decl *decl);
bool sema_analyse_var_decl(Context *context, Decl *decl, bool local);
bool sema_analyse_ct_assert_stmt(Context *context, Ast *statement);
bool sema_analyse_statement(Context *context, Ast *statement);
bool sema_expr_analyse_assign_right_side(Context *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped_var);
@@ -2107,7 +2054,10 @@ static inline Type *type_reduced_from_expr(Expr *expr)
static inline Type *type_no_fail(Type *type)
{
return type && type->type_kind == TYPE_FAILABLE ? type->failable : type;
if (!type) return NULL;
if (type->type_kind == TYPE_FAILABLE) return type->failable;
if (type->type_kind == TYPE_FAILABLE_ANY) return type_void;
return type;
}
static inline bool type_is_pointer_sized_or_more(Type *type)
@@ -2124,8 +2074,11 @@ static inline bool type_is_pointer_sized(Type *type)
TypeKind k_ = (t_)->type_kind; \
if (k_ == TYPE_TYPEDEF) k_ = (t_)->canonical->type_kind;
#define IS_FAILABLE(element_) ((element_)->type->type_kind == TYPE_FAILABLE)
#define TYPE_IS_FAILABLE(type_) (type_->type_kind == TYPE_FAILABLE)
#define IS_FAILABLE(element_) (type_is_failable((element_)->type))
#define type_is_failable(type_) ((type_)->type_kind == TYPE_FAILABLE || (type_)->canonical->type_kind == TYPE_FAILABLE_ANY)
#define type_is_failable_type(type_) ((type_)->type_kind == TYPE_FAILABLE)
#define type_is_failable_any(type_) ((type_)->canonical->type_kind == TYPE_FAILABLE_ANY)
#define type_is_void(type_) (type_->canonical->type_kind == TYPE_VOID)
static inline Type *type_with_added_failability(Expr *expr, bool add_failable)
{
@@ -2143,13 +2096,13 @@ static inline Type *type_get_opt_fail(Type *type, bool add_failable)
static inline bool type_is_integer(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type);
return kind >= TYPE_INTEGER_FIRST && type->type_kind <= TYPE_INTEGER_LAST;
return kind >= TYPE_INTEGER_FIRST && kind <= TYPE_INTEGER_LAST;
}
static inline bool type_is_integer_signed(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type);
return kind >= TYPE_INT_FIRST && type->type_kind <= TYPE_INT_LAST;
return kind >= TYPE_INT_FIRST && kind <= TYPE_INT_LAST;
}
static inline bool type_is_integer_or_bool_kind(Type *type)
@@ -2161,7 +2114,7 @@ static inline bool type_is_integer_or_bool_kind(Type *type)
static inline bool type_is_integer_unsigned(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type);
return kind >= TYPE_UINT_FIRST && type->type_kind <= TYPE_UINT_LAST;
return kind >= TYPE_UINT_FIRST && kind <= TYPE_UINT_LAST;
}
static inline bool type_info_poison(TypeInfo *type)
@@ -2319,9 +2272,12 @@ static inline Type *type_flatten(Type *type)
if (type->type_kind == TYPE_FAILABLE)
{
type = type->failable;
if (!type) type = type_void;
continue;
}
if (type->type_kind == TYPE_FAILABLE_ANY)
{
return type_void;
}
return type;
}
}

View File

@@ -75,9 +75,6 @@ Expr *copy_expr(Expr *source_expr)
case EXPR_UNDEF:
case EXPR_NOP:
return expr;
case EXPR_FORCE_UNWRAP:
MACRO_COPY_EXPR(expr->force_unwrap_expr);
return expr;
case EXPR_DECL:
MACRO_COPY_DECL(expr->decl_expr);
return expr;
@@ -123,19 +120,16 @@ Expr *copy_expr(Expr *source_expr)
case EXPR_LEN:
MACRO_COPY_EXPR(expr->len_expr.inner);
return expr;
case EXPR_TRY_ASSIGN:
MACRO_COPY_EXPR(expr->try_assign_expr.expr);
MACRO_COPY_EXPR(expr->try_assign_expr.init);
return expr;
case EXPR_FORCE_UNWRAP:
case EXPR_TRY:
MACRO_COPY_EXPR(expr->try_expr.expr);
case EXPR_CATCH:
case EXPR_FAILABLE:
case EXPR_GROUP:
MACRO_COPY_EXPR(expr->inner_expr);
return expr;
case EXPR_COND:
MACRO_COPY_EXPR_LIST(expr->cond_expr);
return expr;
case EXPR_FAILABLE:
MACRO_COPY_EXPR(expr->failable_expr);
return expr;
case EXPR_OR_ERROR:
MACRO_COPY_EXPR(expr->or_error_expr.expr);
if (expr->or_error_expr.is_jump)
@@ -149,9 +143,6 @@ Expr *copy_expr(Expr *source_expr)
return expr;
case EXPR_MACRO_BLOCK:
UNREACHABLE
case EXPR_TYPEOF:
MACRO_COPY_EXPR(expr->typeof_expr);
return expr;
case EXPR_COMPOUND_LITERAL:
MACRO_COPY_EXPR(expr->expr_compound_literal.initializer);
MACRO_COPY_TYPE(expr->expr_compound_literal.type_info);
@@ -193,9 +184,6 @@ Expr *copy_expr(Expr *source_expr)
MACRO_COPY_EXPR(expr->subscript_expr.expr);
MACRO_COPY_EXPR(expr->subscript_expr.index);
return expr;
case EXPR_GROUP:
MACRO_COPY_EXPR(expr->group_expr);
return expr;
case EXPR_ACCESS:
MACRO_COPY_EXPR(expr->access_expr.parent);
return expr;

View File

@@ -118,16 +118,9 @@ typedef enum
CAST_VRPTR,
CAST_PTRVR,
CAST_VRBOOL,
CAST_VFTOERR,
} CastKind;
typedef enum
{
CAST_TYPE_EXPLICIT,
CAST_TYPE_IMPLICIT,
CAST_TYPE_OPTIONAL_IMPLICIT,
} CastType;
typedef enum
{
@@ -182,6 +175,7 @@ typedef enum
EXPR_MACRO_BODY_EXPANSION,
EXPR_CALL,
EXPR_CAST,
EXPR_CATCH,
EXPR_CATCH_UNWRAP,
EXPR_COMPOUND_LITERAL,
EXPR_CONST,
@@ -215,10 +209,8 @@ typedef enum
EXPR_TRY,
EXPR_TRY_UNWRAP,
EXPR_TRY_UNWRAP_CHAIN,
EXPR_TRY_ASSIGN,
EXPR_TYPEID,
EXPR_TYPEINFO,
EXPR_TYPEOF,
EXPR_UNARY,
EXPR_UNDEF,
EXPR_CT_CALL,
@@ -557,6 +549,7 @@ typedef enum
TYPE_INFERRED_ARRAY,
TYPE_UNTYPED_LIST,
TYPE_FAILABLE,
TYPE_FAILABLE_ANY,
TYPE_TYPEINFO,
TYPE_VECTOR,
TYPE_VIRTUAL,

View File

@@ -35,6 +35,7 @@ static void header_print_type(FILE *file, Type *type)
case TYPE_BITSTRUCT:
TODO
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
// If this is reachable then we are not doing the proper lowering.
UNREACHABLE
case TYPE_VOID:

View File

@@ -300,15 +300,11 @@ void llvm_emit_ptr_from_array(GenContext *c, BEValue *value)
case TYPE_SUBARRAY:
{
// TODO insert trap on overflow.
LLVMTypeRef subarray_type = llvm_get_type(c, value->type);
assert(value->kind == BE_ADDRESS);
LLVMValueRef pointer_addr = LLVMBuildStructGEP2(c->builder, subarray_type, value->value, 0, "subarrayptr");
LLVMTypeRef pointer_type = llvm_get_type(c, type_get_ptr(value->type->array.base));
AlignSize alignment = type_abi_alignment(type_voidptr);
// We need to pick the worst alignment in case this is packed in an array.
if (value->alignment < alignment) alignment = value->alignment;
llvm_value_set_address_align(value,
llvm_emit_load_aligned(c, pointer_type, pointer_addr, 0, "saptr"), value->type, alignment);
BEValue member;
llvm_emit_subarray_pointer(c, value, &member);
llvm_value_rvalue(c, &member);
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:
@@ -744,10 +740,11 @@ void gencontext_emit_introspection_type(GenContext *c, Decl *decl)
LLVMSetGlobalConstant(enum_elements, 1);
llvm_set_linkage(c, decl, enum_elements);
LLVMSetInitializer(enum_elements, LLVMConstNull(elements_type));
AlignSize alignment = type_alloca_alignment(type_voidptr);
for (unsigned i = 0; i < elements; i++)
{
LLVMValueRef index[2] = { llvm_const_int(c, type_usize, i) };
decl->enums.values[i]->backend_ref = LLVMConstInBoundsGEP(enum_elements, index, 1);
AlignSize store_align;
decl->enums.values[i]->backend_ref = llvm_emit_array_gep_raw(c, enum_elements, elements_type, i, alignment, &store_align);
}
}
LLVMValueRef global_name = LLVMAddGlobal(c->module, llvm_get_type(c, type_char), decl->name ? decl->name : "anon");
@@ -849,9 +846,7 @@ LLVMValueRef llvm_value_rvalue_store(GenContext *c, BEValue *value)
case BE_ADDRESS_FAILABLE:
UNREACHABLE
case BE_ADDRESS:
return llvm_emit_load_aligned(c,
llvm_get_type(c, value->type),
value->value,
return llvm_emit_load_aligned(c, llvm_get_type(c, value->type), value->value,
value->alignment ? value->alignment : type_abi_alignment(value->type),
"");
case BE_BOOLEAN:

View File

@@ -403,6 +403,7 @@ static void x64_classify(Type *type, ByteSize offset_base, X64Class *lo_class, X
case TYPE_ERRTYPE:
case TYPE_BITSTRUCT:
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
case CT_TYPES:
UNREACHABLE
case TYPE_VOID:
@@ -598,6 +599,7 @@ AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_ty
case TYPE_ERRTYPE:
case TYPE_BITSTRUCT:
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
case CT_TYPES:
UNREACHABLE
case TYPE_I128:

View File

@@ -120,6 +120,7 @@ static bool x86_should_return_type_in_reg(Type *type)
case TYPE_BITSTRUCT:
case CT_TYPES:
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
UNREACHABLE
case ALL_INTS:
case ALL_FLOATS:
@@ -596,6 +597,7 @@ static ABIArgInfo *x86_classify_argument(CallABI call, Regs *regs, Type *type)
case TYPE_BITSTRUCT:
case TYPE_STRLIT:
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
case CT_TYPES:
UNREACHABLE
case ALL_FLOATS:

View File

@@ -484,6 +484,7 @@ static inline LLVMMetadataRef llvm_get_debug_type_internal(GenContext *c, Type *
case CT_TYPES:
UNREACHABLE
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
// If this is reachable then we're not doing the proper lowering.
UNREACHABLE
case TYPE_BOOL:

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
static void llvm_emit_param_attributes(GenContext *context, LLVMValueRef function, ABIArgInfo *info, bool is_return, int index, int last_index);
static inline void llvm_emit_return_value(GenContext *context, LLVMValueRef value);
static void llvm_expand_from_args(GenContext *c, Type *type, LLVMValueRef ref, unsigned *index);
static void llvm_expand_from_args(GenContext *c, Type *type, LLVMValueRef ref, unsigned *index, AlignSize alignment);
static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsigned *index);
bool llvm_emit_check_block_branch(GenContext *context)
@@ -76,28 +76,30 @@ void llvm_emit_block(GenContext *context, LLVMBasicBlockRef next_block)
context->current_block_is_target = false;
}
static void llvm_expand_from_args(GenContext *c, Type *type, LLVMValueRef ref, unsigned *index)
static void llvm_expand_from_args(GenContext *c, Type *type, LLVMValueRef ref, unsigned *index, AlignSize alignment)
{
switch (type->type_kind)
{
case TYPE_ARRAY:
{
LLVMTypeRef array_type = llvm_get_type(c, type);
for (unsigned i = 0; i < type->array.len; i++)
{
LLVMValueRef indices[2] = { llvm_get_zero(c, type_uint), llvm_const_int(c, type_uint, i) };
LLVMValueRef target = LLVMBuildInBoundsGEP2(c->builder, llvm_get_type(c, type), ref, indices, 2, "");
LLVMValueRef cast_addr = llvm_emit_bitcast(c, target, type_get_ptr(type->array.base));
llvm_expand_from_args(c, type->array.base, cast_addr, index);
AlignSize element_align;
LLVMValueRef target = llvm_emit_array_gep_raw(c, ref, array_type, i, alignment, &element_align);
llvm_expand_from_args(c, type->array.base, target, index, element_align);
}
return;
}
case TYPE_STRUCT:
{
LLVMTypeRef struct_type = llvm_get_type(c, type);
Decl **members = type->decl->strukt.members;
VECEACH(members, i)
{
LLVMValueRef indices[2] = { llvm_get_zero(c, type_uint), llvm_const_int(c, type_uint, i) };
LLVMValueRef target = LLVMBuildInBoundsGEP2(c->builder, llvm_get_type(c, type), ref, indices, 2, "");
LLVMValueRef cast_addr = llvm_emit_bitcast(c, target, type_get_ptr(members[i]->type));
llvm_expand_from_args(c, members[i]->type, cast_addr, index);
AlignSize element_align;
LLVMValueRef target = llvm_emit_struct_gep_raw(c, ref, struct_type, i, alignment, &element_align);
llvm_expand_from_args(c, members[i]->type, target, index, element_align);
}
return;
}
@@ -105,11 +107,11 @@ static void llvm_expand_from_args(GenContext *c, Type *type, LLVMValueRef ref, u
{
Type *largest_type = type_find_largest_union_element(type);
LLVMValueRef cast_addr = llvm_emit_bitcast(c, ref, type_get_ptr(largest_type));
llvm_expand_from_args(c, largest_type, cast_addr, index);
llvm_expand_from_args(c, largest_type, cast_addr, index, alignment);
return;
}
default:
LLVMBuildStore(c->builder, llvm_get_next_param(c, index), ref);
llvm_store_aligned(c, ref, llvm_get_next_param(c, index), alignment);
return;
}
}
@@ -139,12 +141,15 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsig
// Create the expand type:
LLVMTypeRef coerce_type = llvm_get_coerce_type(c, info);
LLVMValueRef temp = LLVMBuildBitCast(c->builder, decl->backend_ref, LLVMPointerType(coerce_type, 0), "coerce");
LLVMValueRef gep_first = LLVMBuildStructGEP2(c->builder, coerce_type, temp, info->coerce_expand.lo_index, "first");
llvm_store_aligned(c, gep_first, llvm_get_next_param(c, index), 0);
AlignSize alignment = decl->alignment;
AlignSize element_align;
LLVMValueRef gep_first = llvm_emit_struct_gep_raw(c, temp, coerce_type, info->coerce_expand.lo_index, alignment, &element_align);
llvm_store_aligned(c, gep_first, llvm_get_next_param(c, index), element_align);
if (info->coerce_expand.hi)
{
LLVMValueRef gep_second = LLVMBuildStructGEP2(c->builder, coerce_type, temp, info->coerce_expand.hi_index, "second");
llvm_store_aligned(c, gep_second, llvm_get_next_param(c, index), 0);
LLVMValueRef gep_second = llvm_emit_struct_gep_raw(c, temp, coerce_type, info->coerce_expand.hi_index, alignment, &element_align);
llvm_store_aligned(c, gep_second, llvm_get_next_param(c, index), element_align);
}
break;
}
@@ -159,15 +164,14 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsig
// Cast to { lo, hi }
LLVMValueRef cast = LLVMBuildBitCast(c->builder, decl->backend_ref, LLVMPointerType(struct_type, 0), "pair");
// Point to the lo value.
LLVMValueRef lo_ptr = LLVMBuildStructGEP2(c->builder, struct_type, cast, 0, "lo");
AlignSize element_align;
LLVMValueRef lo_ptr = llvm_emit_struct_gep_raw(c, cast, struct_type, 0, decl_alignment, &element_align);
// Store it in the struct.
AlignSize lo_alignment = MIN(llvm_abi_alignment(c, lo), decl_alignment);
llvm_store_aligned(c, lo_ptr, llvm_get_next_param(c, index), lo_alignment);
llvm_store_aligned(c, lo_ptr, llvm_get_next_param(c, index), element_align);
// Point to the hi value.
LLVMValueRef hi_ptr = LLVMBuildStructGEP2(c->builder, struct_type, cast, 1, "hi");
LLVMValueRef hi_ptr = llvm_emit_struct_gep_raw(c, cast, struct_type, 1, decl_alignment, &element_align);
// Store it in the struct.
AlignSize hi_alignment = MIN(llvm_abi_alignment(c, hi), decl_alignment);
llvm_store_aligned(c, hi_ptr, llvm_get_next_param(c, index), hi_alignment);
llvm_store_aligned(c, hi_ptr, llvm_get_next_param(c, index), element_align);
return;
}
case ABI_ARG_DIRECT_COERCE:
@@ -194,19 +198,20 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsig
// Cast to the coerce type.
LLVMValueRef cast = LLVMBuildBitCast(c->builder, decl->backend_ref, LLVMPointerType(coerce_type, 0), "coerce");
AlignSize decl_alignment = decl->alignment;
// Store each expanded parameter.
for (unsigned idx = 0; idx < info->direct_coerce.elements; idx++)
{
LLVMValueRef element_ptr = LLVMBuildStructGEP2(c->builder, coerce_type, cast, idx, "");
AlignSize align;
LLVMValueRef element_ptr = llvm_emit_struct_gep_raw(c, cast, coerce_type, idx, decl_alignment, &align);
LLVMValueRef value = llvm_get_next_param(c, index);
llvm_store_aligned(c, element_ptr, value, MIN(llvm_abi_alignment(c, element_type), decl->alignment));
llvm_store_aligned(c, element_ptr, value, align);
}
return;
}
case ABI_ARG_EXPAND:
{
llvm_expand_from_args(c, decl->type, decl->backend_ref, index);
llvm_expand_from_args(c, decl->type, decl->backend_ref, index, decl->alignment);
if (info->expand.padding_type)
{
// Skip the pad.
@@ -298,10 +303,9 @@ void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *failabl
LLVMValueRef coerce = LLVMBuildBitCast(c->builder, return_value->value, coerce_type, "");
// We might have only one value, in that case, build a GEP to that one.
LLVMValueRef lo_val;
unsigned alignment;
AlignSize alignment;
LLVMValueRef lo = llvm_emit_struct_gep_raw(c, coerce, coerce_type, info->coerce_expand.lo_index,
return_value->alignment,
info->coerce_expand.offset_lo, &alignment);
return_value->alignment, &alignment);
LLVMTypeRef lo_type = llvm_abi_type(c, info->coerce_expand.lo);
lo_val = llvm_emit_load_aligned(c, lo_type, lo, alignment, "");
@@ -314,8 +318,7 @@ void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *failabl
// Let's make a first class aggregate
LLVMValueRef hi = llvm_emit_struct_gep_raw(c, coerce, coerce_type, info->coerce_expand.hi_index,
return_value->alignment,
info->coerce_expand.offset_hi, &alignment);
return_value->alignment, &alignment);
LLVMTypeRef hi_type = llvm_abi_type(c, info->coerce_expand.hi);
LLVMValueRef hi_val = llvm_emit_load_aligned(c, hi_type, hi, alignment, "");
@@ -354,7 +357,7 @@ void llvm_emit_return_implicit(GenContext *c)
LLVMBuildUnreachable(c->builder);
return;
}
if (rtype_real->type_kind == TYPE_FAILABLE)
if (type_is_failable(rtype_real))
{
llvm_emit_return_abi(c, NULL, NULL);
return;

View File

@@ -22,6 +22,7 @@
#include "dwarf.h"
#define SLICE_MAX_UNROLL 4
typedef enum
{
@@ -265,8 +266,15 @@ void llvm_emit_ptr_from_array(GenContext *c, BEValue *value);
void llvm_emit_debug_output(GenContext *c, const char *message, const char *file, const char *func, unsigned line);
void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *failable);
void llvm_emit_return_implicit(GenContext *c);
LLVMValueRef llvm_emit_struct_gep_raw(GenContext *context, LLVMValueRef ptr, LLVMTypeRef struct_type, unsigned index, unsigned struct_alignment, unsigned offset, unsigned *alignment);
LLVMValueRef llvm_emit_array_gep_raw(GenContext *c, LLVMValueRef ptr, LLVMTypeRef array_type, unsigned index, unsigned array_alignment, unsigned *alignment);
void llvm_emit_struct_member_ref(GenContext *c, BEValue *struct_ref, BEValue *member_ref, unsigned member_id);
LLVMValueRef llvm_emit_struct_gep_raw(GenContext *context, LLVMValueRef ptr, LLVMTypeRef struct_type, unsigned index,
unsigned struct_alignment, AlignSize *alignment);
LLVMValueRef llvm_emit_array_gep_raw(GenContext *c, LLVMValueRef ptr, LLVMTypeRef array_type, unsigned index, AlignSize array_alignment, AlignSize *alignment);
LLVMValueRef llvm_emit_array_gep_raw_index(GenContext *c, LLVMValueRef ptr, LLVMTypeRef array_type, LLVMValueRef index, AlignSize array_alignment, AlignSize *alignment);
LLVMValueRef llvm_emit_pointer_gep_raw(GenContext *c, LLVMTypeRef pointee_type, LLVMValueRef ptr, LLVMValueRef offset);
LLVMValueRef llvm_emit_pointer_inbounds_gep_raw(GenContext *c, LLVMTypeRef pointee_type, LLVMValueRef ptr, LLVMValueRef offset);
void llvm_emit_subarray_len(GenContext *context, BEValue *subarray, BEValue *len);
void llvm_emit_subarray_pointer(GenContext *context, BEValue *subarray, BEValue *pointer);
LLVMValueRef llvm_get_next_param(GenContext *context, unsigned *index);

View File

@@ -537,7 +537,7 @@ static void llvm_emit_foreach_stmt(GenContext *c, Ast *ast)
assert(llvm_value_is_addr(&enum_value));
LLVMValueRef ref_to_element = LLVMBuildInBoundsGEP2(c->builder, actual_type_llvm, enum_value.value, &(index_value.value), 1, "");
LLVMValueRef ref_to_element = llvm_emit_pointer_inbounds_gep_raw(c, actual_type_llvm, enum_value.value, index_value.value);
BEValue result;
if (ast->foreach_stmt.value_by_ref)
{
@@ -995,7 +995,6 @@ static bool expr_is_pure(Expr *expr)
case EXPR_CT_IDENT:
case EXPR_TYPEID:
case EXPR_CT_CALL:
case EXPR_TYPEOF:
UNREACHABLE
case EXPR_MACRO_BODY_EXPANSION:
case EXPR_CALL:
@@ -1020,7 +1019,6 @@ static bool expr_is_pure(Expr *expr)
case EXPR_SLICE_ASSIGN:
case EXPR_TRY_UNWRAP:
case EXPR_TRY_UNWRAP_CHAIN:
case EXPR_TRY_ASSIGN:
case EXPR_UNDEF:
case EXPR_TYPEINFO:
case EXPR_FORCE_UNWRAP:
@@ -1036,8 +1034,6 @@ static bool expr_is_pure(Expr *expr)
return true;
}
break;
case EXPR_GROUP:
return expr_is_pure(expr->group_expr);
case EXPR_LEN:
return expr_is_pure(expr->len_expr.inner);
case EXPR_SLICE:
@@ -1052,7 +1048,9 @@ static bool expr_is_pure(Expr *expr)
&& expr_is_pure(expr->ternary_expr.else_expr)
&& expr_is_pure(expr->ternary_expr.then_expr);
case EXPR_TRY:
return expr_is_pure(expr->try_expr.expr);
case EXPR_GROUP:
case EXPR_CATCH:
return expr_is_pure(expr->inner_expr);
}
UNREACHABLE
}
@@ -1208,12 +1206,15 @@ static LLVMValueRef llvm_emit_string(GenContext *c, const char *str)
{
LLVMTypeRef char_type = llvm_get_type(c, type_char);
unsigned len = strlen(str);
LLVMValueRef global_string = LLVMAddGlobal(c->module, LLVMArrayType(char_type, len + 1), "");
LLVMTypeRef char_array_type = LLVMArrayType(char_type, len + 1);
LLVMValueRef global_string = LLVMAddGlobal(c->module, char_array_type, "");
LLVMSetLinkage(global_string, LLVMInternalLinkage);
LLVMSetGlobalConstant(global_string, 1);
LLVMSetInitializer(global_string, LLVMConstStringInContext(c->context, str, len, 0));
LLVMValueRef zero = llvm_get_zero(c, type_usize);
LLVMValueRef string = LLVMBuildInBoundsGEP2(c->builder, LLVMTypeOf(global_string), global_string, &zero, 1, "");
AlignSize alignment;
// TODO alignment
LLVMValueRef string = llvm_emit_array_gep_raw(c, global_string, char_array_type, 0,
1, &alignment);
return LLVMBuildBitCast(c->builder, string, LLVMPointerType(char_type, 0), "");
}
void llvm_emit_debug_output(GenContext *c, const char *message, const char *file, const char *func, unsigned line)

View File

@@ -235,7 +235,7 @@ LLVMTypeRef llvm_func_type(GenContext *context, Type *type)
LLVMTypeRef return_type = NULL;
Type *rtype = signature->rtype->type;
bool is_failable = rtype->type_kind == TYPE_FAILABLE;
bool is_failable = type_is_failable(rtype);
if (is_failable) rtype = rtype->failable;
Type *real_return_type = is_failable ? type_anyerr : rtype;
ABIArgInfo *ret_arg_info = is_failable ? signature->failable_abi_info : signature->ret_abi_info;
@@ -316,6 +316,7 @@ LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
case CT_TYPES:
UNREACHABLE
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
// If this is reachable, then we're not doing the proper lowering.
UNREACHABLE
case TYPE_TYPEID:

View File

@@ -472,11 +472,11 @@ static Expr *parse_grouping_expr(Context *context, Expr *left)
assert(!left && "Unexpected left hand side");
Expr *expr = EXPR_NEW_TOKEN(EXPR_GROUP, context->tok);
advance_and_verify(context, TOKEN_LPAREN);
ASSIGN_EXPR_ELSE(expr->group_expr, parse_expr(context), poisoned_expr);
ASSIGN_EXPR_ELSE(expr->inner_expr, parse_expr(context), poisoned_expr);
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
if (expr->group_expr->expr_kind == EXPR_TYPEINFO && try_consume(context, TOKEN_LPAREN))
if (expr->inner_expr->expr_kind == EXPR_TYPEINFO && try_consume(context, TOKEN_LPAREN))
{
TypeInfo *info = expr->group_expr->type_expr;
TypeInfo *info = expr->inner_expr->type_expr;
if (TOKEN_IS(TOKEN_LBRACE) && info->resolve_status != RESOLVE_DONE)
{
SEMA_TOKEN_ERROR(context->tok, "Unexpected start of a block '{' here. If you intended a compound literal, remove the () around the type.");
@@ -579,7 +579,7 @@ static Expr *parse_failable(Context *context, Expr *left_side)
{
Expr *failable = expr_new(EXPR_FAILABLE, left_side->span);
advance_and_verify(context, TOKEN_BANG);
failable->failable_expr = left_side;
failable->inner_expr = left_side;
RANGE_EXTEND_PREV(failable);
return failable;
}
@@ -852,7 +852,7 @@ static Expr *parse_try_expr(Context *context, Expr *left)
assert(!left && "Unexpected left hand side");
bool is_try = TOKEN_IS(TOKEN_TRY);
advance(context);
Expr *try_expr = expr_new(EXPR_TRY, source_span_from_token_id(context->prev_tok));
Expr *try_expr = expr_new(is_try ? EXPR_TRY : EXPR_CATCH, source_span_from_token_id(context->prev_tok));
if (!try_consume(context, TOKEN_LPAREN))
{
if (is_try)
@@ -866,8 +866,7 @@ static Expr *parse_try_expr(Context *context, Expr *left)
return poisoned_expr;
}
}
ASSIGN_EXPR_ELSE(try_expr->try_expr.expr, parse_expr(context), poisoned_expr);
try_expr->try_expr.is_try = is_try;
ASSIGN_EXPR_ELSE(try_expr->inner_expr, parse_expr(context), poisoned_expr);
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
RANGE_EXTEND_PREV(try_expr);
return try_expr;
@@ -886,7 +885,7 @@ static Expr *parse_force_unwrap_expr(Context *context, Expr *left)
{
Expr *force_unwrap_expr = EXPR_NEW_EXPR(EXPR_FORCE_UNWRAP, left);
advance(context);
force_unwrap_expr->force_unwrap_expr = left;
force_unwrap_expr->inner_expr = left;
RANGE_EXTEND_PREV(force_unwrap_expr);
return force_unwrap_expr;
}

View File

@@ -493,10 +493,10 @@ static inline Ast *parse_decl_or_expr_stmt(Context *context)
bool failable = false;
// We might be parsing "int!"
// If so we need to unwrap this.
if (expr->expr_kind == EXPR_FAILABLE && expr->failable_expr->expr_kind == EXPR_TYPEINFO)
if (expr->expr_kind == EXPR_FAILABLE && expr->inner_expr->expr_kind == EXPR_TYPEINFO)
{
UNREACHABLE
expr_replace(expr, expr->failable_expr);
expr_replace(expr, expr->inner_expr);
}
if (expr->expr_kind == EXPR_TYPEINFO)
{

View File

@@ -23,11 +23,6 @@ do { if (!try_consume(context, TOKEN_COMMA) && !TOKEN_IS(TOKEN_RPAREN)) { \
SEMA_TOKEN_ERROR(context->tok, "Expected ',' or ')'"); return _res; } } while(0)
typedef enum
{
DECL_PARSE_NORMAL,
DECL_PARSE_UNWRAP
} DeclParse;
Decl *parse_top_level_statement(Context *context);
Ast *parse_ct_assert_stmt(Context *context);
Ast *parse_stmt(Context *context);
@@ -35,7 +30,7 @@ Path *parse_path_prefix(Context *context, bool *had_error);
Expr *parse_type_expression_with_path(Context *context, Path *path);
Expr *parse_expr(Context *context);
bool consume_ident(Context *context, const char* name);
Expr *parse_try_expr_after_try(Context *context, bool is_try);
TypeInfo *parse_type(Context *context);
TypeInfo *parse_failable_type(Context *context);
TypeInfo *parse_type_with_base(Context *context, TypeInfo *type_info);
@@ -58,12 +53,12 @@ Decl *parse_decl_after_type(Context *context, TypeInfo *type);
bool parse_parameters(Context *context, Visibility visibility, Decl ***params_ref);
bool parse_arg_list(Context *context, Expr ***result, TokenType param_end, bool *unsplat);
Expr *parse_type_compound_literal_expr_after_type(Context *context, TypeInfo *type_info);
Expr *parse_type_access_expr_after_type(Context *context, TypeInfo *type_info);
bool parse_next_is_decl(Context *context);
bool parse_next_is_case_type(Context *context);
bool parse_next_is_type(Context *context);
bool parse_module(Context *context);
Decl *parse_define_compile_time_variable(Context *context, bool global);
bool try_consume(Context *context, TokenType type);
bool consume(Context *context, TokenType type, const char *message, ...);
bool consume_const_name(Context *context, const char* type);

View File

@@ -24,6 +24,12 @@ static inline bool insert_cast(Expr *expr, CastKind kind, Type *type)
return true;
}
bool sema_failed_cast(Expr *expr, Type *from, Type *to)
{
SEMA_ERROR(expr, "The cast %s to %s is not allowed.", type_quoted_error_string(from), type_quoted_error_string(to));
return false;
}
static inline bool insert_runtime_cast_unless_const(Expr *expr, CastKind kind, Type *type)
{
if (expr->expr_kind == EXPR_CONST) return false;
@@ -121,6 +127,18 @@ bool bool_to_float(Expr *expr, Type *canonical, Type *type)
return true;
}
/**
* Cast bool to float.
*/
bool voidfail_to_error(Expr *expr, Type *canonical, Type *type)
{
Expr *inner = expr_copy(expr);
expr->expr_kind = EXPR_CATCH;
expr->inner_expr = inner;
expr->type = type;
return true;
}
/**
* Convert from any into to bool.
* @return true for any implicit conversion except assign and assign add.
@@ -232,14 +250,6 @@ static bool int_to_float(Expr *expr, CastKind kind, Type *canonical, Type *type)
}
static bool int_literal_to_float(Expr *expr, Type *canonical, Type *type)
{
assert(type_is_float(canonical));
assert(expr->expr_kind == EXPR_CONST);
const_int_to_fp_cast(expr, canonical, type);
return true;
}
/**
* Convert a compile time into to a boolean.
*/
@@ -363,17 +373,23 @@ CastKind cast_to_bool_kind(Type *type)
case TYPE_BITSTRUCT:
case TYPE_UNTYPED_LIST:
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
return CAST_ERROR;
}
UNREACHABLE
}
bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability)
bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability, bool is_const)
{
// 1. failable -> non-failable can't be cast unless we ignore failability.
if (from_type->type_kind == TYPE_FAILABLE && to_type->type_kind != TYPE_FAILABLE)
// *or* we're converting a void! to an error code
if (type_is_failable(from_type) && !type_is_failable(to_type))
{
if (from_type->failable == type_void || !from_type->failable)
{
// void! x; anyerr y = (anyerr)(x);
if (to_type->type_kind == TYPE_ERRTYPE || to_type->type_kind == TYPE_ANYERR) return true;
}
if (!ignore_failability) return false;
}
@@ -388,9 +404,17 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability)
// 2. Same underlying type, always ok
if (from_type == to_type) return true;
if (to_type->type_kind == TYPE_INFERRED_ARRAY)
{
if (from_type->type_kind == TYPE_ARRAY && type_flatten_distinct(from_type->array.base) == type_flatten_distinct(to_type->array.base)) return true;
return false;
}
TypeKind to_kind = to_type->type_kind;
switch (from_type->type_kind)
{
case TYPE_FAILABLE_ANY:
return true;
case TYPE_DISTINCT:
case TYPE_TYPEDEF:
case TYPE_FAILABLE:
@@ -419,6 +443,9 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability)
return to_type == type_bool || to_kind == TYPE_ERRTYPE || type_is_integer(to_type);
case ALL_SIGNED_INTS:
case ALL_UNSIGNED_INTS:
// We don't have to match pointer size if it's a constant.
if (to_kind == TYPE_POINTER && is_const) return true;
FALLTHROUGH;
case TYPE_ENUM:
// Allow conversion int/enum -> float/bool/enum int/enum -> pointer is only allowed if the int/enum is pointer sized.
if (type_is_integer(to_type) || type_is_float(to_type) || to_type == type_bool || to_kind == TYPE_ENUM) return true;
@@ -449,7 +476,7 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability)
case TYPE_STRUCT:
if (type_is_substruct(from_type))
{
if (cast_may_explicit(from_type->decl->strukt.members[0]->type, to_type, false)) return true;
if (cast_may_explicit(from_type->decl->strukt.members[0]->type, to_type, false, false)) return true;
}
FALLTHROUGH;
case TYPE_UNION:
@@ -506,39 +533,49 @@ static bool may_cast_to_virtual(Type *virtual, Type *from)
TODO;
}
bool type_may_convert_to_anyerr(Type *type)
{
if (type_is_failable_any(type)) return true;
if (!type_is_failable_type(type)) return false;
return type->failable->canonical == type_void;
}
/**
* Can the conversion occur implicitly?
*/
bool cast_may_implicit(Type *from_type, Type *to_type)
bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool failable_allowed)
{
if (from_type == type_anyfail)
{
return to_type->type_kind == TYPE_FAILABLE;
}
Type *from = from_type->canonical;
Type *to = to_type->canonical;
// 1. Same canonical type - we're fine.
if (from == to) return true;
// 1. First handle void! => any error
if (to == type_anyerr && type_may_convert_to_anyerr(from_type)) return true;
if (from->type_kind == TYPE_FAILABLE && to->type_kind != TYPE_FAILABLE) return false;
if (to->type_kind == TYPE_FAILABLE)
// 2. any! => may implicitly to convert to any.
if (type_is_failable_any(from_type)) return failable_allowed;
Type *from = from_type->canonical;
if (type_is_failable_type(from_type))
{
return cast_may_implicit(type_no_fail(from), type_no_fail(to));
if (!failable_allowed) return false;
from = from_type->failable->canonical;
}
// 4. Same canonical type - we're fine.
if (from == to) return true;
// 2. Handle floats
if (type_is_float(to))
{
// 2a. Any integer may convert to a float.
if (type_is_integer(from)) return true;
// 2b. Any narrower float or FXX may convert to a float.
// 2b. Any narrower float
if (type_is_float(from))
{
// This works because the type_size of FXX = 0
return type_size(to) >= type_size(from);
ByteSize to_size = type_size(to);
ByteSize from_size = type_size(from);
if (to_size == from_size) return true;
return to_size > from_size && is_simple_expr;
}
return false;
}
@@ -557,7 +594,10 @@ bool cast_may_implicit(Type *from_type, Type *to_type)
// 3a. Any narrower int may convert to a wider or same int, regardless of signedness.
if (type_is_integer(from))
{
return type_size(to) >= type_size(from);
ByteSize to_size = type_size(to);
ByteSize from_size = type_size(from);
if (to_size == from_size) return true;
return to_size > from_size && is_simple_expr;
}
return false;
}
@@ -597,6 +637,12 @@ bool cast_may_implicit(Type *from_type, Type *to_type)
return false;
}
if (to_type->type_kind == TYPE_INFERRED_ARRAY)
{
if (from_type->type_kind == TYPE_ARRAY && type_flatten_distinct(from_type->array.base) == type_flatten_distinct(to_type->array.base)) return true;
return false;
}
// 5. Handle sub arrays
if (to->type_kind == TYPE_SUBARRAY)
{
@@ -621,7 +667,7 @@ bool cast_may_implicit(Type *from_type, Type *to_type)
{
if (from->type_kind == TYPE_STRLIT)
{
return cast_may_implicit(from, type_flatten(to));
return cast_may_implicit(from, type_flatten(to), is_simple_expr, failable_allowed);
}
}
@@ -647,7 +693,7 @@ bool cast_may_implicit(Type *from_type, Type *to_type)
// 11. Substruct cast, if the first member is inline, see if we can cast to this member.
if (type_is_substruct(from))
{
return cast_may_implicit(from->decl->strukt.members[0]->type, to);
return cast_may_implicit(from->decl->strukt.members[0]->type, to, is_simple_expr, failable_allowed);
}
return false;
@@ -804,9 +850,8 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type)
case EXPR_EXPRESSION_LIST:
return recursive_may_narrow_float(VECLAST(expr->expression_list), type);
case EXPR_GROUP:
return recursive_may_narrow_float(expr->group_expr, type);
case EXPR_FORCE_UNWRAP:
return recursive_may_narrow_float(expr->force_unwrap_expr, type);
return recursive_may_narrow_float(expr->inner_expr, type);
case EXPR_RETHROW:
return recursive_may_narrow_float(expr->rethrow_expr.inner, type);
case EXPR_TERNARY:
@@ -843,25 +888,22 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type)
case EXPR_PLACEHOLDER:
case EXPR_TYPEID:
case EXPR_TYPEINFO:
case EXPR_TYPEOF:
case EXPR_UNDEF:
case EXPR_CT_CALL:
case EXPR_NOP:
case EXPR_LEN:
case EXPR_CATCH:
UNREACHABLE
case EXPR_POST_UNARY:
return recursive_may_narrow_float(expr->unary_expr.expr, type);
case EXPR_SCOPED_EXPR:
return recursive_may_narrow_float(expr->expr_scope.expr, type);
case EXPR_TRY:
assert(expr->try_expr.is_try);
return recursive_may_narrow_float(expr->try_expr.expr, type);
return recursive_may_narrow_float(expr->inner_expr, type);
case EXPR_TRY_UNWRAP:
TODO
case EXPR_TRY_UNWRAP_CHAIN:
TODO
case EXPR_TRY_ASSIGN:
return recursive_may_narrow_float(expr->try_assign_expr.expr, type);
case EXPR_UNARY:
{
switch (expr->unary_expr.operator)
@@ -959,12 +1001,8 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type)
if (expr->or_error_expr.is_jump) return NULL;
return recursive_may_narrow_int(expr->or_error_expr.or_error_expr, type);
}
case EXPR_FORCE_UNWRAP:
return recursive_may_narrow_int(expr->force_unwrap_expr, type);
case EXPR_EXPRESSION_LIST:
return recursive_may_narrow_int(VECLAST(expr->expression_list), type);
case EXPR_GROUP:
return recursive_may_narrow_int(expr->group_expr, type);
case EXPR_RETHROW:
return recursive_may_narrow_int(expr->rethrow_expr.inner, type);
case EXPR_TERNARY:
@@ -1001,7 +1039,6 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type)
case EXPR_PLACEHOLDER:
case EXPR_TYPEID:
case EXPR_TYPEINFO:
case EXPR_TYPEOF:
case EXPR_UNDEF:
case EXPR_CT_CALL:
case EXPR_NOP:
@@ -1011,14 +1048,14 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type)
case EXPR_SCOPED_EXPR:
return recursive_may_narrow_int(expr->expr_scope.expr, type);
case EXPR_TRY:
assert(expr->try_expr.is_try);
return recursive_may_narrow_int(expr->try_expr.expr, type);
case EXPR_CATCH:
case EXPR_GROUP:
case EXPR_FORCE_UNWRAP:
return recursive_may_narrow_int(expr->inner_expr, type);
case EXPR_TRY_UNWRAP:
TODO
case EXPR_TRY_UNWRAP_CHAIN:
TODO
case EXPR_TRY_ASSIGN:
return recursive_may_narrow_int(expr->try_assign_expr.expr, type);
case EXPR_UNARY:
{
switch (expr->unary_expr.operator)
@@ -1039,35 +1076,18 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type)
}
UNREACHABLE
}
bool cast_implicit_ignore_failable(Expr *expr, Type *to_type)
{
if (expr->type->type_kind == TYPE_FAILABLE && to_type->type_kind != TYPE_FAILABLE)
{
to_type = type_get_failable(to_type);
}
return cast_implicit(expr, to_type);
}
bool cast_implicit(Expr *expr, Type *to_type)
{
assert(!type_is_failable(to_type));
Type *expr_type = expr->type;
if (expr_type == type_anyfail)
{
if (to_type->type_kind != TYPE_FAILABLE)
{
SEMA_ERROR(expr, "Cannot cast %s to a non-failable type %s.", type_quoted_error_string(expr_type),
type_quoted_error_string(to_type));
return false;
}
expr->type = to_type;
return true;
}
Type *expr_canonical = expr_type->canonical;
Type *to_canonical = to_type->canonical;
if (expr_canonical == to_canonical) return true;
if (!cast_may_implicit(expr_canonical, to_canonical))
bool is_simple = expr_is_simple(expr);
if (!cast_may_implicit(expr_canonical, to_canonical, is_simple, true))
{
if (!cast_may_explicit(expr_canonical, to_canonical, false))
if (!cast_may_explicit(expr_canonical, to_canonical, false, expr->expr_kind == EXPR_CONST))
{
if (expr_canonical->type_kind == TYPE_FAILABLE && to_canonical->type_kind != TYPE_FAILABLE)
{
@@ -1077,7 +1097,8 @@ bool cast_implicit(Expr *expr, Type *to_type)
SEMA_ERROR(expr, "You cannot cast %s into %s even with an explicit cast, so this looks like an error.", type_quoted_error_string(expr->type), type_quoted_error_string(to_type));
return false;
}
if (expr->expr_kind == EXPR_CONST && expr->const_expr.narrowable)
bool is_narrowing = type_size(expr_canonical) >= type_size(to_canonical);
if (expr->expr_kind == EXPR_CONST && expr->const_expr.narrowable && is_narrowing)
{
Type *expr_flatten = type_flatten_distinct(expr_canonical);
Type *to_flatten = type_flatten_distinct(to_canonical);
@@ -1104,9 +1125,8 @@ bool cast_implicit(Expr *expr, Type *to_type)
goto OK;
}
}
if (type_is_integer(expr_canonical) && type_is_integer(to_canonical))
if (type_is_integer(expr_canonical) && type_is_integer(to_canonical) && is_narrowing)
{
assert(type_size(expr_canonical) > type_size(to_canonical));
Expr *problem = recursive_may_narrow_int(expr, to_canonical);
if (problem)
{
@@ -1116,7 +1136,7 @@ bool cast_implicit(Expr *expr, Type *to_type)
}
goto OK;
}
if (type_is_float(expr_canonical) && type_is_float(to_canonical))
if (type_is_float(expr_canonical) && type_is_float(to_canonical) && is_narrowing)
{
Expr *problem = recursive_may_narrow_float(expr, to_canonical);
if (problem)
@@ -1221,39 +1241,24 @@ static inline bool subarray_to_bool(Expr *expr)
return insert_cast(expr, CAST_SABOOL, type_bool);
}
bool cast(Expr *expr, Type *to_type)
static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type, bool from_is_failable)
{
Type *from_type = type_flatten_distinct(expr->type->canonical);
bool from_is_failable = false;
if (from_type->type_kind == TYPE_FAILABLE)
{
from_type = from_type->failable;
from_is_failable = true;
}
Type *to = type_flatten(to_type);
if (from_type == to)
{
if (!from_is_failable && to_type->type_kind == TYPE_FAILABLE)
{
to_type = type_no_fail(to_type);
}
expr->type = to_type;
if (expr->expr_kind == EXPR_CONST) expr->const_expr.narrowable = false;
return true;
}
switch (from_type->type_kind)
{
case TYPE_FAILABLE_ANY:
UNREACHABLE
case TYPE_VOID:
UNREACHABLE
case TYPE_TYPEID:
case TYPE_DISTINCT:
case TYPE_FUNC:
case TYPE_TYPEDEF:
case CT_TYPES:
case TYPE_FAILABLE:
UNREACHABLE
case TYPE_BITSTRUCT:
UNREACHABLE
case TYPE_FAILABLE:
TODO
case TYPE_BOOL:
// Bool may convert into integers and floats but only explicitly.
if (type_is_integer(to)) return bool_to_int(expr, to, to_type);
@@ -1303,7 +1308,7 @@ bool cast(Expr *expr, Type *to_type)
case TYPE_ERRTYPE:
if (to->type_kind == TYPE_ANYERR) return err_to_anyerr(expr, to_type);
if (to == type_bool) return err_to_bool(expr, to_type);
if (type_is_integer(to_type)) return insert_cast(expr, CAST_ERINT, to_type);
if (type_is_integer(to)) return insert_cast(expr, CAST_ERINT, to_type);
break;
case TYPE_STRUCT:
case TYPE_UNION:
@@ -1327,5 +1332,49 @@ bool cast(Expr *expr, Type *to_type)
}
UNREACHABLE
}
bool cast(Expr *expr, Type *to_type)
{
assert(!type_is_failable(to_type));
Type *from_type = expr->type;
bool from_is_failable = false;
Type *to = type_flatten(to_type);
// Special case *! => error
if (to == type_anyerr || to->type_kind == TYPE_ERRTYPE)
{
if (type_is_failable(from_type)) return voidfail_to_error(expr, to, to_type);
}
if (type_is_failable_any(from_type))
{
expr->type = type_get_failable(to_type);
return true;
}
if (type_is_failable_type(from_type))
{
from_type = from_type->failable;
from_is_failable = true;
}
from_type = type_flatten_distinct(from_type);
if (to_type->type_kind == TYPE_INFERRED_ARRAY)
{
to_type = from_type;
to = type_flatten(from_type);
}
if (from_type == to)
{
expr->type = type_get_opt_fail(to_type, from_is_failable);
if (expr->expr_kind == EXPR_CONST) expr->const_expr.narrowable = false;
return true;
}
if (!cast_inner(expr, from_type, to, to_type, from_is_failable)) return false;
Type *result_type = expr->type;
if (from_is_failable && !type_is_failable(result_type))
{
expr->type = type_get_failable(result_type);
}
return true;
}
#pragma clang diagnostic pop

View File

@@ -480,10 +480,8 @@ static inline bool sema_analyse_function_param(Context *context, Decl *param, bo
SEMA_ERROR(param, "Only typed parameters are allowed for functions.");
return false;
}
if (!sema_resolve_type_info(context, param->var.type_info))
{
return false;
}
if (!sema_resolve_type_info(context, param->var.type_info)) return false;
if (param->var.vararg)
{
param->var.type_info->type = type_get_subarray(param->var.type_info->type);
@@ -497,10 +495,14 @@ static inline bool sema_analyse_function_param(Context *context, Decl *param, bo
if (param->var.init_expr)
{
Expr *expr = param->var.init_expr;
if (!sema_analyse_assigned_expr(context, param->type, expr, false)) return false;
Expr *inner = expr;
while (inner->expr_kind == EXPR_CAST) inner = expr->cast_expr.expr;
if (inner->expr_kind != EXPR_CONST)
if (!sema_analyse_expr_rhs(context, param->type, expr, true)) return false;
if (IS_FAILABLE(expr))
{
SEMA_ERROR(expr, "Default arguments may not be failable.");
return false;
}
if (!expr_is_constant_eval(expr, CONSTANT_EVAL_ANY))
{
SEMA_ERROR(expr, "Only constant expressions may be used as default values.");
return false;
@@ -593,6 +595,7 @@ static inline bool sema_analyse_distinct(Context *context, Decl *decl)
case CT_TYPES:
UNREACHABLE
return false;
case TYPE_FAILABLE_ANY:
case TYPE_FAILABLE:
SEMA_ERROR(decl, "You cannot create a distinct type from a failable.");
return false;
@@ -676,7 +679,7 @@ static inline bool sema_analyse_enum(Context *context, Decl *decl)
}
// We try to convert to the desired type.
if (!sema_analyse_expr_of_required_type(context, type, expr))
if (!sema_analyse_expr_rhs(context, type, expr, false))
{
success = false;
enum_value->resolve_status = RESOLVE_DONE;
@@ -988,28 +991,7 @@ static inline bool sema_update_call_convention(Decl *decl, CallABI abi)
static inline bool sema_analyse_func(Context *context, Decl *decl)
{
DEBUG_LOG("----Analysing function %s", decl->name);
Type *func_type = sema_analyse_function_signature(context, &decl->func_decl.function_signature, true);
decl->type = func_type;
if (!func_type) return decl_poison(decl);
if (decl->func_decl.type_parent)
{
if (!sema_analyse_method(context, decl)) return decl_poison(decl);
}
else
{
if (decl->name == kw_main)
{
if (decl->visibility == VISIBLE_LOCAL)
{
SEMA_ERROR(decl, "'main' cannot have local visibility.");
return false;
}
decl->visibility = VISIBLE_EXTERN;
}
decl_set_external_name(decl);
}
if (!sema_analyse_doc_header(decl->docs, decl->func_decl.function_signature.params, NULL)) return decl_poison(decl);
VECEACH(decl->attributes, i)
{
Attr *attr = decl->attributes[i];
@@ -1067,14 +1049,14 @@ static inline bool sema_analyse_func(Context *context, Decl *decl)
}
break;
case ATTRIBUTE_FASTCALL:
if (platform_target.arch == ARCH_TYPE_X86)
if (platform_target.arch == ARCH_TYPE_X86 || (platform_target.arch == ARCH_TYPE_X86_64 && platform_target.os == OS_TYPE_WIN32))
{
had = sema_update_call_convention(decl, CALL_X86_FAST);
}
break;
case ATTRIBUTE_REGCALL:
had = decl->func_decl.function_signature.call_abi > 0;
if (platform_target.arch == ARCH_TYPE_X86)
if (platform_target.arch == ARCH_TYPE_X86 || (platform_target.arch == ARCH_TYPE_X86_64 && platform_target.os == OS_TYPE_WIN32))
{
had = sema_update_call_convention(decl, CALL_X86_REG);
}
@@ -1098,6 +1080,29 @@ static inline bool sema_analyse_func(Context *context, Decl *decl)
return decl_poison(decl);
}
}
Type *func_type = sema_analyse_function_signature(context, &decl->func_decl.function_signature, true);
decl->type = func_type;
if (!func_type) return decl_poison(decl);
if (decl->func_decl.type_parent)
{
if (!sema_analyse_method(context, decl)) return decl_poison(decl);
}
else
{
if (decl->name == kw_main)
{
if (decl->visibility == VISIBLE_LOCAL)
{
SEMA_ERROR(decl, "'main' cannot have local visibility.");
return false;
}
decl->visibility = VISIBLE_EXTERN;
}
decl_set_external_name(decl);
}
if (!sema_analyse_doc_header(decl->docs, decl->func_decl.function_signature.params, NULL)) return decl_poison(decl);
DEBUG_LOG("Function analysis done.");
return true;
}
@@ -1287,10 +1292,27 @@ bool sema_analyse_attributes_for_var(Context *context, Decl *decl)
return true;
}
bool sema_analyse_decl_type(Context *context, Type *type, SourceSpan span)
{
if (type == type_void)
{
sema_error_range(span, "The use of 'void' as a variable type is not permitted.");
return false;
}
if (!type_is_failable(type)) return true;
if (type_is_failable_any(type) || type_flatten_distinct(type->failable) == type_void)
{
sema_error_range(span, "The use of 'void!' as a variable type is not permitted, use %s instead.",
type_quoted_error_string(type_anyerr));
return false;
}
return true;
}
/**
* Analyse a regular global or local declaration, e.g. int x = 123
*/
bool sema_analyse_var_decl(Context *context, Decl *decl)
bool sema_analyse_var_decl(Context *context, Decl *decl, bool local)
{
assert(decl->decl_kind == DECL_VAR && "Unexpected declaration type");
@@ -1298,7 +1320,7 @@ bool sema_analyse_var_decl(Context *context, Decl *decl)
// this should always be true.
assert(decl->var.type_info || decl->var.kind == VARDECL_CONST);
bool is_global = decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST;
bool is_global = decl->var.kind == VARDECL_GLOBAL || !local;
if (!sema_analyse_attributes_for_var(context, decl)) return false;
@@ -1333,15 +1355,16 @@ bool sema_analyse_var_decl(Context *context, Decl *decl)
if (!sema_analyse_expr(context, init_expr)) return false;
decl->type = init_expr->type;
if (!decl->alignment) decl->alignment = type_alloca_alignment(decl->type);
if (!sema_analyse_decl_type(context, decl->type, init_expr->span)) return false;
// Skip further evaluation.
goto EXIT_OK;
}
}
if (!sema_resolve_type_info_maybe_inferred(context, decl->var.type_info, decl->var.init_expr != NULL)) return decl_poison(decl);
decl->type = decl->var.type_info->type;
decl->type = decl->var.type_info->type;
if (!sema_analyse_decl_type(context, decl->type, decl->var.type_info->span)) return false;
if (decl->var.is_static)
{
scratch_buffer_clear();
@@ -1381,16 +1404,9 @@ bool sema_analyse_var_decl(Context *context, Decl *decl)
assert(right_side_type->type_kind == TYPE_ARRAY);
decl->type = type_get_array(decl->type->array.base, right_side_type->array.len);
}
else if (decl->type)
{
decl->var.init_expr->type = decl->type;
}
Expr *init_expr = decl->var.init_expr;
// 1. Check type.
if (!sema_analyse_assigned_expr(context, decl->type, init_expr, false)) return false;
// 2. Check const-ness
if ((is_global || decl->var.is_static) && !expr_is_constant_eval(init_expr, CONSTANT_EVAL_ANY))
{
@@ -1398,7 +1414,7 @@ bool sema_analyse_var_decl(Context *context, Decl *decl)
}
else
{
if (decl->var.unwrap && init->type->type_kind != TYPE_FAILABLE)
if (decl->var.unwrap && IS_FAILABLE(init))
{
SEMA_ERROR(decl->var.init_expr, "A failable expression was expected here.");
return decl_poison(decl);
@@ -1534,13 +1550,6 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl)
UNREACHABLE
}
}
static void decl_define_type(Decl *decl, Type *actual_type)
{
Type *type = type_new(TYPE_TYPEDEF, decl->name);
type->decl = decl;
type->canonical = actual_type->canonical;
decl->type = type;
}
static inline bool sema_analyse_define(Context *c, Decl *decl)
{
@@ -1599,7 +1608,7 @@ bool sema_analyse_decl(Context *context, Decl *decl)
if (!sema_analyse_macro(context, decl)) return decl_poison(decl);
break;
case DECL_VAR:
if (!sema_analyse_var_decl(context, decl)) return decl_poison(decl);
if (!sema_analyse_var_decl(context, decl, false)) return decl_poison(decl);
decl_set_external_name(decl);
break;
case DECL_DISTINCT:

View File

@@ -150,6 +150,7 @@ bool expr_cast_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
{
switch (expr->cast_expr.kind)
{
case CAST_VFTOERR:
case CAST_ERROR:
return false;
case CAST_ERBOOL:
@@ -267,7 +268,6 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
case EXPR_MACRO_BODY_EXPANSION:
case EXPR_TRY_UNWRAP:
case EXPR_TRY_UNWRAP_CHAIN:
case EXPR_TRY_ASSIGN:
case EXPR_POST_UNARY:
case EXPR_SCOPED_EXPR:
case EXPR_SLICE_ASSIGN:
@@ -279,10 +279,8 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
case EXPR_EXPRESSION_LIST:
return expr_list_is_constant_eval(expr->expression_list, eval_kind);
case EXPR_FAILABLE:
expr = expr->failable_expr;
goto RETRY;
case EXPR_GROUP:
expr = expr->group_expr;
expr = expr->inner_expr;
goto RETRY;
case EXPR_INITIALIZER_LIST:
return expr_list_is_constant_eval(expr->initializer_list, eval_kind);
@@ -303,10 +301,9 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
assert(!expr_is_constant_eval(expr->ternary_expr.cond, eval_kind));
return false;
case EXPR_FORCE_UNWRAP:
expr = expr->force_unwrap_expr;
goto RETRY;
case EXPR_TRY:
expr = expr->try_expr.expr;
case EXPR_CATCH:
expr = expr->inner_expr;
goto RETRY;
case EXPR_TYPEID:
return eval_kind == CONSTANT_EVAL_ANY;
@@ -330,7 +327,6 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
}
UNREACHABLE
case EXPR_CT_CALL:
case EXPR_TYPEOF:
case EXPR_TYPEINFO:
case EXPR_HASH_IDENT:
case EXPR_CT_IDENT:
@@ -404,7 +400,7 @@ static inline Ast **context_push_returns(Context *context)
int sema_check_comp_time_bool(Context *context, Expr *expr)
{
if (!sema_analyse_assigned_expr(context, type_bool, expr, false)) return -1;
if (!sema_analyse_cond_expr(context, expr)) return -1;
if (expr->expr_kind != EXPR_CONST)
{
SEMA_ERROR(expr, "Compile time evaluation requires a compile time constant value.");
@@ -452,7 +448,7 @@ bool expr_is_ltype(Expr *expr)
case EXPR_ACCESS:
return expr_is_ltype(expr->access_expr.parent);
case EXPR_GROUP:
return expr_is_ltype(expr->group_expr);
return expr_is_ltype(expr->inner_expr);
case EXPR_SUBSCRIPT:
case EXPR_SLICE:
return true;
@@ -465,7 +461,6 @@ static inline bool sema_cast_ident_rvalue(Context *context, Expr *expr)
{
Decl *decl = expr->identifier_expr.decl;
decl = decl_flatten(decl);
expr->identifier_expr.is_rvalue = true;
switch (decl->decl_kind)
{
@@ -614,8 +609,7 @@ static inline bool sema_expr_analyse_ternary(Context *context, Expr *expr)
// Normal
if (left)
{
if (!sema_analyse_expr(context, cond)) return expr_poison(expr);
if (!cast_implicit(cond, type_bool)) return expr_poison(expr);
if (!sema_analyse_cond_expr(context, cond)) return expr_poison(expr);
if (!sema_analyse_expr(context, left)) return expr_poison(expr);
if (cond->expr_kind == EXPR_CONST)
{
@@ -656,7 +650,8 @@ static inline bool sema_expr_analyse_ternary(Context *context, Expr *expr)
type_to_error_string(left_canonical), type_to_error_string(right_canonical));
return false;
}
if (!cast_implicit(left, max) || !cast_implicit(right, max)) return false;
Type *no_fail_max = type_no_fail(max);
if (!cast_implicit(left, no_fail_max) || !cast_implicit(right, max)) return false;
}
if (path > -1)
@@ -879,7 +874,35 @@ static inline bool sema_expr_analyse_hash_identifier(Context *context, Expr *exp
return sema_analyse_expr(context, expr);
}
static inline bool sema_expr_analyse_binary_subexpr(Context *context, Expr *left, Expr *right)
static inline bool sema_widen_top_down(Expr *expr, Type *type)
{
Type *to = type;
Type *from = expr->type;
RETRY:
if (type_is_integer(from) && type_is_integer(to)) goto CONVERT_IF_BIGGER;
if (type_is_float(from) && type_is_float(to)) goto CONVERT_IF_BIGGER;
if (type_is_integer(from) && type_is_float(to)) goto CONVERT;
if (type_is_vector(from) && type_is_vector(to))
{
to = type_vector_type(to);
from = type_vector_type(from);
goto RETRY;
}
return true;
CONVERT_IF_BIGGER:
if (type_size(to) <= type_size(from)) return true;
CONVERT:
return cast_implicit(expr, type);
}
static inline bool sema_promote_binary_top_down(Context *context, Expr *binary, Expr *left, Expr *right)
{
if (!binary->binary_expr.widen) return true;
Type *to = binary->type;
return sema_widen_top_down(left, to) && sema_widen_top_down(right, to);
}
static inline bool sema_expr_analyse_binary_subexpr(Context *context, Expr *binary, Expr *left, Expr *right)
{
return (int)sema_analyse_expr(context, left) & (int)sema_analyse_expr(context, right);
}
@@ -890,7 +913,9 @@ static inline bool sema_expr_analyse_binary_arithmetic_subexpr(Context *context,
Expr *right = expr->binary_expr.right;
// 1. Analyse both sides.
if (!sema_expr_analyse_binary_subexpr(context, left, right)) return false;
if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false;
if (!sema_promote_binary_top_down(context, expr, left, right)) return false;
Type *left_type = type_no_fail(left->type)->canonical;
Type *right_type = type_no_fail(right->type)->canonical;
@@ -1054,6 +1079,7 @@ static inline bool sema_check_invalid_body_arguments(Context *context, Expr *cal
return true;
}
static inline bool sema_expand_call_arguments(Context *context, CalledDecl *callee, Expr *call, Decl **params, Expr **args, unsigned func_param_count, bool variadic, bool *failable)
{
unsigned num_args = vec_size(args);
@@ -1262,7 +1288,7 @@ static inline bool sema_expr_analyse_call_invocation(Context *context, Expr *cal
else
{
// 11e. A simple variadic value:
if (!sema_analyse_assigned_expr(context, variadic_type, arg, true)) return false;
if (!sema_analyse_expr_rhs(context, variadic_type, arg, true)) return false;
}
// Set the argument at the location.
*failable |= IS_FAILABLE(arg);
@@ -1304,7 +1330,7 @@ static inline bool sema_expr_analyse_call_invocation(Context *context, Expr *cal
break;
case VARDECL_PARAM:
// foo
if (!sema_analyse_assigned_expr(context, param->type, arg, true)) return false;
if (!sema_analyse_expr_rhs(context, param->type, arg, true)) return false;
if (IS_FAILABLE(arg)) *failable = true;
if (callee.macro)
{
@@ -1317,14 +1343,14 @@ static inline bool sema_expr_analyse_call_invocation(Context *context, Expr *cal
// compile time variables during evaluation:
assert(callee.macro);
SCOPE_START
if (!sema_analyse_assigned_expr(context, param->type, arg, true)) return SCOPE_POP_ERROR();
if (!sema_analyse_expr_rhs(context, param->type, arg, true)) return SCOPE_POP_ERROR();
SCOPE_END;
if (IS_FAILABLE(arg)) *failable = true;
break;
case VARDECL_PARAM_CT:
// $foo
assert(callee.macro);
if (!sema_analyse_assigned_expr(context, param->type, arg, false)) return false;
if (!sema_analyse_expr_rhs(context, param->type, arg, true)) return false;
if (!expr_is_constant_eval(arg, CONSTANT_EVAL_ANY))
{
SEMA_ERROR(arg, "A compile time parameter must always be a constant, did you mistake it for a normal paramter?");
@@ -1448,7 +1474,7 @@ static inline Type *unify_returns(Context *context)
Ast *return_stmt = context->returns[i];
Expr *ret_expr = return_stmt->return_stmt.expr;
// 8. All casts should work.
if (!cast_implicit(ret_expr, common_type))
if (!cast_implicit(ret_expr, type_no_fail(common_type)))
{
assert(false);
return NULL;
@@ -1648,14 +1674,14 @@ static bool sema_expr_analyse_macro_call(Context *context, Expr *call_expr, Expr
goto EXIT;
}
Type *type = ret_expr->type;
if (!cast_may_implicit(type, rtype))
if (!cast_may_implicit(type, rtype, true, true))
{
SEMA_ERROR(ret_expr, "Expected %s, not %s.", type_quoted_error_string(rtype),
type_quoted_error_string(type));
ok = false;
goto EXIT;
}
bool success = cast_implicit_ignore_failable(ret_expr, rtype);
bool success = cast_implicit(ret_expr, rtype);
assert(success);
}
call_expr->type = type_get_opt_fail(rtype, failable);
@@ -1749,7 +1775,7 @@ static inline bool sema_expr_analyse_generic_call(Context *context, Expr *call_e
}
if (param->var.type_info)
{
if (!sema_analyse_assigned_expr(context, param->var.type_info->type, arg, true)) return false;
if (!sema_analyse_expr_rhs(context, param->var.type_info->type, arg, true)) return false;
}
else
{
@@ -2234,8 +2260,8 @@ static inline bool sema_expr_analyse_slice(Context *context, Expr *expr)
static inline bool sema_expr_analyse_group(Context *context, Expr *expr)
{
if (!sema_analyse_expr(context, expr->group_expr)) return false;
*expr = *expr->group_expr;
if (!sema_analyse_expr(context, expr->inner_expr)) return false;
*expr = *expr->inner_expr;
return true;
}
@@ -3162,8 +3188,9 @@ static bool sema_expr_analyse_designated_initializer(Context *context, Type *ass
Expr *expr = init_expressions[i];
Type *result = sema_expr_analyse_designator(context, original, expr, &max_index);
if (!result) return false;
if (!sema_analyse_assigned_expr(context, result, expr->designator_expr.value, true)) return false;
failable = failable || IS_FAILABLE(expr->designator_expr.value);
Expr *value = expr->designator_expr.value;
if (!sema_analyse_expr_rhs(context, result, value, true)) return false;
failable = failable || IS_FAILABLE(value);
expr->resolve_status = RESOLVE_DONE;
}
@@ -3222,7 +3249,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(Context *context,
return false;
}
// 5. We know the required type, so resolve the expression.
if (!sema_analyse_assigned_expr(context, members[i]->type, elements[i], true)) return false;
if (!sema_analyse_expr_rhs(context, members[i]->type, element, true)) return false;
failable = failable || IS_FAILABLE(element);
}
assert(initializer->type);
@@ -3294,7 +3321,8 @@ static inline bool sema_expr_analyse_array_plain_initializer(Context *context, T
SEMA_ERROR(element, "Too many elements in initializer, expected only %d.", expected_members);
return false;
}
if (!sema_analyse_assigned_expr(context, inner_type, element, true)) return false;
if (!sema_analyse_expr_rhs(context, inner_type, element, true)) return false;
failable = failable || IS_FAILABLE(element);
}
assert(initializer->type);
@@ -3483,18 +3511,16 @@ static inline bool sema_expr_analyse_cast(Context *context, Expr *expr)
if (!sema_analyse_expr(context, inner) || !success) return false;
Type *target_type = expr->cast_expr.type_info->type;
Type *inner_no_fail = type_no_fail(inner->type);
if (!cast_may_explicit(inner_no_fail, target_type, false))
if (type_is_failable(target_type))
{
if (inner->expr_kind == EXPR_CONST && type_is_integer(inner_no_fail->canonical) && target_type->canonical->type_kind == TYPE_POINTER)
{
goto OK;
}
SEMA_ERROR(expr, "Cannot cast %s to %s.", type_quoted_error_string(inner->type), type_quoted_error_string(target_type));
SEMA_ERROR(expr->cast_expr.type_info, "Casting to a failable type is not allowed.");
return false;
}
OK:
cast(inner, type_get_opt_fail(target_type, IS_FAILABLE(inner)));
if (!cast_may_explicit(inner->type, target_type, true, inner->expr_kind == EXPR_CONST))
{
return sema_failed_cast(expr, type_no_fail(inner->type), target_type);
}
cast(inner, target_type);
expr_replace(expr, inner);
return true;
}
@@ -3502,8 +3528,7 @@ static inline bool sema_expr_analyse_cast(Context *context, Expr *expr)
static inline bool sema_expr_analyse_slice_assign(Context *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped)
{
// 1. Evaluate right side to required type.
Type *left_no_fail = type_no_fail(left_type);
if (!sema_analyse_assigned_expr(context, left_no_fail->array.base, right, TYPE_IS_FAILABLE(left_type))) return false;
if (!sema_analyse_expr_rhs(context, left_type->array.base, right, false)) return false;
Expr *left = expr->binary_expr.left;
expr->type = right->type;
@@ -3522,9 +3547,8 @@ bool sema_expr_analyse_assign_right_side(Context *context, Expr *expr, Type *lef
}
// 1. Evaluate right side to required type.
Type *no_fail_left_type = type_no_fail(left_type);
if (!sema_analyse_inferred_expr(context, no_fail_left_type, right)) return false;
if (IS_FAILABLE(right) && !TYPE_IS_FAILABLE(left_type))
if (!sema_analyse_expr_rhs(context, left_type, right, true)) return false;
if (IS_FAILABLE(right) && !type_is_failable(left_type))
{
if (is_unwrapped)
{
@@ -3532,21 +3556,9 @@ bool sema_expr_analyse_assign_right_side(Context *context, Expr *expr, Type *lef
return false;
}
if (!left_type) left_type = type_no_fail(right->type);
SEMA_ERROR(right, "%s cannot be converted to %s.", type_quoted_error_string(right->type), type_quoted_error_string(left_type));
return false;
return sema_failed_cast(right, right->type, left_type);
}
Type *right_type = type_no_fail(right->type)->canonical;
// 2. Evaluate right hand side, making special concession for inferred arrays.
if (!no_fail_left_type) goto DONE;
if (no_fail_left_type->canonical->type_kind == TYPE_INFERRED_ARRAY && right_type->type_kind == TYPE_ARRAY)
{
if (no_fail_left_type->canonical->array.base == right_type->array.base) goto DONE;
}
if (!cast_implicit_ignore_failable(right, no_fail_left_type)) return false;
DONE:
// 3. Set the result to the type on the right side.
if (expr) expr->type = right->type;
@@ -3763,8 +3775,13 @@ static bool sema_expr_analyse_common_assign(Context *context, Expr *expr, Expr *
}
// 5. Cast the right hand side to the one on the left
if (!sema_analyse_assigned_expr(context, no_fail, right, IS_FAILABLE(left))) return false;
if (!sema_analyse_expr(context, right)) return false;
if (!cast_implicit(right, no_fail)) return false;
if (IS_FAILABLE(right) && !IS_FAILABLE(left))
{
SEMA_ERROR(right, "This expression cannot be failable, since the assigned variable isn't.");
return false;
}
// 6. Check for zero in case of div or mod.
if (right->expr_kind == EXPR_CONST)
{
@@ -3841,6 +3858,11 @@ static bool sema_expr_analyse_add_sub_assign(Context *context, Expr *expr, Expr
if (!sema_analyse_expr(context, right)) return false;
// 3. Copy type & set properties.
if (IS_FAILABLE(right) && !IS_FAILABLE(left))
{
SEMA_ERROR(right, "Cannot assign a failable value to a non-failable.");
return false;
}
expr->type = left->type;
bool failable = IS_FAILABLE(left) || IS_FAILABLE(right);
@@ -3907,20 +3929,7 @@ static bool binary_arithmetic_promotion(Context *context, Expr *left, Expr *righ
SEMA_ERROR(parent, error_message, type_quoted_error_string(left->type), type_quoted_error_string(right->type));
return false;
}
return cast_implicit_ignore_failable(left, max) && cast_implicit_ignore_failable(right, max);
}
static bool sema_check_int_type_fit(Expr *expr, Type *target_type)
{
if (!target_type) return true;
Type *type = expr->type->canonical;
if (!type_is_integer(target_type->canonical) || !type_is_integer(type)) return true;
if (type_size(type) > type_size(target_type))
{
SEMA_ERROR(expr, "A '%s' cannot implicitly convert into '%s'.", type_to_error_string(expr->type), type_to_error_string(target_type));
return false;
}
return true;
return cast_implicit(left, max) && cast_implicit(right, max);
}
static void unify_voidptr(Expr *left, Expr *right, Type **left_type_ref, Type **right_type_ref)
@@ -3945,7 +3954,7 @@ static Type *defer_iptr_cast(Expr *maybe_pointer, Expr *maybe_diff)
if (maybe_pointer->expr_kind == EXPR_CAST
&& maybe_pointer->cast_expr.kind == CAST_PTRXI
&& type_flatten(maybe_pointer->type) == type_flatten(type_iptr)
&& cast_may_implicit(maybe_diff->type, maybe_diff->type))
&& cast_may_implicit(maybe_diff->type, maybe_diff->type, true, true))
{
Type *cast_to_iptr = maybe_pointer->type;
maybe_pointer->cast_expr.kind = CAST_PTRPTR;
@@ -3962,7 +3971,7 @@ static Type *defer_iptr_cast(Expr *maybe_pointer, Expr *maybe_diff)
static bool sema_expr_analyse_sub(Context *context, Expr *expr, Expr *left, Expr *right)
{
// 1. Analyse a and b.
if (!sema_expr_analyse_binary_subexpr(context, left, right)) return false;
if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false;
// Do we have (iptr)(ptr) - rhs? If so we change it to
// (iptr)((char*)(ptr) - 1)
@@ -4020,6 +4029,11 @@ static bool sema_expr_analyse_sub(Context *context, Expr *expr, Expr *left, Expr
return true;
}
if (!sema_promote_binary_top_down(context, expr, left, right)) return false;
left_type = type_no_fail(left->type)->canonical;
right_type = type_no_fail(right->type)->canonical;
// 7. Attempt arithmetic promotion, to promote both to a common type.
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type, expr, "The subtraction %s - %s is not possible."))
{
@@ -4059,7 +4073,7 @@ static bool sema_expr_analyse_add(Context *context, Expr *expr, Expr *left, Expr
{
// 1. Promote everything to the recipient type if possible
// this is safe in the pointer case actually.
if (!sema_expr_analyse_binary_subexpr(context, left, right)) return false;
if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false;
Type *cast_to_iptr = defer_iptr_cast(left, right);
if (!cast_to_iptr) cast_to_iptr = defer_iptr_cast(right, left);
@@ -4111,6 +4125,11 @@ static bool sema_expr_analyse_add(Context *context, Expr *expr, Expr *left, Expr
return true;
}
if (!sema_promote_binary_top_down(context, expr, left, right)) return false;
left_type = type_no_fail(left->type)->canonical;
right_type = type_no_fail(right->type)->canonical;
assert(!cast_to_iptr);
// 4. Do an binary arithmetic promotion
if (!binary_arithmetic_promotion(context, left, right, left_type, right_type, expr, "Cannot do the addition %s + %s."))
@@ -4156,6 +4175,7 @@ static bool sema_expr_analyse_mult(Context *context, Expr *expr, Expr *left, Exp
// 1. Analyse the sub expressions and promote to a common type
if (!sema_expr_analyse_binary_arithmetic_subexpr(context, expr, "It is not possible to multiply %s by %s.")) return false;
// 2. Handle constant folding.
if (expr_both_const(left, right))
{
@@ -4306,7 +4326,7 @@ static bool sema_expr_analyse_bit(Context *context, Expr *expr, Expr *left, Expr
static bool sema_expr_analyse_shift(Context *context, Expr *expr, Expr *left, Expr *right)
{
// 1. Analyze both sides.
if (!sema_expr_analyse_binary_subexpr(context, left, right)) return false;
if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false;
// 2. Only integers or integer vectors may be shifted.
if (!both_any_integer_or_integer_vector(left, right))
@@ -4314,8 +4334,10 @@ static bool sema_expr_analyse_shift(Context *context, Expr *expr, Expr *left, Ex
return sema_type_error_on_binop(expr);
}
if (expr->binary_expr.widen && !sema_widen_top_down(left, expr->type)) return false;
// 3. Promote lhs using the usual numeric promotion.
if (!cast_implicit_ignore_failable(left, numeric_arithmetic_promotion(type_no_fail(left->type)))) return false;
if (!cast_implicit(left, numeric_arithmetic_promotion(type_no_fail(left->type)))) return false;
// 4. For a constant rhs side we will make a series of checks.
if (IS_CONST(right))
@@ -4366,7 +4388,7 @@ static bool sema_expr_analyse_shift_assign(Context *context, Expr *expr, Expr *l
{
// 1. Analyze the two sub lhs & rhs *without coercion*
if (!sema_expr_analyse_binary_subexpr(context, left, right)) return false;
if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false;
bool failable = IS_FAILABLE(left) || IS_FAILABLE(right);
@@ -4408,7 +4430,7 @@ static bool sema_expr_analyse_shift_assign(Context *context, Expr *expr, Expr *l
static bool sema_expr_analyse_and_or(Context *context, Expr *expr, Expr *left, Expr *right)
{
if (!sema_expr_analyse_binary_subexpr(context, left, right)) return false;
if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false;
if (!cast_implicit(left, type_bool) || !cast_implicit(right, type_bool)) return false;
if (expr_both_const(left, right))
@@ -4441,14 +4463,14 @@ static void cast_to_max_bit_size(Context *context, Expr *left, Expr *right, Type
Type *to = left->type->type_kind < TYPE_U8
? type_int_signed_by_bitsize(bit_size_right)
: type_int_unsigned_by_bitsize(bit_size_right);
bool success = cast_implicit_ignore_failable(left, to);
bool success = cast_implicit(left, to);
assert(success);
return;
}
Type *to = right->type->type_kind < TYPE_U8
? type_int_signed_by_bitsize(bit_size_left)
: type_int_unsigned_by_bitsize(bit_size_left);
bool success = cast_implicit_ignore_failable(right, to);
bool success = cast_implicit(right, to);
assert(success);
}
@@ -4510,7 +4532,7 @@ static bool sema_is_unsigned_always_false_comparison(Context *context, Expr *exp
static bool sema_expr_analyse_comp(Context *context, Expr *expr, Expr *left, Expr *right)
{
// 1. Analyse left and right side without any conversions.
if (!sema_expr_analyse_binary_subexpr(context, left, right)) return false;
if (!sema_expr_analyse_binary_subexpr(context, expr, left, right)) return false;
bool is_equality_type_op = expr->binary_expr.operator == BINARYOP_NE || expr->binary_expr.operator == BINARYOP_EQ;
@@ -4583,7 +4605,7 @@ static bool sema_expr_analyse_comp(Context *context, Expr *expr, Expr *left, Exp
}
// 6. Do the implicit cast.
bool success = cast_implicit_ignore_failable(left, max) && cast_implicit_ignore_failable(right, max);
bool success = cast_implicit(left, max) && cast_implicit(right, max);
assert(success);
DONE:
@@ -4745,7 +4767,7 @@ static bool sema_take_addr_of(Expr *inner)
case EXPR_ACCESS:
return sema_take_addr_of(inner->access_expr.parent);
case EXPR_GROUP:
return sema_take_addr_of(inner->group_expr);
return sema_take_addr_of(inner->inner_expr);
case EXPR_SUBSCRIPT:
return sema_take_addr_of(inner->subscript_expr.expr);
case EXPR_TYPEINFO:
@@ -4773,7 +4795,7 @@ static bool sema_expr_analyse_addr(Context *context, Expr *expr)
return false;
case EXPR_GROUP:
// We want to collapse any grouping here.
expr_replace(inner, inner->group_expr);
expr_replace(inner, inner->inner_expr);
goto REDO;
default:
{
@@ -4798,6 +4820,7 @@ static bool sema_expr_analyse_neg(Context *context, Expr *expr)
// 1. Check the inner expression
Expr *inner = expr->unary_expr.expr;
if (!sema_analyse_expr(context, inner)) return false;
if (expr->unary_expr.widen && !sema_widen_top_down(inner, expr->type)) return false;
// 2. Check if it's possible to negate this (i.e. is it an int, float or vector)
Type *no_fail = type_no_fail(inner->type);
@@ -4808,7 +4831,7 @@ static bool sema_expr_analyse_neg(Context *context, Expr *expr)
}
// 3. Promote the type
Type *result_type = numeric_arithmetic_promotion(no_fail);
if (!cast_implicit_ignore_failable(inner, result_type)) return false;
if (!cast_implicit(inner, result_type)) return false;
// 4. If it's non-const, we're done.
if (inner->expr_kind != EXPR_CONST)
@@ -4844,6 +4867,8 @@ static bool sema_expr_analyse_bit_not(Context *context, Expr *expr)
Expr *inner = expr->unary_expr.expr;
if (!sema_analyse_expr(context, inner)) return false;
if (expr->unary_expr.widen && !sema_widen_top_down(inner, expr->type)) return false;
// 2. Check that it's a vector, bool
Type *canonical = type_no_fail(inner->type)->canonical;
if (!type_is_integer_or_bool_kind(type_flatten_distinct(canonical)))
@@ -4895,7 +4920,7 @@ static bool sema_expr_analyse_not(Context *context, Expr *expr)
}
// 4. Let's see if it's possible to cast it implicitly
if (!cast_may_implicit(type, type_bool))
if (!cast_may_implicit(type, type_bool, true, true))
{
SEMA_ERROR(expr, "The use of '!' on %s is not allowed as it can't be converted to a boolean value.", type_quoted_error_string(inner->type));
return false;
@@ -5123,101 +5148,39 @@ static inline bool sema_expr_analyse_unary(Context *context, Expr *expr)
}
static inline bool sema_expr_analyse_try_assign(Context *context, Expr *expr, bool implicitly_create_variable)
{
Expr *init = expr->try_assign_expr.init;
Expr *lhs = expr->try_assign_expr.expr;
Type *lhs_type;
// If we have:
// a. In a context where implicit declaration of variables occur
// b. The LHS is an identifier without PATH
// c. And this variable does not exist in the scope.
// Create it (when we know the type)
bool create_variable;
if (implicitly_create_variable && lhs->expr_kind == EXPR_IDENTIFIER && !lhs->identifier_expr.path
&& !sema_resolve_normal_symbol(context, lhs->identifier_expr.identifier, NULL, false))
{
create_variable = true;
lhs_type = NULL;
}
else
{
// Otherwise we just analyse it.
create_variable = false;
if (expr->try_assign_expr.is_try)
{
if (!sema_analyse_expr_lvalue(context, lhs)) return false;
}
else
{
if (!sema_analyse_assigned_expr(context, type_anyerr, lhs, true)) return false;
}
if (!expr_is_ltype(lhs))
{
SEMA_ERROR(lhs, "This expression is not assignable, did you make a mistake?");
return false;
}
if (IS_FAILABLE(lhs))
{
SEMA_ERROR(lhs, "A 'try' assignment is not possible with failable on the left hand side, did you intend 'try (variable = expr)'?");
return false;
}
lhs_type = lhs->type;
}
lhs_type = type_no_fail(lhs_type);
if (expr->try_assign_expr.is_try)
{
if (!sema_analyse_assigned_expr(context, lhs_type, init, true)) return false;
}
else
{
if (!sema_analyse_assigned_expr(context, NULL, init, true)) return false;
}
if (!IS_FAILABLE(init))
{
SEMA_ERROR(init, "Expected a failable expression to '%s'.", expr->try_assign_expr.is_try ? "try" : "catch");
return false;
}
if (create_variable)
{
lhs_type = init->type;
Decl *decl = decl_new_var(lhs->identifier_expr.identifier, type_info_new_base(lhs_type, lhs->span), VARDECL_LOCAL, VISIBLE_LOCAL);
TODO
// try_expr->try_expr.implicit_decl = decl;
if (!sema_add_local(context, decl)) return false;
if (!sema_analyse_expr_lvalue(context, lhs)) return false;
}
expr->type = type_bool;
return true;
}
static inline bool sema_expr_analyse_try(Context *context, Expr *expr)
{
Expr *inner = expr->try_expr.expr;
Expr *inner = expr->inner_expr;
if (!sema_analyse_expr(context, inner)) return false;
if (!IS_FAILABLE(inner))
{
SEMA_ERROR(expr->try_expr.expr, "Expected a failable expression to '%s'.", expr->expr_kind == EXPR_TRY ? "try" : "catch");
SEMA_ERROR(inner, "Expected a failable expression to 'try'.");
return false;
}
expr->type = expr->try_expr.is_try ? type_bool : type_anyerr;
expr->type = type_bool;
return true;
}
static inline bool sema_expr_analyse_catch(Context *context, Expr *expr)
{
Expr *inner = expr->inner_expr;
if (!sema_analyse_expr(context, inner)) return false;
if (!IS_FAILABLE(inner))
{
SEMA_ERROR(inner, "Expected a failable expression to 'catch'.");
return false;
}
expr->type = type_anyerr;
return true;
}
static inline bool sema_expr_analyse_or_error(Context *context, Expr *expr)
{
Expr *inner = expr->or_error_expr.expr;
bool success = sema_analyse_expr(context, inner);
if (!sema_analyse_expr(context, inner)) return false;
if (expr->or_error_expr.widen && !sema_widen_top_down(inner, expr->type)) return false;
if (!success) return false;
Type *type = inner->type;
if (type->type_kind != TYPE_FAILABLE)
{
@@ -5235,6 +5198,8 @@ static inline bool sema_expr_analyse_or_error(Context *context, Expr *expr)
// First we analyse the "else" and try to implictly cast.
Expr *else_expr = expr->or_error_expr.or_error_expr;
if (!sema_analyse_expr(context, else_expr)) return false;
if (expr->or_error_expr.widen && !sema_widen_top_down(else_expr, expr->type)) return false;
// Here we might need to insert casts.
Type *else_type = else_expr->type;
if (else_type->type_kind == TYPE_FAILABLE)
@@ -5249,9 +5214,13 @@ static inline bool sema_expr_analyse_or_error(Context *context, Expr *expr)
type_quoted_error_string(else_type));
return false;
}
if (!cast_implicit(inner, type_get_failable(common))) return false;
if (!cast_implicit(inner, common)) return false;
if (!cast_implicit(else_expr, common)) return false;
if (IS_FAILABLE(else_expr))
{
SEMA_ERROR(else_expr, "The expression must be a non-failable.");
return false;
}
expr->type = common;
return true;
@@ -5287,7 +5256,7 @@ static inline bool sema_expr_analyse_rethrow(Context *context, Expr *expr)
static inline bool sema_expr_analyse_force_unwrap(Context *context, Expr *expr)
{
Expr *inner = expr->force_unwrap_expr;
Expr *inner = expr->inner_expr;
if (!sema_analyse_expr(context, inner)) return false;
if (inner->type == type_anyfail)
{
@@ -5375,7 +5344,7 @@ static inline bool sema_expr_analyse_compound_literal(Context *context, Expr *ex
{
if (!sema_resolve_type_info(context, expr->expr_compound_literal.type_info)) return false;
Type *type = expr->expr_compound_literal.type_info->type;
if (TYPE_IS_FAILABLE(type))
if (type_is_failable(type))
{
SEMA_ERROR(expr->expr_compound_literal.type_info,
"The type here should always be written as a plain type and not a failable, please remove the '!'.");
@@ -5386,22 +5355,11 @@ static inline bool sema_expr_analyse_compound_literal(Context *context, Expr *ex
return true;
}
static inline bool sema_expr_analyse_typeof(Context *context, Expr *expr)
{
TODO
if (!sema_analyse_expr(context, expr->typeof_expr)) return false;
Type *type = expr->typeof_expr->type->canonical;
expr->expr_kind = EXPR_TYPEID;
expr->typeid_expr = type_info_new_base(type, expr->typeof_expr->span);
expr->type = type_typeid;
return true;
}
static inline bool sema_expr_analyse_failable(Context *context, Expr *expr)
{
Expr *inner = expr->failable_expr;
Expr *inner = expr->inner_expr;
if (!sema_analyse_expr(context, inner)) return false;
if (IS_FAILABLE(inner))
@@ -5970,51 +5928,6 @@ static inline bool sema_expr_analyse_ct_nameof(Context *context, Expr *expr)
return true;
}
static inline bool sema_expr_resolve_maybe_identifier(Context *c, Expr *expr, Decl **decl_ref, Type **type_ref, ExprFlatElement **flatpath)
{
switch (expr->expr_kind)
{
case EXPR_CONST_IDENTIFIER:
case EXPR_IDENTIFIER:
{
ASSIGN_DECL_ELSE(*decl_ref, sema_resolve_normal_symbol(c, expr->identifier_expr.identifier, expr->identifier_expr.path, false), false);
return true;
}
case EXPR_TYPEINFO:
if (expr->resolve_status == RESOLVE_DONE)
{
*type_ref = expr->type_expr->type;
return true;
}
if (expr->type_expr->kind != TYPE_INFO_IDENTIFIER)
{
SEMA_ERROR(expr, "Expected a plain type name here.");
return false;
}
ASSIGN_DECL_ELSE(*decl_ref, sema_resolve_normal_symbol(c, expr->type_expr->unresolved.name_loc,
expr->type_expr->unresolved.path, false), false);
return true;
case EXPR_CONST:
switch (expr->const_expr.const_kind)
{
case CONST_STRING:
return sema_analyse_identifier_path_string(c, expr->span, expr, decl_ref, type_ref, flatpath, false);
case CONST_ERR:
case CONST_ENUM:
// This should not be possible, they should only be found after analysing access.
UNREACHABLE
default:
SEMA_ERROR(expr, "You can only do $define on identifiers and types.");
break;
}
case EXPR_ACCESS:
TODO // This will handle enum and errs
default:
return false;
}
}
static Type *sema_expr_check_type_exists(Context *context, TypeInfo *type_info)
{
@@ -6279,7 +6192,7 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Expr *expr)
case EXPR_CATCH_UNWRAP:
UNREACHABLE
case EXPR_DECL:
if (!sema_analyse_var_decl(context, expr->decl_expr)) return false;
if (!sema_analyse_var_decl(context, expr->decl_expr, true)) return false;
expr->type = expr->decl_expr->type;
return true;
case EXPR_CT_CALL:
@@ -6310,10 +6223,8 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Expr *expr)
return sema_expr_analyse_force_unwrap(context, expr);
case EXPR_TRY:
return sema_expr_analyse_try(context, expr);
case EXPR_TRY_ASSIGN:
return sema_expr_analyse_try_assign(context, expr, false);
case EXPR_TYPEOF:
return sema_expr_analyse_typeof(context, expr);
case EXPR_CATCH:
return sema_expr_analyse_catch(context, expr);
case EXPR_OR_ERROR:
return sema_expr_analyse_or_error(context, expr);
case EXPR_COMPOUND_LITERAL:
@@ -6357,50 +6268,41 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Expr *expr)
UNREACHABLE
}
bool sema_analyse_assigned_expr(Context *context, Type *to, Expr *expr, bool may_be_failable)
{
if (!sema_analyse_inferred_expr(context, to, expr)) return false;
if (IS_FAILABLE(expr))
{
if (!may_be_failable)
{
if (!to) to = expr->type;
SEMA_ERROR(expr, "%s cannot be converted to %s.", type_quoted_error_string(type_no_fail(expr->type)), type_quoted_error_string(to));
return false;
}
if (to && to->type_kind != TYPE_FAILABLE)
{
to = type_get_failable(to);
}
}
return to ? cast_implicit(expr, to) : true;
}
bool sema_analyse_cond_expr(Context *context, Expr *expr)
{
if (expr->expr_kind == EXPR_BINARY && expr->binary_expr.operator == BINARYOP_ASSIGN)
{
SEMA_ERROR(expr, "Assignment expressions must be enclosed in an extra () in conditionals.");
return false;
}
if (!sema_analyse_expr(context, expr)) return false;
if (IS_FAILABLE(expr))
{
SEMA_ERROR(expr, "%s cannot be converted to %s.", type_quoted_error_string(expr->type), type_quoted_error_string(type_bool));
SEMA_ERROR(expr, "A failable %s cannot be implicitly converted to a regular boolean value, use 'try(<expr>)' "
"and 'catch(<expr>)' to conditionally execute on success or failure.",
type_quoted_error_string(expr->type));
return false;
}
return cast_implicit(expr, type_bool);
}
bool sema_analyse_expr_of_required_type(Context *context, Type *to, Expr *expr)
bool sema_analyse_expr_rhs(Context *context, Type *to, Expr *expr, bool allow_failable)
{
Type *no_fail_type = type_no_fail(to);
if (!sema_analyse_inferred_expr(context, no_fail_type, expr)) return false;
if (IS_FAILABLE(expr))
if (to && type_is_failable_type(to))
{
if (no_fail_type && to->type_kind != TYPE_FAILABLE)
{
if (!to) to = expr->type;
SEMA_ERROR(expr, "%s cannot be converted to %s.", type_quoted_error_string(expr->type), type_quoted_error_string(to));
return false;
}
to = to->failable;
assert(allow_failable);
}
return to ? cast_implicit(expr, to) : true;
if (!sema_analyse_inferred_expr(context, to, expr)) return false;
if (to && !cast_implicit(expr, to)) return false;
if (!allow_failable && IS_FAILABLE(expr))
{
SEMA_ERROR(expr, "You cannot have a failable here.");
return false;
}
return true;
}
@@ -6573,8 +6475,66 @@ bool sema_analyse_expr(Context *context, Expr *expr)
return sema_analyse_expr_lvalue(context, expr) && sema_cast_rvalue(context, expr);
}
void insert_widening_type(Expr *expr, Type *infer_type)
{
if (!infer_type) return;
switch (expr->expr_kind)
{
case EXPR_BINARY:
switch (expr->binary_expr.operator)
{
case BINARYOP_MULT:
case BINARYOP_SUB:
case BINARYOP_ADD:
case BINARYOP_DIV:
case BINARYOP_MOD:
case BINARYOP_SHR:
case BINARYOP_SHL:
case BINARYOP_BIT_OR:
case BINARYOP_BIT_XOR:
case BINARYOP_BIT_AND:
if (!expr_is_simple(expr->binary_expr.left) || !expr_is_simple(expr->binary_expr.right)) return;
expr->type = infer_type;
expr->binary_expr.widen = true;
return;
default:
return;
}
case EXPR_OR_ERROR:
if (!expr_is_simple(expr->or_error_expr.expr)) return;
if (!expr->or_error_expr.is_jump && !expr_is_simple(expr->or_error_expr.or_error_expr)) return;
expr->type = infer_type;
expr->or_error_expr.widen = true;
return;
case EXPR_GROUP:
insert_widening_type(expr->inner_expr, infer_type);
return;
case EXPR_TERNARY:
if (!expr_is_simple(expr->ternary_expr.else_expr)) return;
if (expr->ternary_expr.then_expr && !expr_is_simple(expr->ternary_expr.else_expr)) return;
expr->type = infer_type;
expr->ternary_expr.widen = true;
return;
case EXPR_UNARY:
switch (expr->unary_expr.operator)
{
case UNARYOP_NEG:
case UNARYOP_BITNEG:
if (!expr_is_simple(expr->unary_expr.expr)) return;
expr->type = infer_type;
expr->unary_expr.widen = true;
return;
default:
return;
}
default:
return;
}
UNREACHABLE
}
bool sema_analyse_inferred_expr(Context *context, Type *infer_type, Expr *expr)
{
infer_type = type_no_fail(infer_type);
switch (expr->resolve_status)
{
case RESOLVE_NOT_DONE:
@@ -6600,6 +6560,7 @@ bool sema_analyse_inferred_expr(Context *context, Type *infer_type, Expr *expr)
if (!sema_expr_analyse_identifier(context, infer_type, expr)) return expr_poison(expr);
break;
default:
insert_widening_type(expr, infer_type);
if (!sema_analyse_expr_dispatch(context, expr)) return expr_poison(expr);
break;
}

View File

@@ -103,7 +103,7 @@ static inline bool sema_analyse_return_stmt(Context *context, Ast *statement)
}
// 3. Evaluate the return value to be the expected return type.
if (!sema_analyse_expr_of_required_type(context, expected_rtype, return_expr)) return false;
if (!sema_analyse_expr_rhs(context, expected_rtype, return_expr, type_is_failable(expected_rtype))) return false;
assert(type_no_fail(statement->return_stmt.expr->type)->canonical == type_no_fail(expected_rtype)->canonical);
@@ -212,7 +212,7 @@ static inline bool sema_analyse_try_unwrap(Context *context, Expr *expr)
return false;
}
if (!cast_implicit_ignore_failable(failable, ident->type)) return false;
if (!cast_implicit(failable, ident->type)) return false;
expr->try_unwrap_expr.assign_existing = true;
expr->try_unwrap_expr.lhs = ident;
@@ -253,7 +253,7 @@ static inline bool sema_analyse_try_unwrap(Context *context, Expr *expr)
if (var_type)
{
if (!cast_implicit_ignore_failable(failable, var_type->type)) return false;
if (!cast_implicit(failable, var_type->type)) return false;
}
// 4c. Create a type_info if needed.
@@ -266,7 +266,7 @@ static inline bool sema_analyse_try_unwrap(Context *context, Expr *expr)
Decl *decl = decl_new_var(ident_token, var_type, VARDECL_LOCAL, VISIBLE_LOCAL);
// 4e. Analyse it
if (!sema_analyse_var_decl(context, decl)) return false;
if (!sema_analyse_var_decl(context, decl, true)) return false;
expr->try_unwrap_expr.decl = decl;
}
@@ -369,7 +369,7 @@ static inline bool sema_analyse_catch_unwrap(Context *context, Expr *expr)
decl->var.init_expr = expr_new(EXPR_UNDEF, decl->span);
// 4e. Analyse it
if (!sema_analyse_var_decl(context, decl)) return false;
if (!sema_analyse_var_decl(context, decl, true)) return false;
expr->catch_unwrap_expr.decl = decl;
expr->catch_unwrap_expr.lhs = NULL;
@@ -380,7 +380,7 @@ RESOLVE_EXPRS:;
{
Expr *fail = exprs[i];
if (!sema_analyse_expr(context, fail)) return false;
if (fail->type->type_kind != TYPE_FAILABLE)
if (!type_is_failable(fail->type))
{
SEMA_ERROR(fail, "This expression is not failable, did you add it by mistake?");
return false;
@@ -515,9 +515,7 @@ static inline bool sema_analyse_cond(Context *context, Expr *expr, bool cast_to_
// 3e. Expect that it isn't a failable
if (IS_FAILABLE(init) && !decl->var.unwrap)
{
SEMA_ERROR(last, "%s cannot be converted to %s.",
type_quoted_error_string(last->type),
cast_to_bool ? "'bool'" : type_quoted_error_string(init->type));
return sema_failed_cast(last, last->type, cast_to_bool ? type_bool : init->type);
return false;
}
// TODO document
@@ -531,9 +529,7 @@ static inline bool sema_analyse_cond(Context *context, Expr *expr, bool cast_to_
// 3a. Check for failables in case of an expression.
if (IS_FAILABLE(last))
{
SEMA_ERROR(last, "%s cannot be converted to %s.",
type_quoted_error_string(last->type),
cast_to_bool ? "'bool'" : type_quoted_error_string(type_no_fail(last->type)));
sema_failed_cast(last, last->type, cast_to_bool ? type_bool : type_no_fail(last->type));
return false;
}
// 3b. Cast to bool if that is needed
@@ -660,98 +656,9 @@ static inline bool sema_analyse_do_stmt(Context *context, Ast *statement)
}
/**
* Analyse a regular local declaration, e.g. int x = 123
*/
bool sema_analyse_local_decl(Context *context, Decl *decl)
{
assert(decl->decl_kind == DECL_VAR && "Unexpected declaration type");
// TODO unify with global decl analysis
// Add a local to the current context, will throw error on shadowing.
if (!sema_add_local(context, decl)) return decl_poison(decl);
// 1. Local constants: const int FOO = 123.
if (decl->var.kind == VARDECL_CONST)
{
Expr *init_expr = decl->var.init_expr;
// 1a. We require an init expression.
if (!init_expr)
{
SEMA_ERROR(decl, "Constants need to have an initial value.");
return false;
}
// 1b. We require defined constants
if (init_expr->expr_kind == EXPR_UNDEF)
{
SEMA_ERROR(decl, "Constants cannot be undefined.");
return false;
}
if (!decl->var.type_info)
{
if (!sema_analyse_expr(context, init_expr)) return false;
decl->type = init_expr->type;
// Skip further evaluation.
goto EXIT_OK;
}
}
if (!sema_resolve_type_info_maybe_inferred(context, decl->var.type_info, decl->var.init_expr != NULL)) return decl_poison(decl);
decl->type = decl->var.type_info->type;
if (decl->var.init_expr)
{
bool type_is_inferred = decl->type->type_kind == TYPE_INFERRED_ARRAY;
Expr *init = decl->var.init_expr;
// Handle explicit undef
if (init->expr_kind == EXPR_UNDEF)
{
if (type_is_inferred)
{
SEMA_ERROR(decl->var.type_info, "Size of the array cannot be inferred with explicit undef.");
return false;
}
goto EXIT_OK;
}
if (!sema_expr_analyse_assign_right_side(context, NULL, decl->type, init, false)) return decl_poison(decl);
if (type_is_inferred)
{
Type *right_side_type = init->type->canonical;
assert(right_side_type->type_kind == TYPE_ARRAY);
decl->type = type_get_array(decl->type->array.base, right_side_type->array.len);
}
if (decl->var.unwrap && init->type->type_kind != TYPE_FAILABLE)
{
SEMA_ERROR(decl->var.init_expr, "A failable expression was expected here.");
return decl_poison(decl);
}
if (init->expr_kind == EXPR_CONST) init->const_expr.narrowable = false;
}
EXIT_OK:
if (decl->var.is_static)
{
scratch_buffer_clear();
scratch_buffer_append(context->active_function_for_analysis->name);
scratch_buffer_append_char('.');
scratch_buffer_append(decl->name);
decl->external_name = scratch_buffer_interned();
}
if (decl->var.init_expr && decl->var.is_static)
{
if (!expr_is_constant_eval(decl->var.init_expr, CONSTANT_EVAL_ANY))
{
SEMA_ERROR(decl->var.init_expr, "Static variable initialization must be constant.");
return false;
}
}
if (!decl->alignment) decl->alignment = type_alloca_alignment(decl->type);
return true;
}
static inline bool sema_analyse_declare_stmt(Context *context, Ast *statement)
{
return sema_analyse_local_decl(context, statement->declare_stmt);
return sema_analyse_var_decl(context, statement->declare_stmt, true);
}
/**
@@ -798,7 +705,7 @@ static inline bool sema_analyse_var_stmt(Context *context, Ast *statement)
}
if (decl->var.init_expr)
{
if (!sema_analyse_expr_of_required_type(context, decl->type, decl->var.init_expr)) return false;
if (!sema_analyse_expr_rhs(context, decl->type, decl->var.init_expr, false)) return false;
if (!expr_is_constant_eval(decl->var.init_expr, CONSTANT_EVAL_ANY))
{
SEMA_ERROR(decl->var.init_expr, "Expected a constant expression assigned to %s.", decl->name);
@@ -1174,7 +1081,7 @@ static inline bool sema_analyse_foreach_stmt(Context *context, Ast *statement)
Type *indexed_type;
// First fold the enumerator expression, removing any () around it.
while (enumerator->expr_kind == EXPR_GROUP) enumerator = enumerator->group_expr;
while (enumerator->expr_kind == EXPR_GROUP) enumerator = enumerator->inner_expr;
bool iterator_based = false;
@@ -1283,9 +1190,9 @@ static inline bool sema_analyse_foreach_stmt(Context *context, Ast *statement)
index->var.type_info = type_info_new_base(type_isize, index->span);
}
// Analyse the declaration.
if (!sema_analyse_local_decl(context, index)) return SCOPE_POP_ERROR();
if (!sema_analyse_var_decl(context, index, true)) return SCOPE_POP_ERROR();
if (index->type->type_kind == TYPE_FAILABLE)
if (type_is_failable(index->type))
{
SEMA_ERROR(index->var.type_info, "The index may not be a failable.");
return SCOPE_POP_ERROR();
@@ -1314,7 +1221,7 @@ static inline bool sema_analyse_foreach_stmt(Context *context, Ast *statement)
}
// Analyse the value declaration.
if (!sema_analyse_local_decl(context, var)) return SCOPE_POP_ERROR();
if (!sema_analyse_var_decl(context, var, true)) return SCOPE_POP_ERROR();
if (IS_FAILABLE(var))
{
@@ -1333,7 +1240,11 @@ static inline bool sema_analyse_foreach_stmt(Context *context, Ast *statement)
Expr dummy = { .resolve_status = RESOLVE_DONE, .span = { var->var.type_info->span.loc,
var->span.end_loc }, .expr_kind = EXPR_IDENTIFIER, .type = expected_var_type };
if (!cast_implicit(&dummy, var->type)) return SCOPE_POP_ERROR();
if (IS_FAILABLE(&dummy))
{
SEMA_ERROR(var, "The variable may not be failable.");
return false;
}
assert(dummy.expr_kind == EXPR_CAST);
statement->foreach_stmt.cast = dummy.cast_expr.kind;
}
@@ -1638,7 +1549,7 @@ static bool sema_analyse_nextcase_stmt(Context *context, Ast *statement)
Type *expected_type = parent->ast_kind == AST_SWITCH_STMT ? parent->switch_stmt.cond->type : type_anyerr;
if (!sema_analyse_expr_of_required_type(context, expected_type, target)) return false;
if (!sema_analyse_expr_rhs(context, expected_type, target, false)) return false;
if (target->expr_kind == EXPR_CONST)
{
@@ -1753,35 +1664,6 @@ static bool sema_analyse_ct_if_stmt(Context *context, Ast *statement)
}
}
/**
* Cast the case expression to the switch type and ensure it is constant.
*
* @return true if the analysis succeeds.
*/
static bool sema_analyse_case_expr(Context *context, Type* to_type, Ast *case_stmt, bool *is_const)
{
assert(to_type);
Expr *case_expr = case_stmt->case_stmt.expr;
// 1. Try to do implicit conversion to the correct type.
if (!sema_analyse_inferred_expr(context, to_type, case_expr)) return false;
Type *case_type = case_expr->type->canonical;
Type *to_type_canonical = to_type->canonical;
// 3. If we already have the same type we're done.
if (to_type_canonical == case_type) return true;
// 4. Otherwise check if we have an enum receiving type and a number on
// in the case. In that case we do an implicit conversion.
if (to_type_canonical->type_kind == TYPE_ENUM && type_is_integer(case_type))
{
return cast(case_expr, to_type);
}
return cast_implicit(case_expr, to_type);
}
static inline bool sema_analyse_compound_statement_no_scope(Context *context, Ast *compound_statement)
{
@@ -1802,7 +1684,7 @@ static inline bool sema_analyse_compound_statement_no_scope(Context *context, As
static inline bool sema_check_type_case(Context *context, Type *switch_type, Ast *case_stmt, Ast **cases, unsigned index)
{
Expr *expr = case_stmt->case_stmt.expr;
if (!sema_analyse_expr_of_required_type(context, type_typeid, expr)) return false;
if (!sema_analyse_expr_rhs(context, type_typeid, expr, false)) return false;
if (expr->expr_kind == EXPR_CONST)
{
@@ -1825,8 +1707,12 @@ static inline bool sema_check_type_case(Context *context, Type *switch_type, Ast
static inline bool sema_check_value_case(Context *context, Type *switch_type, Ast *case_stmt, Ast **cases, unsigned index, bool *if_chained)
{
if (!sema_analyse_case_expr(context, switch_type, case_stmt, if_chained)) return false;
assert(switch_type);
Expr *expr = case_stmt->case_stmt.expr;
// 1. Try to do implicit conversion to the correct type.
if (!sema_analyse_expr_rhs(context, switch_type, expr, false)) return false;
if (expr->expr_kind != EXPR_CONST)
{
*if_chained = true;
@@ -1950,8 +1836,7 @@ static bool sema_analyse_ct_switch_body(Context *context, Ast *statement)
}
else
{
if (!sema_analyse_inferred_expr(context, type, expr)) return false;
if (!cast_implicit(expr, type)) return false;
if (!sema_analyse_expr_rhs(context, type, expr, false)) return false;
}
if (expr->expr_kind != EXPR_CONST)
{
@@ -2117,7 +2002,7 @@ bool sema_analyse_assert_stmt(Context *context, Ast *statement)
}
else
{
if (!sema_analyse_assigned_expr(context, type_bool, expr, false)) return false;
if (!sema_analyse_cond_expr(context, expr)) return false;
}
return true;
}

View File

@@ -195,6 +195,7 @@ bool sema_resolve_type(Context *context, Type *type)
case TYPE_VECTOR:
case TYPE_TYPEINFO:
case TYPE_UNTYPED_LIST:
case TYPE_FAILABLE_ANY:
return true;
case TYPE_POINTER:
return sema_resolve_type(context, type->pointer);

View File

@@ -42,8 +42,6 @@ Type *type_u128 = &t.u128;
Type *type_uptr = &t.uptr;
Type *type_uptrdiff = &t.uptrdiff;
Type *type_usize = &t.usz;
Type *type_compint = &t.ixx;
Type *type_compfloat = &t.fxx;
Type *type_compstr = &t.str;
Type *type_anyerr = &t.anyerr;
Type *type_complist = &t.ctlist;
@@ -51,8 +49,6 @@ Type *type_anyfail = &t.anyfail;
static unsigned size_subarray;
static AlignSize alignment_subarray;
unsigned size_error_code;
unsigned alignment_error_code;
static AlignSize max_alignment_vector;
#define PTR_OFFSET 0
@@ -139,6 +135,8 @@ const char *type_to_error_string(Type *type)
return "typeinfo";
case TYPE_TYPEID:
return "typeid";
case TYPE_FAILABLE_ANY:
return "void!";
case TYPE_POINTER:
if (type->pointer->type_kind == TYPE_FUNC)
{
@@ -216,7 +214,6 @@ RETRY:
UNREACHABLE;
case TYPE_FAILABLE:
type = type->failable;
if (!type) return 1;
goto RETRY;
case TYPE_TYPEDEF:
type = type->canonical;
@@ -231,6 +228,7 @@ RETRY:
assert(type->decl->resolve_status == RESOLVE_DONE);
return type->decl->strukt.size;
case TYPE_VOID:
case TYPE_FAILABLE_ANY:
return 1;
case TYPE_BOOL:
case TYPE_TYPEID:
@@ -354,7 +352,6 @@ bool type_is_abi_aggregate(Type *type)
return false;
case TYPE_FAILABLE:
type = type->failable;
if (!type) return false;
goto RETRY;
case TYPE_DISTINCT:
type = type->decl->distinct_decl.base_type;
@@ -365,6 +362,7 @@ bool type_is_abi_aggregate(Type *type)
case TYPE_BITSTRUCT:
case ALL_FLOATS:
case TYPE_VOID:
case TYPE_FAILABLE_ANY:
case ALL_INTS:
case TYPE_BOOL:
case TYPE_TYPEID:
@@ -518,7 +516,6 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
{
case TYPE_FAILABLE:
type = type->failable;
if (!type) return false;
goto RETRY;
case TYPE_DISTINCT:
type = type->decl->distinct_decl.base_type;
@@ -532,6 +529,7 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
case TYPE_STRLIT:
case TYPE_SUBARRAY:
case CT_TYPES:
case TYPE_FAILABLE_ANY:
return false;
case TYPE_VIRTUAL:
case TYPE_VIRTUAL_ANY:
@@ -745,10 +743,10 @@ AlignSize type_abi_alignment(Type *type)
return alignment;
}
case TYPE_VOID:
case TYPE_FAILABLE_ANY:
return 1;
case TYPE_FAILABLE:
type = type->failable;
if (!type) return 1;
goto RETRY;
case TYPE_DISTINCT:
type = type->decl->distinct_decl.base_type;
@@ -900,6 +898,7 @@ static Type *type_generate_inferred_array(Type *arr_type, bool canonical)
Type *type_get_ptr_recurse(Type *ptr_type)
{
assert(ptr_type->type_kind != TYPE_FAILABLE_ANY);
if (ptr_type->type_kind == TYPE_FAILABLE)
{
ptr_type = ptr_type->failable;
@@ -910,13 +909,13 @@ Type *type_get_ptr_recurse(Type *ptr_type)
}
Type *type_get_ptr(Type *ptr_type)
{
assert(ptr_type->type_kind != TYPE_FAILABLE);
assert(!type_is_failable(ptr_type));
return type_generate_ptr(ptr_type, false);
}
Type *type_get_failable(Type *failable_type)
{
assert(failable_type->type_kind != TYPE_FAILABLE);
assert(!type_is_failable(failable_type));
return type_generate_failable(failable_type, false);
}
@@ -967,8 +966,6 @@ bool type_is_structurally_equivalent(Type *type1, Type *type2)
if (type1 == type2) return true;
if (type_size(type1) != type_size(type2)) return false;
// If the other type is a union, we check against every member
// noting that there is only structural equivalence if it fills out the
if (type2->type_kind == TYPE_UNION)
@@ -1213,6 +1210,9 @@ static void type_append_name_to_scratch(Type *type)
type_append_name_to_scratch(type->pointer);
scratch_buffer_append_char('*');
break;
case TYPE_FAILABLE_ANY:
scratch_buffer_append("void!");
break;
case TYPE_FAILABLE:
if (type->failable)
{
@@ -1349,7 +1349,7 @@ void type_setup(PlatformTarget *target)
type_create("typeinfo", &t.typeinfo, TYPE_TYPEINFO, 1, 1, 1);
type_create("complist", &t.ctlist, TYPE_UNTYPED_LIST, 1, 1, 1);
t.anyfail = (Type){ .type_kind = TYPE_FAILABLE, .failable = type_void };
type_create("void!", &t.anyfail, TYPE_FAILABLE_ANY, 1, 1, 1);
type_init("typeid", &t.typeid, TYPE_TYPEID, target->width_pointer, target->align_pointer);
type_init("void*", &t.voidstar, TYPE_POINTER, target->width_pointer, target->align_pointer);
@@ -1415,6 +1415,7 @@ bool type_is_scalar(Type *type)
case TYPE_ARRAY:
case TYPE_SUBARRAY:
case TYPE_VECTOR:
case TYPE_FAILABLE_ANY:
return false;
case TYPE_BOOL:
case ALL_INTS:
@@ -1653,7 +1654,7 @@ Type *type_find_max_type(Type *type, Type *other)
type = type->canonical;
other = other->canonical;
assert(type->type_kind != TYPE_FAILABLE && other->type_kind != TYPE_FAILABLE);
assert(!type_is_failable(type) && !type_is_failable(other));
if (type == other) return type;
@@ -1670,6 +1671,7 @@ Type *type_find_max_type(Type *type, Type *other)
case TYPE_INFERRED_ARRAY:
case TYPE_POISONED:
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
UNREACHABLE
case TYPE_VOID:
case TYPE_BOOL:

View File

@@ -17,15 +17,15 @@ func Test creator()
// #expect: literal_load.ll
%literal = alloca %Test, align 4
%literal1 = alloca %Test, align 4
%0 = bitcast %Test* %literal to i32*
store i32 0, i32* %0, align 4
%dive = getelementptr inbounds %Test, %Test* %literal, i32 0, i32 0
%1 = load i32, i32* %dive, align 4
call void @blorg(i32 %1)
%2 = bitcast %Test* %literal1 to i32*
store i32 0, i32* %2, align 4
%dive2 = getelementptr inbounds %Test, %Test* %literal1, i32 0, i32 0
%3 = load i32, i32* %dive2, align 4
ret i32 %3
%literal = alloca %Test, align 4
%literal1 = alloca %Test, align 4
%0 = bitcast %Test* %literal to i32*
store i32 0, i32* %0, align 4
%1 = getelementptr inbounds %Test, %Test* %literal, i32 0, i32 0
%2 = load i32, i32* %1, align 4
call void @blorg(i32 %2)
%3 = bitcast %Test* %literal1 to i32*
store i32 0, i32* %3, align 4
%4 = getelementptr inbounds %Test, %Test* %literal1, i32 0, i32 0
%5 = load i32, i32* %4, align 4
ret i32 %5

View File

@@ -20,17 +20,17 @@ func Test creator()
declare void @blorg(i64)
%literal = alloca %Test, align 4
%literal1 = alloca %Test, align 4
%0 = bitcast %Test* %literal to i32*
store i32 0, i32* %0, align 4
%dive = getelementptr inbounds %Test, %Test* %literal, i32 0, i32 0
%1 = load i32, i32* %dive, align 4
%2 = zext i32 %1 to i64
call void @blorg(i64 %2)
%3 = bitcast %Test* %literal1 to i32*
store i32 0, i32* %3, align 4
%dive2 = getelementptr inbounds %Test, %Test* %literal1, i32 0, i32 0
%4 = load i32, i32* %dive2, align 4
%5 = zext i32 %4 to i64
ret i64 %5
%literal = alloca %Test, align 4
%literal1 = alloca %Test, align 4
%0 = bitcast %Test* %literal to i32*
store i32 0, i32* %0, align 4
%1 = getelementptr inbounds %Test, %Test* %literal, i32 0, i32 0
%2 = load i32, i32* %1, align 4
%3 = zext i32 %2 to i64
call void @blorg(i64 %3)
%4 = bitcast %Test* %literal1 to i32*
store i32 0, i32* %4, align 4
%5 = getelementptr inbounds %Test, %Test* %literal1, i32 0, i32 0
%6 = load i32, i32* %5, align 4
%7 = zext i32 %6 to i64
ret i64 %7

View File

@@ -19,14 +19,14 @@ func Test creator()
// #expect: literal_load.ll
%literal = alloca %Test, align 4
%literal1 = alloca %Test, align 4
%0 = bitcast %Test* %literal to i32*
store i32 0, i32* %0, align 4
%dive = getelementptr inbounds %Test, %Test* %literal, i32 0, i32 0
%1 = load i32, i32* %dive, align 4
call void @blorg(i32 %1)
%2 = bitcast %Test* %literal1 to i32*
store i32 0, i32* %2, align 4
%dive2 = getelementptr inbounds %Test, %Test* %literal1, i32 0, i32 0
%3 = load i32, i32* %dive2, align 4
ret i32 %3
%literal1 = alloca %Test, align 4
%0 = bitcast %Test* %literal to i32*
store i32 0, i32* %0, align 4
%1 = getelementptr inbounds %Test, %Test* %literal, i32 0, i32 0
%2 = load i32, i32* %1, align 4
call void @blorg(i32 %2)
%3 = bitcast %Test* %literal1 to i32*
store i32 0, i32* %3, align 4
%4 = getelementptr inbounds %Test, %Test* %literal1, i32 0, i32 0
%5 = load i32, i32* %4, align 4
ret i32 %5

View File

@@ -0,0 +1,53 @@
// #target: x64-mingw
module test;
extern fn void printf(char*, ...);
struct Foo
{
float[2] x;
}
fn void test(Foo x) @regcall
{
}
fn void main()
{
test(Foo { });
}
/* #expect: test.ll
%Foo = type { [2 x float] }
@Foo = linkonce_odr constant i8 1
; Function Attrs: nounwind
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define x86_regcallcc void @test.test(float %0, float %1) #0 {
entry:
%x = alloca %Foo, align 4
%2 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 0
%3 = getelementptr inbounds [2 x float], [2 x float]* %2, i64 0, i64 0
store float %0, float* %3, align 4
%4 = getelementptr inbounds [2 x float], [2 x float]* %2, i64 0, i64 1
store float %1, float* %4, align 4
ret void
}
; Function Attrs: nounwind
define void @main() #0 {
entry:
%literal = alloca %Foo, align 4
%0 = bitcast %Foo* %literal to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 8, i1 false)
%1 = getelementptr inbounds %Foo, %Foo* %literal, i32 0, i32 0
%2 = getelementptr inbounds [2 x float], [2 x float]* %1, i64 0, i64 0
%loadexpanded = load float, float* %2, align 4
%3 = getelementptr inbounds [2 x float], [2 x float]* %1, i64 0, i64 1
%loadexpanded1 = load float, float* %3, align 4
call x86_regcallcc void @test.test(float %loadexpanded, float %loadexpanded1)
ret void
}

View File

@@ -20,17 +20,19 @@ func void hello(Foo f)
declare void @hello2(i64, i64) #0
define void @unionx64.hello(i64 %0, i64 %1)
define void @unionx64.hello(i64 %0, i64 %1) #0 {
entry:
%f = alloca %Foo, align 8
%pair = bitcast %Foo* %f to { i64, i64 }*
%lo = getelementptr inbounds { i64, i64 }, { i64, i64 }* %pair, i32 0, i32 0
store i64 %0, i64* %lo, align 8
%hi = getelementptr inbounds { i64, i64 }, { i64, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %hi, align 8
%casttemp = bitcast %Foo* %f to { i64, i64 }*
%lo1 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %casttemp, i32 0, i32 0
%lo2 = load i64, i64* %lo1, align 8
%hi3 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %casttemp, i32 0, i32 1
%hi4 = load i64, i64* %hi3, align 8
call void @hello2(i64 %lo2, i64 %hi4)
%2 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %pair, i32 0, i32 0
store i64 %0, i64* %2, align 8
%3 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %3, align 8
%4 = bitcast %Foo* %f to { i64, i64 }*
%5 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %4, i32 0, i32 0
%lo = load i64, i64* %5, align 8
%6 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %4, i32 0, i32 1
%hi = load i64, i64* %6, align 8
call void @hello2(i64 %lo, i64 %hi)
ret void
}

View File

@@ -24,6 +24,6 @@ entry:
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %1, i8* align 16 bitcast ([30 x double]* @.__const to i8*), i32 240, i1 false)
%2 = load i32, i32* %x, align 4
%uiuiext = zext i32 %2 to i64
%arridx = getelementptr inbounds [30 x double], [30 x double]* %student_t, i64 0, i64 %uiuiext
%3 = load double, double* %arridx, align 8
ret double %3
%3 = getelementptr inbounds [30 x double], [30 x double]* %student_t, i64 0, i64 %uiuiext
%4 = load double, double* %3, align 8
ret double %4

View File

@@ -0,0 +1,7 @@
fn int[*] hello() // #error: Inferred array types can only be used in declarations with initializers
{
return int[3] { 1, 2, 3};
}
int[*] c; // #error: Inferred array types can only be used in declarations with initializers

View File

@@ -0,0 +1,5 @@
fn void test()
{
int[3] z;
(int[*])(z); // #error: Inferred array types can only be used in declarations with initializers
}

View File

@@ -25,11 +25,11 @@ struct BazTwo
func void test1()
{
Foo x;
Bar z = (Baz)(x); // #error: Cannot cast 'Foo' to 'Baz'
Bar z = (Baz)(x); // #error: cast 'Foo' to 'Baz'
}
func void test2()
{
Baz x;
BazTwo z = (BazTwo)(x); // #error: Cannot cast 'Baz' to 'BazTwo'
BazTwo z = (BazTwo)(x); // #error: cast 'Baz' to 'BazTwo'
}

View File

@@ -0,0 +1,12 @@
errtype MyErr
{
FOO
}
func void test()
{
int! x;
int! d = ($typeof(MyErr.FOO!))(x); // #error: Casting to a failable type is not allowed
}

View File

@@ -0,0 +1,29 @@
fn void test()
{
int x;
int y;
long z = x * y;
z = x * y + z; // #error: 'int' to 'long'
z = x * y + x; // #error: 'int' to 'long'
z = x / y;
z = x + y;
z = x - y;
z = x % y;
z = x / y + z; // #error: 'int' to 'long'
z = x + y + z; // #error: 'int' to 'long'
z = x - y + z; // #error: 'int' to 'long'
z = x % y + z; // #error: 'int' to 'long'
z = x / y + x; // #error: 'int' to 'long'
z = x + y + x; // #error: 'int' to 'long'
z = x - y + x; // #error: 'int' to 'long'
z = x % y + x; // #error: 'int' to 'long'
z = x << y + x; // #error: 'int' to 'long'
z = x >> y + x; // #error: 'int' to 'long'
z = x << y + z; // #error: 'int' to 'long'
z = x >> y + z; // #error: 'int' to 'long'
z = ~x + x; // #error: 'int' to 'long'
z = ~x + z; // #error: 'int' to 'long'
z = -x + z; // #error: 'int' to 'long'
z = x + z;
}

View File

@@ -0,0 +1,101 @@
fn void test()
{
int x;
int y;
long z = x * y;
z = x / y;
z = x + y;
z = x - y;
z = x % y;
z = x << y;
z = x >> y;
z = ~x;
z = -x;
int! w;
z = w ?? 1;
}
// #expect: top_down_casts.ll
define void @top_down_casts.test() #0 {
entry:
%x = alloca i32, align 4
%y = alloca i32, align 4
%z = alloca i64, align 8
%w = alloca i32, align 4
%w.f = alloca i64, align 8
store i32 0, i32* %x, align 4
store i32 0, i32* %y, align 4
%0 = load i32, i32* %x, align 4
%sisiext = sext i32 %0 to i64
%1 = load i32, i32* %y, align 4
%sisiext1 = sext i32 %1 to i64
%mul = mul i64 %sisiext, %sisiext1
store i64 %mul, i64* %z, align 8
%2 = load i32, i32* %x, align 4
%sisiext2 = sext i32 %2 to i64
%3 = load i32, i32* %y, align 4
%sisiext3 = sext i32 %3 to i64
%sdiv = sdiv i64 %sisiext2, %sisiext3
store i64 %sdiv, i64* %z, align 8
%4 = load i32, i32* %x, align 4
%sisiext4 = sext i32 %4 to i64
%5 = load i32, i32* %y, align 4
%sisiext5 = sext i32 %5 to i64
%add = add i64 %sisiext4, %sisiext5
store i64 %add, i64* %z, align 8
%6 = load i32, i32* %x, align 4
%sisiext6 = sext i32 %6 to i64
%7 = load i32, i32* %y, align 4
%sisiext7 = sext i32 %7 to i64
%sub = sub i64 %sisiext6, %sisiext7
store i64 %sub, i64* %z, align 8
%8 = load i32, i32* %x, align 4
%sisiext8 = sext i32 %8 to i64
%9 = load i32, i32* %y, align 4
%sisiext9 = sext i32 %9 to i64
%smod = srem i64 %sisiext8, %sisiext9
store i64 %smod, i64* %z, align 8
%10 = load i32, i32* %x, align 4
%sisiext10 = sext i32 %10 to i64
%11 = load i32, i32* %y, align 4
%12 = zext i32 %11 to i64
%shl = shl i64 %sisiext10, %12
%13 = freeze i64 %shl
store i64 %13, i64* %z, align 8
%14 = load i32, i32* %x, align 4
%sisiext11 = sext i32 %14 to i64
%15 = load i32, i32* %y, align 4
%16 = zext i32 %15 to i64
%ashr = ashr i64 %sisiext11, %16
%17 = freeze i64 %ashr
store i64 %17, i64* %z, align 8
%18 = load i32, i32* %x, align 4
%sisiext12 = sext i32 %18 to i64
%bnot = xor i64 %sisiext12, -1
store i64 %bnot, i64* %z, align 8
%19 = load i32, i32* %x, align 4
%sisiext13 = sext i32 %19 to i64
%20 = load i32, i32* %x, align 4
%sisiext14 = sext i32 %20 to i64
%neg = sub i64 0, %sisiext14
store i64 %neg, i64* %z, align 8
store i64 0, i64* %w.f, align 8
store i32 0, i32* %w, align 4
%21 = load i64, i64* %w.f, align 8
%not_err = icmp eq i64 %21, 0
br i1 %not_err, label %after_check, label %else_block
after_check: ; preds = %entry
%22 = load i32, i32* %w, align 4
%sisiext15 = sext i32 %22 to i64
br label %phi_block
else_block: ; preds = %entry
br label %phi_block
phi_block: ; preds = %else_block, %after_check
%val = phi i64 [ %sisiext15, %after_check ], [ 1, %else_block ]
store i64 %val, i64* %z, align 8
ret void
}

View File

@@ -0,0 +1,97 @@
errtype MyError
{
FOO,
BAR
}
fn void! errorThing()
{
return MyError.BAR!;
}
fn void! errorThing2()
{
return;
}
extern fn void printf(char*, ...);
func void main()
{
anyerr z = errorThing();
printf("Z; %llx\n", (iptr)(z));
printf("BAR: %llx\n", (iptr)(MyError.BAR));
printf("FOO: %llx\n", (iptr)(MyError.FOO));
z = errorThing2();
printf("Z2: %llx\n", (iptr)(z));
}
/* #expect: anyerr_void.ll
; Function Attrs: nounwind
define i64 @anyerr_void.errorThing() #0 {
entry:
%reterr = alloca i64, align 8
store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"anyerr_void.MyError$elements", i64 0, i64 1) to i64), i64* %reterr, align 8
br label %err_retblock
postfailed: ; No predecessors!
ret i64 0
err_retblock: ; preds = %entry
%0 = load i64, i64* %reterr, align 8
ret i64 %0
}
; Function Attrs: nounwind
define i64 @anyerr_void.errorThing2() #0 {
entry:
%reterr = alloca i64, align 8
ret i64 0
}
; Function Attrs: nounwind
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @main() #0 {
entry:
%z = alloca i64, align 8
%error_var = alloca i64, align 8
%error_var1 = alloca i64, align 8
store i64 0, i64* %error_var, align 8
%0 = call i64 @anyerr_void.errorThing()
%not_err = icmp eq i64 %0, 0
br i1 %not_err, label %after.errcheck, label %error
error: ; preds = %entry
store i64 %0, i64* %error_var, align 8
br label %noerr_block
after.errcheck: ; preds = %entry
br label %noerr_block
noerr_block: ; preds = %after.errcheck, %error
%1 = load i64, i64* %error_var, align 8
store i64 %1, i64* %z, align 8
%2 = load i64, i64* %z, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i64 %2)
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"anyerr_void.MyError$elements", i64 0, i64 1) to i64))
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), i64 ptrtoint ([2 x i8*]* @"anyerr_void.MyError$elements" to i64))
store i64 0, i64* %error_var1, align 8
%3 = call i64 @anyerr_void.errorThing2()
%not_err2 = icmp eq i64 %3, 0
br i1 %not_err2, label %after.errcheck4, label %error3
error3: ; preds = %noerr_block
store i64 %3, i64* %error_var1, align 8
br label %noerr_block5
after.errcheck4: ; preds = %noerr_block
br label %noerr_block5
noerr_block5: ; preds = %after.errcheck4, %error3
%4 = load i64, i64* %error_var1, align 8
store i64 %4, i64* %z, align 8
%5 = load i64, i64* %z, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.3, i32 0, i32 0), i64 %5)
ret void
}

View File

@@ -14,7 +14,7 @@ extern func int printf(char *c, ...);
func void main()
{
int! z = 2;
Foo*! w = &&{ z, 0 }; // #error: casting 'int[2]*' to 'Foo*' is not permitted
Foo*! w = &&{ z, 0 }; // #error: A failable 'int[2]*!' cannot be converted to 'Foo*'
}
func void test()

View File

@@ -104,7 +104,7 @@ entry:
%b = alloca i32, align 4
%a = alloca i32, align 4
store i64 ptrtoint ([5 x i8*]* @"foo.Foo$elements" to i64), i64* %f, align 8
store i64 ptrtoint ([5 x i8*]* getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 1) to i64), i64* %ef, align 8
store i64 ptrtoint (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 0, i64 1) to i64), i64* %ef, align 8
%0 = load i64, i64* %f, align 8
store i64 %0, i64* %x, align 8
%1 = load i64, i64* %x, align 8
@@ -117,12 +117,12 @@ entry:
store i64 %5, i64* %z, align 8
%6 = load i64, i64* %z, align 8
%7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0), i64 %6)
store i64 ptrtoint ([5 x i8*]* getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 3) to i64), i64* %x, align 8
store i64 ptrtoint (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 0, i64 3) to i64), i64* %x, align 8
%8 = load i64, i64* %x, align 8
store i64 %8, i64* %z, align 8
%9 = load i64, i64* %z, align 8
%10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i64 %9)
store i64 ptrtoint ([5 x i8*]* getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 4) to i64), i64* %x, align 8
store i64 ptrtoint (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 0, i64 4) to i64), i64* %x, align 8
%11 = load i64, i64* %x, align 8
store i64 %11, i64* %z, align 8
%12 = load i64, i64* %z, align 8
@@ -132,7 +132,7 @@ entry:
store i64 %14, i64* %z, align 8
%15 = load i64, i64* %z, align 8
%16 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0), i64 %15)
store i64 ptrtoint ([2 x i8*]* getelementptr inbounds ([2 x i8*], [2 x i8*]* @"foo.Foob$elements", i64 1) to i64), i64* %x, align 8
store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"foo.Foob$elements", i64 0, i64 1) to i64), i64* %x, align 8
%17 = load i64, i64* %x, align 8
store i64 %17, i64* %z, align 8
%18 = load i64, i64* %z, align 8
@@ -143,5 +143,4 @@ entry:
call void @foo.Bar__hello(i32* %b)
call void @foo.MyEnum__hello(i32* %a)
ret void
}
}

View File

@@ -1,12 +1,12 @@
func void syntaxErrors()
{
int! i = 0;
while (i + 1) {} // #error: 'int!' cannot be converted to 'bool'
if (i + 1) {} // #error: 'int!' cannot be converted to 'bool'
for (int x = i;;) {} // #error: 'int!' cannot be converted to 'int'.
for (int x = 0; x < i + 1;) {} // #error: 'bool!' cannot be converted to 'bool'
for (int x = 0; x < 10; x += i + 1) {} // #error: 'int!' cannot be converted to 'int'
switch (i + 1) // #error: 'int!' cannot be converted to 'int'
while (i + 1) {} // #error: 'int!' to 'bool'
if (i + 1) {} // #error: 'int!' to 'bool'
for (int x = i;;) {} // #error: 'int!' to 'int'
for (int x = 0; x < i + 1;) {} // #error: A failable 'bool!' cannot be implicitly converted to a regular boolean
for (int x = 0; x < 10; x += i + 1) {} // #error: Cannot assign a failable value to a non-failable
switch (i + 1) // #error: 'int!' to 'int'
{
default:
i + 1;

View File

@@ -88,6 +88,6 @@ func void test10()
}
else
{
int g = a; // #error: 'int!' cannot be converted to 'int'
int g = a; // #error: 'int!' to 'int'
}
}

View File

@@ -113,33 +113,32 @@ entry:
%6 = load i32*, i32** %zy, align 8
%7 = load i32, i32* %6, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.3, i32 0, i32 0), i32 %5, i32 %7)
%arridx = getelementptr inbounds [3 x i32], [3 x i32]* %arr, i64 0, i64 0
%8 = load i32, i32* %arridx, align 4
%sub = sub i32 %8, 1
store i32 %sub, i32* %arridx, align 4
%arridx1 = getelementptr inbounds [3 x i32], [3 x i32]* %arr, i64 0, i64 1
%9 = load i32, i32* %arridx1, align 4
%sub2 = sub i32 %9, 1
store i32 %sub2, i32* %arridx1, align 4
%arridx3 = getelementptr inbounds [3 x i32], [3 x i32]* %arr, i64 0, i64 2
%10 = load i32, i32* %arridx3, align 4
%sub4 = sub i32 %10, 1
store i32 %sub4, i32* %arridx3, align 4
%arridx5 = getelementptr inbounds [3 x i32], [3 x i32]* %arr, i64 0, i64 2
store i32* %arridx5, i32** %d, align 8
%11 = bitcast [3 x i32]* %arr to i32*
%offset = getelementptr inbounds i32, i32* %11, i64 1
%12 = insertvalue %"int[]" undef, i32* %offset, 0
%13 = insertvalue %"int[]" %12, i64 2, 1
store %"int[]" %13, %"int[]"* %taddr, align 8
%8 = getelementptr inbounds [3 x i32], [3 x i32]* %arr, i64 0, i64 0
%9 = load i32, i32* %8, align 4
%sub = sub i32 %9, 1
store i32 %sub, i32* %8, align 4
%10 = getelementptr inbounds [3 x i32], [3 x i32]* %arr, i64 0, i64 1
%11 = load i32, i32* %10, align 4
%sub1 = sub i32 %11, 1
store i32 %sub1, i32* %10, align 4
%12 = getelementptr inbounds [3 x i32], [3 x i32]* %arr, i64 0, i64 2
%13 = load i32, i32* %12, align 4
%sub2 = sub i32 %13, 1
store i32 %sub2, i32* %12, align 4
%14 = getelementptr inbounds [3 x i32], [3 x i32]* %arr, i64 0, i64 2
store i32* %14, i32** %d, align 8
%15 = getelementptr inbounds [3 x i32], [3 x i32]* %arr, i64 0, i64 1
%16 = insertvalue %"int[]" undef, i32* %15, 0
%17 = insertvalue %"int[]" %16, i64 2, 1
store %"int[]" %17, %"int[]"* %taddr, align 8
store %"int[]"* %taddr, %"int[]"** %e, align 8
%14 = load i32*, i32** %d, align 8
%15 = load i32, i32* %14, align 8
%16 = load %"int[]"*, %"int[]"** %e, align 8
%subarrayptr = getelementptr inbounds %"int[]", %"int[]"* %16, i32 0, i32 0
%saptr = load i32*, i32** %subarrayptr, align 8
%sarridx = getelementptr inbounds i32, i32* %saptr, i64 0
%17 = load i32, i32* %sarridx, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.4, i32 0, i32 0), i32 %15, i32 %17)
%18 = load i32*, i32** %d, align 8
%19 = load i32, i32* %18, align 8
%20 = load %"int[]"*, %"int[]"** %e, align 8
%21 = getelementptr inbounds %"int[]", %"int[]"* %20, i32 0, i32 0
%22 = load i32*, i32** %21, align 8
%ptroffset = getelementptr inbounds i32, i32* %22, i64 0
%23 = load i32, i32* %ptroffset, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.4, i32 0, i32 0), i32 %19, i32 %23)
ret void
}

View File

@@ -0,0 +1,10 @@
errtype MyErr
{
FOO
}
func void test()
{
int! x = (int!)(MyErr.FOO!); // #error: Casting to a failable type is not allowed
int! y = MyErr.FOO!;
}

View File

@@ -21,17 +21,17 @@ func void test1(Func arg)
func void test2(Func arg)
{
ichar b = (ichar)(arg); // #error: Cannot cast 'Func' (func void(int)) to 'ichar'.
ichar b = (ichar)(arg); // #error: 'Func' (func void(int)) to 'ichar'
}
func void test3(Func arg)
{
uint c = (uint)(arg); // #error: Cannot cast 'Func' (func void(int)) to 'uint'.
uint c = (uint)(arg); // #error: 'Func' (func void(int)) to 'uint'
}
func void test4(Func arg)
{
float d = (float)(arg); // #error: Cannot cast 'Func' (func void(int)) to 'float'.
float d = (float)(arg); // #error: 'Func' (func void(int)) to 'float'
}
func void test7(Func arg)
@@ -41,5 +41,5 @@ func void test7(Func arg)
FuncSame l = (FuncSame)(arg);
FuncOther ke = arg; // #error: 'Func' (func void(int)) to 'FuncOther' (func bool(char*))
FuncSame fe = arg;
Enum j = (Enum)(arg); // #error: Cannot cast 'Func' (func void(int)) to 'Enum'.
Enum j = (Enum)(arg); // #error: 'Func' (func void(int)) to 'Enum'
}

View File

@@ -5,5 +5,5 @@ struct Struct
func void test1()
{
int a = (Struct)(200); // #error: Cannot cast 'int' to 'Struct'
int a = (Struct)(200); // #error: 'int' to 'Struct'
}

View File

@@ -18,11 +18,11 @@ func void test(int* foo)
%z = alloca float, align 4
store i32* %0, i32** %foo
%1 = load i32*, i32** %foo, align 8
%ptrincdec = getelementptr i32, i32* %1, i8 1
store i32* %ptrincdec, i32** %foo, align 8
%ptroffset = getelementptr i32, i32* %1, i8 1
store i32* %ptroffset, i32** %foo, align 8
%2 = load i32*, i32** %foo, align 8
%ptrincdec1 = getelementptr i32, i32* %2, i8 -1
store i32* %ptrincdec1, i32** %foo, align 8
%ptroffset1 = getelementptr i32, i32* %2, i8 -1
store i32* %ptroffset1, i32** %foo, align 8
store i32 10, i32* %y, align 4
%3 = load i32, i32* %y, align 4
%add = add i32 %3, 1

View File

@@ -2,40 +2,40 @@ func void test1()
{
short! a = 1;
try(-a);
short b = -a; // #error: 'int!' cannot be converted to 'short'.
short b = -a; // #error: 'int!' cannot be converted to 'short'
}
func void test2()
{
int! a = 1;
try(-a);
int b = -a; // #error: 'int!' cannot be converted to 'int'
int b = -a; // #error: 'int!' to 'int'
}
func void test3()
{
long! a = 1;
try(-a);
long b = -a; // #error: 'long!' cannot be converted to 'long'
long b = -a; // #error: 'long!' to 'long'
}
func void test4()
{
short! a = 1;
try(~a);
short b = ~a; // #error: 'short!' cannot be converted to 'short'
short b = ~a; // #error: 'short!' to 'short'
}
func void test5()
{
int! a = 1;
try(~a);
int b = ~a; // #error: 'int!' cannot be converted to 'int'
int b = ~a; // #error: 'int!' to 'int'
}
func void test6()
{
long! a = 1;
try(~a);
long b = ~a; // #error: 'long!' cannot be converted to 'long'
long b = ~a; // #error: 'long!' to 'long'
}

View File

@@ -32,158 +32,144 @@ func void main()
define void @main() #0 {
entry:
%a = alloca i32, align 4
%a.f = alloca i64, align 8
%x = alloca i32, align 4
%blockret = alloca i32, align 4
%b = alloca i32, align 4
%b.f = alloca i64, align 8
%x1 = alloca i32, align 4
%blockret2 = alloca i32, align 4
%c = alloca i32, align 4
%c.f = alloca i64, align 8
%x8 = alloca i32, align 4
%blockret9 = alloca i32, align 4
%error_var = alloca i64, align 8
store i32 1, i32* %x, align 4
%0 = load i32, i32* %x, align 4
%intbool = icmp ne i32 %0, 0
br i1 %intbool, label %if.then, label %if.exit
%a.f = alloca i64, align 8
%x = alloca i32, align 4
%blockret = alloca i32, align 4
%b = alloca i32, align 4
%b.f = alloca i64, align 8
%x1 = alloca i32, align 4
%blockret2 = alloca i32, align 4
%c = alloca i32, align 4
%c.f = alloca i64, align 8
%x8 = alloca i32, align 4
%blockret9 = alloca i32, align 4
store i32 1, i32* %x, align 4
%0 = load i32, i32* %x, align 4
%intbool = icmp ne i32 %0, 0
br i1 %intbool, label %if.then, label %if.exit
if.then: ; preds = %entry
%1 = load i32, i32* %x, align 4
store i32 %1, i32* %blockret, align 4
br label %expr_block.exit
if.then: ; preds = %entry
%1 = load i32, i32* %x, align 4
store i32 %1, i32* %blockret, align 4
br label %expr_block.exit
if.exit: ; preds = %entry
store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %a.f, align 8
br label %after_assign
if.exit: ; preds = %entry
store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %a.f, align 8
br label %after_assign
expr_block.exit: ; preds = %if.then
%2 = load i32, i32* %blockret, align 4
store i32 %2, i32* %a, align 4
store i64 0, i64* %a.f, align 8
br label %after_assign
expr_block.exit: ; preds = %if.then
%2 = load i32, i32* %blockret, align 4
store i32 %2, i32* %a, align 4
store i64 0, i64* %a.f, align 8
br label %after_assign
after_assign: ; preds = %expr_block.exit, %if.exit
%3 = load i64, i64* %a.f, align 8
%not_err = icmp eq i64 %3, 0
br i1 %not_err, label %after_check, label %else_block
after_assign: ; preds = %expr_block.exit, %if.exit
%3 = load i64, i64* %a.f, align 8
%not_err = icmp eq i64 %3, 0
br i1 %not_err, label %after_check, label %else_block
after_check: ; preds = %after_assign
%4 = load i32, i32* %a, align 4
%add = add i32 %4, 3
br label %phi_block
after_check: ; preds = %after_assign
%4 = load i32, i32* %a, align 4
%add = add i32 %4, 3
br label %phi_block
else_block: ; preds = %after_assign
br label %phi_block
else_block: ; preds = %after_assign
br label %phi_block
phi_block: ; preds = %else_block, %after_check
%val = phi i32 [ %add, %after_check ], [ 2, %else_block ]
store i32 %val, i32* %x1, align 4
%5 = load i32, i32* %x1, align 4
%intbool3 = icmp ne i32 %5, 0
br i1 %intbool3, label %if.then4, label %if.exit5
phi_block: ; preds = %else_block, %after_check
%val = phi i32 [ %add, %after_check ], [ 2, %else_block ]
store i32 %val, i32* %x1, align 4
%5 = load i32, i32* %x1, align 4
%intbool3 = icmp ne i32 %5, 0
br i1 %intbool3, label %if.then4, label %if.exit5
if.then4: ; preds = %phi_block
%6 = load i32, i32* %x1, align 4
store i32 %6, i32* %blockret2, align 4
br label %expr_block.exit6
if.then4: ; preds = %phi_block
%6 = load i32, i32* %x1, align 4
store i32 %6, i32* %blockret2, align 4
br label %expr_block.exit6
if.exit5: ; preds = %phi_block
store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %b.f, align 8
br label %after_assign7
if.exit5: ; preds = %phi_block
store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %b.f, align 8
br label %after_assign7
expr_block.exit6: ; preds = %if.then4
%7 = load i32, i32* %blockret2, align 4
store i32 %7, i32* %b, align 4
store i64 0, i64* %b.f, align 8
br label %after_assign7
expr_block.exit6: ; preds = %if.then4
%7 = load i32, i32* %blockret2, align 4
store i32 %7, i32* %b, align 4
store i64 0, i64* %b.f, align 8
br label %after_assign7
after_assign7: ; preds = %expr_block.exit6, %if.exit5
store i32 0, i32* %x8, align 4
%8 = load i32, i32* %x8, align 4
%intbool10 = icmp ne i32 %8, 0
br i1 %intbool10, label %if.then11, label %if.exit12
after_assign7: ; preds = %expr_block.exit6, %if.exit5
store i32 0, i32* %x8, align 4
%8 = load i32, i32* %x8, align 4
%intbool10 = icmp ne i32 %8, 0
br i1 %intbool10, label %if.then11, label %if.exit12
if.then11: ; preds = %after_assign7
%9 = load i32, i32* %x8, align 4
store i32 %9, i32* %blockret9, align 4
br label %expr_block.exit13
if.then11: ; preds = %after_assign7
%9 = load i32, i32* %x8, align 4
store i32 %9, i32* %blockret9, align 4
br label %expr_block.exit13
if.exit12: ; preds = %after_assign7
store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %c.f, align 8
br label %after_assign14
if.exit12: ; preds = %after_assign7
store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %c.f, align 8
br label %after_assign14
expr_block.exit13: ; preds = %if.then11
%10 = load i32, i32* %blockret9, align 4
store i32 %10, i32* %c, align 4
store i64 0, i64* %c.f, align 8
br label %after_assign14
expr_block.exit13: ; preds = %if.then11
%10 = load i32, i32* %blockret9, align 4
store i32 %10, i32* %c, align 4
store i64 0, i64* %c.f, align 8
br label %after_assign14
after_assign14: ; preds = %expr_block.exit13, %if.exit12
%11 = load i64, i64* %a.f, align 8
%not_err15 = icmp eq i64 %11, 0
br i1 %not_err15, label %after_check16, label %voiderr
after_assign14: ; preds = %expr_block.exit13, %if.exit12
%11 = load i64, i64* %a.f, align 8
%not_err15 = icmp eq i64 %11, 0
br i1 %not_err15, label %after_check16, label %voiderr
after_check16: ; preds = %after_assign14
%12 = load i32, i32* %a, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 %12)
br label %voiderr
after_check16: ; preds = %after_assign14
%12 = load i32, i32* %a, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 %12)
br label %voiderr
voiderr: ; preds = %after_check16, %after_assign14
%13 = load i64, i64* %b.f, align 8
%not_err17 = icmp eq i64 %13, 0
br i1 %not_err17, label %after_check18, label %voiderr19
voiderr: ; preds = %after_check16, %after_assign14
%13 = load i64, i64* %b.f, align 8
%not_err17 = icmp eq i64 %13, 0
br i1 %not_err17, label %after_check18, label %voiderr19
after_check18: ; preds = %voiderr
%14 = load i32, i32* %b, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 %14)
br label %voiderr19
after_check18: ; preds = %voiderr
%14 = load i32, i32* %b, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 %14)
br label %voiderr19
voiderr19: ; preds = %after_check18, %voiderr
%15 = load i64, i64* %c.f, align 8
%not_err20 = icmp eq i64 %15, 0
br i1 %not_err20, label %after_check21, label %voiderr22
voiderr19: ; preds = %after_check18, %voiderr
%15 = load i64, i64* %c.f, align 8
%not_err20 = icmp eq i64 %15, 0
br i1 %not_err20, label %after_check21, label %voiderr22
after_check21: ; preds = %voiderr19
%16 = load i32, i32* %c, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i32 %16)
br label %voiderr22
after_check21: ; preds = %voiderr19
%16 = load i32, i32* %c, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i32 %16)
br label %voiderr22
voiderr22: ; preds = %after_check21, %voiderr19
store i64 0, i64* %error_var, align 8
%17 = load i64, i64* %c.f, align 8
%not_err23 = icmp eq i64 %17, 0
br i1 %not_err23, label %after_check24, label %error
voiderr22: ; preds = %after_check21, %voiderr19
%17 = load i64, i64* %c.f, align 8
%neq = icmp ne i64 %17, 0
br i1 %neq, label %if.then23, label %if.exit24
error: ; preds = %voiderr22
store i64 %17, i64* %error_var, align 8
br label %noerr_block
if.then23: ; preds = %voiderr22
call void (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i32 0, i32 0))
br label %if.exit24
after_check24: ; preds = %voiderr22
br label %noerr_block
if.exit24: ; preds = %if.then23, %voiderr22
store i32 3, i32* %c, align 4
store i64 0, i64* %c.f, align 8
%18 = load i64, i64* %c.f, align 8
%not_err25 = icmp eq i64 %18, 0
br i1 %not_err25, label %after_check26, label %voiderr27
noerr_block: ; preds = %after_check24, %error
%18 = load i64, i64* %error_var, align 8
%neq = icmp ne i64 %18, 0
br i1 %neq, label %if.then25, label %if.exit26
after_check26: ; preds = %if.exit24
%19 = load i32, i32* %c, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.4, i32 0, i32 0), i32 %19)
br label %voiderr27
if.then25: ; preds = %noerr_block
call void (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i32 0, i32 0))
br label %if.exit26
if.exit26: ; preds = %if.then25, %noerr_block
store i32 3, i32* %c, align 4
store i64 0, i64* %c.f, align 8
%19 = load i64, i64* %c.f, align 8
%not_err27 = icmp eq i64 %19, 0
br i1 %not_err27, label %after_check28, label %voiderr29
after_check28: ; preds = %if.exit26
%20 = load i32, i32* %c, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.4, i32 0, i32 0), i32 %20)
br label %voiderr29
voiderr29: ; preds = %after_check28, %if.exit26
ret void
}
voiderr27: ; preds = %after_check26, %if.exit24
ret void
}

View File

@@ -0,0 +1,11 @@
int z;
errtype MyError
{
FOO,
}
fn void test(int a = z) {} // #error: Only constant expressions may be used as default values
fn void test2(int b = MyError.FOO!) {} // #error: Default arguments may not be failable

View File

@@ -19,9 +19,9 @@ func void test()
%varargslots = alloca [3 x i32], align 4
%x = alloca [3 x i32], align 4
%z = alloca %"int[]", align 8
%vararg3 = alloca %"int[]", align 8
%vararg9 = alloca %"int[]", align 8
%vararg15 = alloca %"int[]", align 8
%vararg1 = alloca %"int[]", align 8
%vararg4 = alloca %"int[]", align 8
%vararg7 = alloca %"int[]", align 8
%0 = getelementptr inbounds [3 x i32], [3 x i32]* %varargslots, i64 0, i64 0
store i32 1, i32* %0, align 4
%1 = getelementptr inbounds [3 x i32], [3 x i32]* %varargslots, i64 0, i64 1
@@ -33,43 +33,43 @@ func void test()
%4 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0
%5 = bitcast [3 x i32]* %varargslots to i32*
store i32* %5, i32** %4, align 8
%casttemp = bitcast %"int[]"* %vararg to { i8*, i64 }*
%lo = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp, i32 0, i32 0
%lo1 = load i8*, i8** %lo, align 8
%hi = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp, i32 0, i32 1
%hi2 = load i64, i64* %hi, align 8
%6 = call i32 @sum_us(i8* %lo1, i64 %hi2)
%7 = bitcast [3 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %7, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
%8 = bitcast [3 x i32]* %x to i32*
%9 = insertvalue %"int[]" undef, i32* %8, 0
%10 = insertvalue %"int[]" %9, i64 3, 1
store %"int[]" %10, %"int[]"* %z, align 8
%11 = getelementptr inbounds %"int[]", %"int[]"* %vararg3, i32 0, i32 1
%12 = getelementptr inbounds %"int[]", %"int[]"* %vararg3, i32 0, i32 0
store i64 3, i64* %11, align 8
%13 = bitcast [3 x i32]* %x to i32*
store i32* %13, i32** %12, align 8
%casttemp4 = bitcast %"int[]"* %vararg3 to { i8*, i64 }*
%lo5 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp4, i32 0, i32 0
%lo6 = load i8*, i8** %lo5, align 8
%hi7 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp4, i32 0, i32 1
%hi8 = load i64, i64* %hi7, align 8
%14 = call i32 @sum_us(i8* %lo6, i64 %hi8)
%15 = getelementptr inbounds %"int[]", %"int[]"* %vararg9, i32 0, i32 1
%16 = getelementptr inbounds %"int[]", %"int[]"* %vararg9, i32 0, i32 0
%casttemp10 = bitcast %"int[]"* %z to { i8*, i64 }*
%lo11 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp10, i32 0, i32 0
%lo12 = load i8*, i8** %lo11, align 8
%hi13 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp10, i32 0, i32 1
%hi14 = load i64, i64* %hi13, align 8
%17 = call i32 @sum_us(i8* %lo12, i64 %hi14)
%18 = getelementptr inbounds %"int[]", %"int[]"* %vararg15, i32 0, i32 1
store i64 0, i64* %18, align 8
%casttemp16 = bitcast %"int[]"* %vararg15 to { i8*, i64 }*
%lo17 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp16, i32 0, i32 0
%lo18 = load i8*, i8** %lo17, align 8
%hi19 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp16, i32 0, i32 1
%hi20 = load i64, i64* %hi19, align 8
%19 = call i32 @sum_us(i8* %lo18, i64 %hi20)
%6 = bitcast %"int[]"* %vararg to { i8*, i64 }*
%7 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %6, i32 0, i32 0
%lo = load i8*, i8** %7, align 8
%8 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %6, i32 0, i32 1
%hi = load i64, i64* %8, align 8
%9 = call i32 @sum_us(i8* %lo, i64 %hi)
%10 = bitcast [3 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %10, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
%11 = bitcast [3 x i32]* %x to i32*
%12 = insertvalue %"int[]" undef, i32* %11, 0
%13 = insertvalue %"int[]" %12, i64 3, 1
store %"int[]" %13, %"int[]"* %z, align 8
%14 = getelementptr inbounds %"int[]", %"int[]"* %vararg1, i32 0, i32 1
%15 = getelementptr inbounds %"int[]", %"int[]"* %vararg1, i32 0, i32 0
store i64 3, i64* %14, align 8
%16 = bitcast [3 x i32]* %x to i32*
store i32* %16, i32** %15, align 8
%17 = bitcast %"int[]"* %vararg1 to { i8*, i64 }*
%18 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %17, i32 0, i32 0
%lo2 = load i8*, i8** %18, align 8
%19 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %17, i32 0, i32 1
%hi3 = load i64, i64* %19, align 8
%20 = call i32 @sum_us(i8* %lo2, i64 %hi3)
%21 = getelementptr inbounds %"int[]", %"int[]"* %vararg4, i32 0, i32 1
%22 = getelementptr inbounds %"int[]", %"int[]"* %vararg4, i32 0, i32 0
%23 = bitcast %"int[]"* %z to { i8*, i64 }*
%24 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %23, i32 0, i32 0
%lo5 = load i8*, i8** %24, align 8
%25 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %23, i32 0, i32 1
%hi6 = load i64, i64* %25, align 8
%26 = call i32 @sum_us(i8* %lo5, i64 %hi6)
%27 = getelementptr inbounds %"int[]", %"int[]"* %vararg7, i32 0, i32 1
store i64 0, i64* %27, align 8
%28 = bitcast %"int[]"* %vararg7 to { i8*, i64 }*
%29 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %28, i32 0, i32 0
%lo8 = load i8*, i8** %29, align 8
%30 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %28, i32 0, i32 1
%hi9 = load i64, i64* %30, align 8
%31 = call i32 @sum_us(i8* %lo8, i64 %hi9)
ret void

View File

@@ -268,6 +268,7 @@ entry:
ret void
}
; Function Attrs: nounwind
define i32 @test.Foo2__mutate(%Foo2* %0) #0 {
entry:
%foo = alloca %Foo2*, align 8
@@ -281,14 +282,17 @@ entry:
ret i32 %add
}
; Function Attrs: nounwind
declare i32 @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @test.helloWorld() #0 {
entry:
%0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i32 0, i32 0))
ret void
}
; Function Attrs: nounwind
define i32 @test.test_static() #0 {
entry:
%0 = load i32, i32* @test_static.x, align 4
@@ -300,6 +304,7 @@ entry:
ret i32 %3
}
; Function Attrs: nounwind
define i32 @test.helo(double %0, %Bobo* byval(%Bobo) align 8 %1) #0 {
entry:
%d = alloca double, align 8
@@ -323,6 +328,7 @@ entry:
ret i32 1
}
; Function Attrs: nounwind
define i32 @test.test1(i32 %0, i32 %1) #0 {
entry:
%a = alloca i32, align 4
@@ -346,10 +352,13 @@ if.exit: ; preds = %entry
ret i32 %6
}
; Function Attrs: nounwind
declare void @test_virtual3(i64, i8*) #0
; Function Attrs: nounwind
declare void @test_virtual2(i8*, i8*) #0
; Function Attrs: nounwind
define i32 @test.sum_us(i8* %0, i64 %1) #0 {
entry:
%x = alloca %"int[]", align 8
@@ -357,97 +366,99 @@ entry:
%vararg = alloca %"int[]", align 8
%taddr = alloca %"int[]", align 8
%pair = bitcast %"int[]"* %x to { i8*, i64 }*
%lo = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0
store i8* %0, i8** %lo, align 8
%hi = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %hi, align 8
%2 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0
store i8* %0, i8** %2, align 8
%3 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %3, align 8
store i32 0, i32* %sum, align 4
%len = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%2 = load i64, i64* %len, align 8
%eq = icmp eq i64 0, %2
%4 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%5 = load i64, i64* %4, align 8
%eq = icmp eq i64 0, %5
br i1 %eq, label %if.then, label %if.exit
if.then: ; preds = %entry
ret i32 0
if.exit: ; preds = %entry
%3 = load i32, i32* %sum, align 4
%subarrayptr = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%saptr = load i32*, i32** %subarrayptr, align 8
%sarridx = getelementptr inbounds i32, i32* %saptr, i64 0
%4 = load i32, i32* %sarridx, align 4
%5 = load %"int[]", %"int[]"* %x, align 8
%6 = extractvalue %"int[]" %5, 0
%7 = extractvalue %"int[]" %5, 1
%sub = sub i64 %7, 1
%8 = add i64 %sub, 1
%size = sub i64 %8, 1
%offsetsub = getelementptr inbounds i32, i32* %6, i64 1
%9 = insertvalue %"int[]" undef, i32* %offsetsub, 0
%10 = insertvalue %"int[]" %9, i64 %size, 1
%11 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 1
%12 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0
store %"int[]" %10, %"int[]"* %taddr, align 8
%casttemp = bitcast %"int[]"* %taddr to { i8*, i64 }*
%lo1 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp, i32 0, i32 0
%lo2 = load i8*, i8** %lo1, align 8
%hi3 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp, i32 0, i32 1
%hi4 = load i64, i64* %hi3, align 8
%13 = call i32 @test.sum_us(i8* %lo2, i64 %hi4)
%add = add i32 %4, %13
%add5 = add i32 %3, %add
store i32 %add5, i32* %sum, align 4
%14 = load i32, i32* %sum, align 4
ret i32 %14
%6 = load i32, i32* %sum, align 4
%7 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%8 = load i32*, i32** %7, align 8
%ptroffset = getelementptr inbounds i32, i32* %8, i64 0
%9 = load i32, i32* %ptroffset, align 4
%10 = load %"int[]", %"int[]"* %x, align 8
%11 = extractvalue %"int[]" %10, 0
%12 = extractvalue %"int[]" %10, 1
%sub = sub i64 %12, 1
%13 = add i64 %sub, 1
%size = sub i64 %13, 1
%ptroffset1 = getelementptr inbounds i32, i32* %11, i64 1
%14 = insertvalue %"int[]" undef, i32* %ptroffset1, 0
%15 = insertvalue %"int[]" %14, i64 %size, 1
%16 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 1
%17 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0
store %"int[]" %15, %"int[]"* %taddr, align 8
%18 = bitcast %"int[]"* %taddr to { i8*, i64 }*
%19 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %18, i32 0, i32 0
%lo = load i8*, i8** %19, align 8
%20 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %18, i32 0, i32 1
%hi = load i64, i64* %20, align 8
%21 = call i32 @test.sum_us(i8* %lo, i64 %hi)
%add = add i32 %9, %21
%add2 = add i32 %6, %add
store i32 %add2, i32* %sum, align 4
%22 = load i32, i32* %sum, align 4
ret i32 %22
}
; Function Attrs: nounwind
define i32 @test.sumd(i8* %0, i64 %1) #0 {
entry:
%x = alloca %"int[]", align 8
%sum = alloca i32, align 4
%i = alloca i32, align 4
%pair = bitcast %"int[]"* %x to { i8*, i64 }*
%lo = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0
store i8* %0, i8** %lo, align 8
%hi = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %hi, align 8
%2 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0
store i8* %0, i8** %2, align 8
%3 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %3, align 8
store i32 0, i32* %sum, align 4
store i32 0, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%2 = load i32, i32* %i, align 4
%sisiext = sext i32 %2 to i64
%len = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%3 = load i64, i64* %len, align 8
%lt = icmp slt i64 %sisiext, %3
%check = icmp slt i64 %3, 0
%4 = load i32, i32* %i, align 4
%sisiext = sext i32 %4 to i64
%5 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%6 = load i64, i64* %5, align 8
%lt = icmp slt i64 %sisiext, %6
%check = icmp slt i64 %6, 0
%siui-lt = or i1 %check, %lt
br i1 %siui-lt, label %for.body, label %for.exit
for.body: ; preds = %for.cond
%4 = load i32, i32* %sum, align 4
%subarrayptr = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%saptr = load i32*, i32** %subarrayptr, align 8
%5 = load i32, i32* %i, align 4
%sisiext1 = sext i32 %5 to i64
%sarridx = getelementptr inbounds i32, i32* %saptr, i64 %sisiext1
%6 = load i32, i32* %sarridx, align 4
%add = add i32 %4, %6
%7 = load i32, i32* %sum, align 4
%8 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%9 = load i32*, i32** %8, align 8
%10 = load i32, i32* %i, align 4
%sisiext1 = sext i32 %10 to i64
%ptroffset = getelementptr inbounds i32, i32* %9, i64 %sisiext1
%11 = load i32, i32* %ptroffset, align 4
%add = add i32 %7, %11
store i32 %add, i32* %sum, align 4
br label %for.inc
for.inc: ; preds = %for.body
%7 = load i32, i32* %i, align 4
%add2 = add i32 %7, 1
%12 = load i32, i32* %i, align 4
%add2 = add i32 %12, 1
store i32 %add2, i32* %i, align 4
br label %for.cond
for.exit: ; preds = %for.cond
%8 = load i32, i32* %sum, align 4
ret i32 %8
%13 = load i32, i32* %sum, align 4
ret i32 %13
}
; Function Attrs: nounwind
define void @main() #0 {
entry:
%list = alloca %LinkedList, align 8
@@ -466,13 +477,13 @@ entry:
%vararg = alloca %"int[]", align 8
%z = alloca %"int[]", align 8
%de = alloca [3 x i32], align 4
%vararg11 = alloca %"int[]", align 8
%vararg14 = alloca %"int[]", align 8
%vararg20 = alloca %"int[]", align 8
%vararg26 = alloca %"int[]", align 8
%vararg17 = alloca %"int[]", align 8
%varargslots = alloca [4 x i32], align 16
%vararg32 = alloca %"int[]", align 8
%varargslots33 = alloca [1 x i32], align 4
%vararg39 = alloca %"int[]", align 8
%vararg20 = alloca %"int[]", align 8
%varargslots21 = alloca [1 x i32], align 4
%vararg24 = alloca %"int[]", align 8
%a1 = alloca i32 (double, %Bobo*)*, align 8
%b2 = alloca i32 (double, %Bobo*)*, align 8
%0 = call i32 @test.test_static()
@@ -552,114 +563,114 @@ for.exit9: ; preds = %for.cond2
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob* @.__const.6 to i8*), i32 4, i1 false)
%22 = bitcast %Blob.0* %b to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.0* @.__const.7 to i8*), i32 8, i1 false)
%dive = getelementptr inbounds %Blob, %Blob* %a, i32 0, i32 0
%23 = load i32, i32* %dive, align 4
%24 = call i32 @test2.int.getValue(i32 %23)
%25 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i32 %24)
%dive10 = getelementptr inbounds %Blob.0, %Blob.0* %b, i32 0, i32 0
%26 = bitcast double* %tempcoerce to i8*
%27 = bitcast double* %dive10 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %26, i8* align 8 %27, i32 8, i1 false)
%28 = load double, double* %tempcoerce, align 8
%29 = call double @test2.double.getValue(double %28)
%30 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), double %29)
%31 = call i32 @test2.int.getMult(i32 25)
%32 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.10, i32 0, i32 0), i32 %31)
%33 = call double @test2.double.getMult(double 3.300000e+00)
%34 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.11, i32 0, i32 0), double %33)
%23 = getelementptr inbounds %Blob, %Blob* %a, i32 0, i32 0
%24 = load i32, i32* %23, align 4
%25 = call i32 @test2.int.getValue(i32 %24)
%26 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i32 %25)
%27 = getelementptr inbounds %Blob.0, %Blob.0* %b, i32 0, i32 0
%28 = bitcast double* %tempcoerce to i8*
%29 = bitcast double* %27 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %28, i8* align 8 %29, i32 8, i1 false)
%30 = load double, double* %tempcoerce, align 8
%31 = call double @test2.double.getValue(double %30)
%32 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), double %31)
%33 = call i32 @test2.int.getMult(i32 25)
%34 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.10, i32 0, i32 0), i32 %33)
%35 = call double @test2.double.getMult(double 3.300000e+00)
%36 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.11, i32 0, i32 0), double %35)
call void @test.helloWorld()
%35 = bitcast %Foo* %ddx to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %35, i8 0, i64 8, i1 false)
%37 = bitcast %Foo* %ddx to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %37, i8 0, i64 8, i1 false)
store i32 3, i32* %fro, align 4
%36 = bitcast [4 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %36, i8* align 16 bitcast ([4 x i32]* @.__const.12 to i8*), i32 16, i1 false)
%37 = load i32, i32* %fro, align 4
%38 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 1
%39 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0
store i64 4, i64* %38, align 8
%40 = bitcast [4 x i32]* %x to i32*
store i32* %40, i32** %39, align 8
%casttemp = bitcast %"int[]"* %vararg to { i8*, i64 }*
%lo = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp, i32 0, i32 0
%lo11 = load i8*, i8** %lo, align 8
%hi = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp, i32 0, i32 1
%hi12 = load i64, i64* %hi, align 8
%41 = call i32 @test.sum_us(i8* %lo11, i64 %hi12)
%42 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.13, i32 0, i32 0), i32 %41)
%add13 = add i32 %37, %42
store i32 %add13, i32* %fro, align 4
%43 = load i32, i32* %fro, align 4
%44 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.14, i32 0, i32 0), i32 %43)
%45 = bitcast [4 x i32]* %x to i32*
%46 = insertvalue %"int[]" undef, i32* %45, 0
%47 = insertvalue %"int[]" %46, i64 4, 1
store %"int[]" %47, %"int[]"* %z, align 8
%48 = bitcast [3 x i32]* %de to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %48, i8* align 4 bitcast ([3 x i32]* @.__const.15 to i8*), i32 12, i1 false)
%49 = getelementptr inbounds %"int[]", %"int[]"* %vararg14, i32 0, i32 1
%50 = getelementptr inbounds %"int[]", %"int[]"* %vararg14, i32 0, i32 0
store i64 4, i64* %49, align 8
%51 = bitcast [4 x i32]* %x to i32*
store i32* %51, i32** %50, align 8
%casttemp15 = bitcast %"int[]"* %vararg14 to { i8*, i64 }*
%lo16 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp15, i32 0, i32 0
%lo17 = load i8*, i8** %lo16, align 8
%hi18 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp15, i32 0, i32 1
%hi19 = load i64, i64* %hi18, align 8
%52 = call i32 @test.sum_us(i8* %lo17, i64 %hi19)
%53 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.16, i32 0, i32 0), i32 %52)
%54 = getelementptr inbounds %"int[]", %"int[]"* %vararg20, i32 0, i32 1
%55 = getelementptr inbounds %"int[]", %"int[]"* %vararg20, i32 0, i32 0
%casttemp21 = bitcast %"int[]"* %z to { i8*, i64 }*
%lo22 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp21, i32 0, i32 0
%lo23 = load i8*, i8** %lo22, align 8
%hi24 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp21, i32 0, i32 1
%hi25 = load i64, i64* %hi24, align 8
%56 = call i32 @test.sum_us(i8* %lo23, i64 %hi25)
%57 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.17, i32 0, i32 0), i32 %56)
%58 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 0
store i32 1, i32* %58, align 4
%59 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 1
store i32 2, i32* %59, align 4
%60 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 2
store i32 4, i32* %60, align 4
%61 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 3
store i32 5, i32* %61, align 4
%62 = getelementptr inbounds %"int[]", %"int[]"* %vararg26, i32 0, i32 1
store i64 4, i64* %62, align 8
%63 = getelementptr inbounds %"int[]", %"int[]"* %vararg26, i32 0, i32 0
%64 = bitcast [4 x i32]* %varargslots to i32*
store i32* %64, i32** %63, align 8
%casttemp27 = bitcast %"int[]"* %vararg26 to { i8*, i64 }*
%lo28 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp27, i32 0, i32 0
%lo29 = load i8*, i8** %lo28, align 8
%hi30 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp27, i32 0, i32 1
%hi31 = load i64, i64* %hi30, align 8
%65 = call i32 @test.sum_us(i8* %lo29, i64 %hi31)
%66 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.18, i32 0, i32 0), i32 %65)
%67 = getelementptr inbounds [1 x i32], [1 x i32]* %varargslots33, i64 0, i64 0
store i32 1, i32* %67, align 4
%68 = getelementptr inbounds %"int[]", %"int[]"* %vararg32, i32 0, i32 1
store i64 1, i64* %68, align 8
%69 = getelementptr inbounds %"int[]", %"int[]"* %vararg32, i32 0, i32 0
%70 = bitcast [1 x i32]* %varargslots33 to i32*
store i32* %70, i32** %69, align 8
%casttemp34 = bitcast %"int[]"* %vararg32 to { i8*, i64 }*
%lo35 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp34, i32 0, i32 0
%lo36 = load i8*, i8** %lo35, align 8
%hi37 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp34, i32 0, i32 1
%hi38 = load i64, i64* %hi37, align 8
%71 = call i32 @test.sum_us(i8* %lo36, i64 %hi38)
%72 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.19, i32 0, i32 0), i32 %71)
%73 = getelementptr inbounds %"int[]", %"int[]"* %vararg39, i32 0, i32 1
store i64 0, i64* %73, align 8
%casttemp40 = bitcast %"int[]"* %vararg39 to { i8*, i64 }*
%lo41 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp40, i32 0, i32 0
%lo42 = load i8*, i8** %lo41, align 8
%hi43 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %casttemp40, i32 0, i32 1
%hi44 = load i64, i64* %hi43, align 8
%74 = call i32 @test.sum_us(i8* %lo42, i64 %hi44)
%75 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.20, i32 0, i32 0), i32 %74)
%38 = bitcast [4 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %38, i8* align 16 bitcast ([4 x i32]* @.__const.12 to i8*), i32 16, i1 false)
%39 = load i32, i32* %fro, align 4
%40 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 1
%41 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0
store i64 4, i64* %40, align 8
%42 = bitcast [4 x i32]* %x to i32*
store i32* %42, i32** %41, align 8
%43 = bitcast %"int[]"* %vararg to { i8*, i64 }*
%44 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %43, i32 0, i32 0
%lo = load i8*, i8** %44, align 8
%45 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %43, i32 0, i32 1
%hi = load i64, i64* %45, align 8
%46 = call i32 @test.sum_us(i8* %lo, i64 %hi)
%47 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.13, i32 0, i32 0), i32 %46)
%add10 = add i32 %39, %47
store i32 %add10, i32* %fro, align 4
%48 = load i32, i32* %fro, align 4
%49 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.14, i32 0, i32 0), i32 %48)
%50 = bitcast [4 x i32]* %x to i32*
%51 = insertvalue %"int[]" undef, i32* %50, 0
%52 = insertvalue %"int[]" %51, i64 4, 1
store %"int[]" %52, %"int[]"* %z, align 8
%53 = bitcast [3 x i32]* %de to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %53, i8* align 4 bitcast ([3 x i32]* @.__const.15 to i8*), i32 12, i1 false)
%54 = getelementptr inbounds %"int[]", %"int[]"* %vararg11, i32 0, i32 1
%55 = getelementptr inbounds %"int[]", %"int[]"* %vararg11, i32 0, i32 0
store i64 4, i64* %54, align 8
%56 = bitcast [4 x i32]* %x to i32*
store i32* %56, i32** %55, align 8
%57 = bitcast %"int[]"* %vararg11 to { i8*, i64 }*
%58 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %57, i32 0, i32 0
%lo12 = load i8*, i8** %58, align 8
%59 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %57, i32 0, i32 1
%hi13 = load i64, i64* %59, align 8
%60 = call i32 @test.sum_us(i8* %lo12, i64 %hi13)
%61 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.16, i32 0, i32 0), i32 %60)
%62 = getelementptr inbounds %"int[]", %"int[]"* %vararg14, i32 0, i32 1
%63 = getelementptr inbounds %"int[]", %"int[]"* %vararg14, i32 0, i32 0
%64 = bitcast %"int[]"* %z to { i8*, i64 }*
%65 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %64, i32 0, i32 0
%lo15 = load i8*, i8** %65, align 8
%66 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %64, i32 0, i32 1
%hi16 = load i64, i64* %66, align 8
%67 = call i32 @test.sum_us(i8* %lo15, i64 %hi16)
%68 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.17, i32 0, i32 0), i32 %67)
%69 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 0
store i32 1, i32* %69, align 4
%70 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 1
store i32 2, i32* %70, align 4
%71 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 2
store i32 4, i32* %71, align 4
%72 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 3
store i32 5, i32* %72, align 4
%73 = getelementptr inbounds %"int[]", %"int[]"* %vararg17, i32 0, i32 1
store i64 4, i64* %73, align 8
%74 = getelementptr inbounds %"int[]", %"int[]"* %vararg17, i32 0, i32 0
%75 = bitcast [4 x i32]* %varargslots to i32*
store i32* %75, i32** %74, align 8
%76 = bitcast %"int[]"* %vararg17 to { i8*, i64 }*
%77 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %76, i32 0, i32 0
%lo18 = load i8*, i8** %77, align 8
%78 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %76, i32 0, i32 1
%hi19 = load i64, i64* %78, align 8
%79 = call i32 @test.sum_us(i8* %lo18, i64 %hi19)
%80 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.18, i32 0, i32 0), i32 %79)
%81 = getelementptr inbounds [1 x i32], [1 x i32]* %varargslots21, i64 0, i64 0
store i32 1, i32* %81, align 4
%82 = getelementptr inbounds %"int[]", %"int[]"* %vararg20, i32 0, i32 1
store i64 1, i64* %82, align 8
%83 = getelementptr inbounds %"int[]", %"int[]"* %vararg20, i32 0, i32 0
%84 = bitcast [1 x i32]* %varargslots21 to i32*
store i32* %84, i32** %83, align 8
%85 = bitcast %"int[]"* %vararg20 to { i8*, i64 }*
%86 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %85, i32 0, i32 0
%lo22 = load i8*, i8** %86, align 8
%87 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %85, i32 0, i32 1
%hi23 = load i64, i64* %87, align 8
%88 = call i32 @test.sum_us(i8* %lo22, i64 %hi23)
%89 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.19, i32 0, i32 0), i32 %88)
%90 = getelementptr inbounds %"int[]", %"int[]"* %vararg24, i32 0, i32 1
store i64 0, i64* %90, align 8
%91 = bitcast %"int[]"* %vararg24 to { i8*, i64 }*
%92 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %91, i32 0, i32 0
%lo25 = load i8*, i8** %92, align 8
%93 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %91, i32 0, i32 1
%hi26 = load i64, i64* %93, align 8
%94 = call i32 @test.sum_us(i8* %lo25, i64 %hi26)
%95 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.20, i32 0, i32 0), i32 %94)
store i32 (double, %Bobo*)* null, i32 (double, %Bobo*)** %a1, align 8
store i32 (double, %Bobo*)* null, i32 (double, %Bobo*)** %b2, align 8
ret void
@@ -708,11 +719,11 @@ entry:
define i32 @test2.int.getValue(i32 %0)
entry:
%blob = alloca %Blob, align 4
%dive = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
store i32 %0, i32* %dive, align 4
%1 = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%2 = load i32, i32* %1, align 4
ret i32 %2
store i32 %0, i32* %1, align 4
%2 = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%3 = load i32, i32* %2, align 4
ret i32 %3
// #expect: test2.double.ll
@@ -736,8 +747,8 @@ entry:
define double @test2.double.getValue(double %0)
entry:
%blob = alloca %Blob, align 8
%dive = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
store double %0, double* %dive, align 8
%1 = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%2 = load double, double* %1, align 8
ret double %2
store double %0, double* %1, align 8
%2 = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%3 = load double, double* %2, align 8
ret double %3

View File

@@ -245,7 +245,7 @@ func Type getValue(Blob blob)
return blob.a;
}
// #expect: test.ll
/* #expect: test.ll
%Blob = type { i32 }
%Blob.0 = type { double }
@@ -259,7 +259,125 @@ func Type getValue(Blob blob)
%"int[]" = type { i32*, i64 }
%Foo = type { i32, i32 }
define void @test.Foo2__printme(%Foo2* %0)
@test2.int.argh = external global i32
@Bobo = linkonce_odr constant i8 1
@Blob = linkonce_odr constant i8 1
@Foor = linkonce_odr constant i8 1
@Foo2 = linkonce_odr constant i8 1
@Foo = linkonce_odr constant i8 1
@.str = private constant [13 x i8] c"helloWorld!\0A\00", align 1
@test_static.x = hidden global i32 1, align 4
@.str.1 = private constant [16 x i8] c"Test static %d\0A\00", align 1
@.__const = private constant [3 x i32] [i32 1, i32 2, i32 3], align 4
@.str.2 = private constant [17 x i8] c"Element[%d]: %d\0A\00", align 1
@.str.3 = private constant [28 x i8] c"Min %d Max %d Elements: %d\0A\00", align 1
@.str.4 = private constant [7 x i8] c"Hello\0A\00", align 1
@.str.5 = private constant [17 x i8] c"Element[%d]: %d\0A\00", align 1
@.__const.6 = private constant %Blob { i32 42 }, align 4
@.__const.7 = private constant %Blob.0 { double 3.330000e+01 }, align 8
@.str.8 = private constant [10 x i8] c"a was %d\0A\00", align 1
@.str.9 = private constant [10 x i8] c"b was %f\0A\00", align 1
@.str.10 = private constant [17 x i8] c"Mult int was %d\0A\00", align 1
@.str.11 = private constant [20 x i8] c"Mult double was %f\0A\00", align 1
@.__const.12 = private constant [4 x i32] [i32 1, i32 2, i32 3, i32 3], align 4
@.str.13 = private constant [22 x i8] c"1Vararg4unsplatA: %d\0A\00", align 1
@.str.14 = private constant [4 x i8] c"%d\0A\00", align 1
@.__const.15 = private constant [3 x i32] [i32 1, i32 2, i32 3], align 4
@.str.16 = private constant [21 x i8] c"Vararg4unsplatB: %d\0A\00", align 1
@.str.17 = private constant [21 x i8] c"Vararg4unsplatC: %d\0A\00", align 1
@.str.18 = private constant [13 x i8] c"Vararg4: %d\0A\00", align 1
@.str.19 = private constant [13 x i8] c"Vararg1: %d\0A\00", align 1
@.str.20 = private constant [13 x i8] c"Vararg0: %d\0A\00", align 1
@.str.21 = private constant [12 x i8] c"Foo is: %d\0A\00", align 1
@.str.22 = private constant [9 x i8] c"Mutating\00", align 1
declare i32 @test2.int.getValue(i32)
declare double @test2.double.getValue(i64)
declare i32 @test2.int.getMult(i32)
declare double @test2.double.getMult(double)
; Function Attrs: nounwind
declare void @List.ensureCapacity(%List*) #0
; Function Attrs: nounwind
declare void @"std::array::list.int.List__push"(%List*, i32) #0
; Function Attrs: nounwind
declare void @"std::array::list.int.List__append"(%List*, i32) #0
; Function Attrs: nounwind
declare i32 @"std::array::list.int.List__pop"(%List*) #0
; Function Attrs: nounwind
declare i32 @"std::array::list.int.List__popFirst"(%List*) #0
; Function Attrs: nounwind
declare void @"std::array::list.int.List__removeAt"(%List*, i64) #0
; Function Attrs: nounwind
declare void @"std::array::list.int.List__pushFront"(%List*, i32) #0
; Function Attrs: nounwind
declare void @"std::array::list.int.List__insertAt"(%List*, i64, i32) #0
; Function Attrs: nounwind
declare void @"std::array::list.int.List__removeLast"(%List*) #0
; Function Attrs: nounwind
declare void @"std::array::list.int.List__removeFirst"(%List*) #0
; Function Attrs: nounwind
declare i32* @"std::array::list.int.List__first"(%List*) #0
; Function Attrs: nounwind
declare i32* @"std::array::list.int.List__last"(%List*) #0
; Function Attrs: nounwind
declare zeroext i8 @"std::array::list.int.List__isEmpty"(%List*) #0
; Function Attrs: nounwind
declare i64 @"std::array::list.int.List__len"(%List*) #0
; Function Attrs: nounwind
declare i32 @"std::array::list.int.List__get"(%List*, i64) #0
; Function Attrs: nounwind
declare void @"std::array::list.int.List__free"(%List*) #0
; Function Attrs: nounwind
declare void @"std::array::linkedlist.int.LinkedList__push"(%LinkedList*, i32) #0
; Function Attrs: nounwind
declare void @LinkedList.linkFirst(%LinkedList*, i32) #0
; Function Attrs: nounwind
declare void @LinkedList.linkLast(%LinkedList*, i32) #0
; Function Attrs: nounwind
declare void @"std::array::linkedlist.int.LinkedList__free"(%LinkedList*) #0
; Function Attrs: nounwind
declare i64 @"std::array::linkedlist.int.LinkedList__len"(%LinkedList*) #0
; Function Attrs: nounwind
declare i32 @"std::array::linkedlist.int.LinkedList__get"(%LinkedList*, i64) #0
; Function Attrs: nounwind
declare void @LinkedList.linkBefore(%LinkedList*, %Node*, i32) #0
; Function Attrs: nounwind
declare void @LinkedList.unlinkLast(%LinkedList*, %Node*) #0
; Function Attrs: nounwind
declare void @LinkedList.unlink(%LinkedList*, %Node*) #0
declare void @hello_world.hello()
; Function Attrs: nounwind
define void @test.Foo2__printme(%Foo2* %0) #0 {
entry:
%foo = alloca %Foo2*, align 8
store %Foo2* %0, %Foo2** %foo, align 8
@@ -270,7 +388,8 @@ entry:
ret void
}
define i32 @test.Foo2__mutate(%Foo2* %0)
; Function Attrs: nounwind
define i32 @test.Foo2__mutate(%Foo2* %0) #0 {
entry:
%foo = alloca %Foo2*, align 8
store %Foo2* %0, %Foo2** %foo, align 8
@@ -283,13 +402,18 @@ entry:
ret i32 %add
}
define void @test.helloWorld()
; Function Attrs: nounwind
declare i32 @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @test.helloWorld() #0 {
entry:
%0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i32 0, i32 0))
ret void
}
define i32 @test.test_static()
; Function Attrs: nounwind
define i32 @test.test_static() #0 {
entry:
%0 = load i32, i32* @test_static.x, align 4
%add = add i32 %0, 1
@@ -300,7 +424,9 @@ entry:
ret i32 %3
}
define i32 @test.helo(double %0, %Bobo* align 4 %1)
; Function Attrs: nounwind
define i32 @test.helo(double %0, %Bobo* align 4 %1) #0 {
entry:
%d = alloca double, align 8
%b = alloca %Bobo, align 4
%de = alloca [3 x i32], align 4
@@ -322,7 +448,9 @@ define i32 @test.helo(double %0, %Bobo* align 4 %1)
ret i32 1
}
define i32 @test.test1(i32 %0, i32 %1)
; Function Attrs: nounwind
define i32 @test.test1(i32 %0, i32 %1) #0 {
entry:
%a = alloca i32, align 4
%b = alloca i32, align 4
store i32 %0, i32* %a, align 4
@@ -336,17 +464,22 @@ define i32 @test.test1(i32 %0, i32 %1)
%gt = icmp sgt i32 %5, 128
br i1 %gt, label %if.then, label %if.exit
if.then: ; preds = %entry
ret i32 -1
if.exit: ; preds = %entry
%6 = load i32, i32* %a, align 4
ret i32 %6
}
declare void @test_virtual3(%"virtual*"* align 8)
; Function Attrs: nounwind
declare void @test_virtual3(%"virtual*"* align 8) #0
declare void @test_virtual2(%"virtual$"* align 8)
; Function Attrs: nounwind
declare void @test_virtual2(%"virtual$"* align 8) #0
define i32 @test.sum_us(%"int[]"* align 8 %0)
; Function Attrs: nounwind
define i32 @test.sum_us(%"int[]"* align 8 %0) #0 {
entry:
%x = alloca %"int[]", align 8
%sum = alloca i32, align 4
@@ -356,41 +489,42 @@ entry:
%2 = bitcast %"int[]"* %0 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %1, i8* align 8 %2, i32 16, i1 false)
store i32 0, i32* %sum, align 4
%len = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%3 = load i64, i64* %len, align 8
%eq = icmp eq i64 0, %3
%3 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%4 = load i64, i64* %3, align 8
%eq = icmp eq i64 0, %4
br i1 %eq, label %if.then, label %if.exit
if.then:
if.then: ; preds = %entry
ret i32 0
if.exit:
%4 = load i32, i32* %sum, align 4
%subarrayptr = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%saptr = load i32*, i32** %subarrayptr, align 8
%sarridx = getelementptr inbounds i32, i32* %saptr, i64 0
%5 = load i32, i32* %sarridx, align 4
%6 = load %"int[]", %"int[]"* %x, align 8
%7 = extractvalue %"int[]" %6, 0
%8 = extractvalue %"int[]" %6, 1
%sub = sub i64 %8, 1
%9 = add i64 %sub, 1
%size = sub i64 %9, 1
%offsetsub = getelementptr inbounds i32, i32* %7, i64 1
%10 = insertvalue %"int[]" undef, i32* %offsetsub, 0
%11 = insertvalue %"int[]" %10, i64 %size, 1
%12 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 1
%13 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0
store %"int[]" %11, %"int[]"* %indirectarg, align 8
%14 = call i32 @test.sum_us(%"int[]"* %indirectarg)
%add = add i32 %5, %14
%add1 = add i32 %4, %add
store i32 %add1, i32* %sum, align 4
%15 = load i32, i32* %sum, align 4
ret i32 %15
if.exit: ; preds = %entry
%5 = load i32, i32* %sum, align 4
%6 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%7 = load i32*, i32** %6, align 8
%ptroffset = getelementptr inbounds i32, i32* %7, i64 0
%8 = load i32, i32* %ptroffset, align 4
%9 = load %"int[]", %"int[]"* %x, align 8
%10 = extractvalue %"int[]" %9, 0
%11 = extractvalue %"int[]" %9, 1
%sub = sub i64 %11, 1
%12 = add i64 %sub, 1
%size = sub i64 %12, 1
%ptroffset1 = getelementptr inbounds i32, i32* %10, i64 1
%13 = insertvalue %"int[]" undef, i32* %ptroffset1, 0
%14 = insertvalue %"int[]" %13, i64 %size, 1
%15 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 1
%16 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0
store %"int[]" %14, %"int[]"* %indirectarg, align 8
%17 = call i32 @test.sum_us(%"int[]"* %indirectarg)
%add = add i32 %8, %17
%add2 = add i32 %5, %add
store i32 %add2, i32* %sum, align 4
%18 = load i32, i32* %sum, align 4
ret i32 %18
}
define i32 @test.sumd(%"int[]"* align 8 %0)
; Function Attrs: nounwind
define i32 @test.sumd(%"int[]"* align 8 %0) #0 {
entry:
%x = alloca %"int[]", align 8
%sum = alloca i32, align 4
@@ -402,40 +536,41 @@ entry:
store i32 0, i32* %i, align 4
br label %for.cond
for.cond:
for.cond: ; preds = %for.inc, %entry
%3 = load i32, i32* %i, align 4
%sisiext = sext i32 %3 to i64
%len = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%4 = load i64, i64* %len, align 8
%lt = icmp slt i64 %sisiext, %4
%check = icmp slt i64 %4, 0
%4 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%5 = load i64, i64* %4, align 8
%lt = icmp slt i64 %sisiext, %5
%check = icmp slt i64 %5, 0
%siui-lt = or i1 %check, %lt
br i1 %siui-lt, label %for.body, label %for.exit
for.body:
%5 = load i32, i32* %sum, align 4
%subarrayptr = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%saptr = load i32*, i32** %subarrayptr, align 8
%6 = load i32, i32* %i, align 4
%sisiext1 = sext i32 %6 to i64
%sarridx = getelementptr inbounds i32, i32* %saptr, i64 %sisiext1
%7 = load i32, i32* %sarridx, align 4
%add = add i32 %5, %7
for.body: ; preds = %for.cond
%6 = load i32, i32* %sum, align 4
%7 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%8 = load i32*, i32** %7, align 8
%9 = load i32, i32* %i, align 4
%sisiext1 = sext i32 %9 to i64
%ptroffset = getelementptr inbounds i32, i32* %8, i64 %sisiext1
%10 = load i32, i32* %ptroffset, align 4
%add = add i32 %6, %10
store i32 %add, i32* %sum, align 4
br label %for.inc
for.inc:
%8 = load i32, i32* %i, align 4
%add2 = add i32 %8, 1
for.inc: ; preds = %for.body
%11 = load i32, i32* %i, align 4
%add2 = add i32 %11, 1
store i32 %add2, i32* %i, align 4
br label %for.cond
for.exit:
%9 = load i32, i32* %sum, align 4
ret i32 %9
for.exit: ; preds = %for.cond
%12 = load i32, i32* %sum, align 4
ret i32 %12
}
define void @main()
; Function Attrs: nounwind
define void @main() #0 {
entry:
%list = alloca %LinkedList, align 8
%i = alloca i32, align 4
@@ -454,18 +589,18 @@ entry:
%indirectarg = alloca %"int[]", align 8
%z = alloca %"int[]", align 8
%de = alloca [3 x i32], align 4
%vararg12 = alloca %"int[]", align 8
%indirectarg13 = alloca %"int[]", align 8
%vararg14 = alloca %"int[]", align 8
%indirectarg15 = alloca %"int[]", align 8
%vararg16 = alloca %"int[]", align 8
%vararg11 = alloca %"int[]", align 8
%indirectarg12 = alloca %"int[]", align 8
%vararg13 = alloca %"int[]", align 8
%indirectarg14 = alloca %"int[]", align 8
%vararg15 = alloca %"int[]", align 8
%varargslots = alloca [4 x i32], align 4
%indirectarg17 = alloca %"int[]", align 8
%vararg18 = alloca %"int[]", align 8
%varargslots19 = alloca [1 x i32], align 4
%indirectarg20 = alloca %"int[]", align 8
%vararg21 = alloca %"int[]", align 8
%indirectarg22 = alloca %"int[]", align 8
%indirectarg16 = alloca %"int[]", align 8
%vararg17 = alloca %"int[]", align 8
%varargslots18 = alloca [1 x i32], align 4
%indirectarg19 = alloca %"int[]", align 8
%vararg20 = alloca %"int[]", align 8
%indirectarg21 = alloca %"int[]", align 8
%a1 = alloca i32 (double, %Bobo*)*, align 8
%b2 = alloca i32 (double, %Bobo*)*, align 8
%0 = call i32 @test.test_static()
@@ -480,14 +615,14 @@ entry:
store i32 0, i32* %i, align 4
br label %for.cond
for.cond:
for.cond: ; preds = %for.inc, %entry
%4 = load i32, i32* %i, align 4
%5 = call i64 @"std::array::linkedlist.int.LinkedList__len"(%LinkedList* %list)
%5 = call i64 @"std::array::linkedlist.int.LinkedList__len"(%LinkedList* %list) #3
%uisitrunc = trunc i64 %5 to i32
%lt = icmp slt i32 %4, %uisitrunc
br i1 %lt, label %for.body, label %for.exit
for.body:
for.body: ; preds = %for.cond
%6 = load i32, i32* %i, align 4
%7 = load i32, i32* %i, align 4
%siuiext = zext i32 %7 to i64
@@ -495,13 +630,13 @@ for.body:
%9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.2, i32 0, i32 0), i32 %6, i32 %8)
br label %for.inc
for.inc:
for.inc: ; preds = %for.body
%10 = load i32, i32* %i, align 4
%add = add i32 %10, 1
store i32 %add, i32* %i, align 4
br label %for.cond
for.exit:
for.exit: ; preds = %for.cond
call void @"std::array::linkedlist.int.LinkedList__free"(%LinkedList* %list)
%11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.3, i32 0, i32 0), i32 -5, i32 14, i32 3)
store i32 14, i32* %max, align 4
@@ -513,19 +648,19 @@ for.exit:
call void @"std::array::list.int.List__append"(%List* %array, i32 100)
call void @"std::array::list.int.List__append"(%List* %array, i32 200)
call void @"std::array::list.int.List__append"(%List* %array, i32 400)
call void @"std::array::list.int.List__push"(%List* %array, i32 600)
call void @"std::array::list.int.List__push"(%List* %array, i32 600) #3
call void @"std::array::list.int.List__insertAt"(%List* %array, i64 2, i32 300)
store i32 0, i32* %i1, align 4
br label %for.cond2
for.cond2:
for.cond2: ; preds = %for.inc7, %for.exit
%14 = load i32, i32* %i1, align 4
%15 = call i64 @"std::array::list.int.List__len"(%List* %array)
%uisitrunc3 = trunc i64 %15 to i32
%lt4 = icmp slt i32 %14, %uisitrunc3
br i1 %lt4, label %for.body5, label %for.exit9
for.body5:
for.body5: ; preds = %for.cond2
%16 = load i32, i32* %i1, align 4
%17 = load i32, i32* %i1, align 4
%siuiext6 = zext i32 %17 to i64
@@ -533,114 +668,114 @@ for.body5:
%19 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.5, i32 0, i32 0), i32 %16, i32 %18)
br label %for.inc7
for.inc7:
for.inc7: ; preds = %for.body5
%20 = load i32, i32* %i1, align 4
%add8 = add i32 %20, 1
store i32 %add8, i32* %i1, align 4
br label %for.cond2
for.exit9:
for.exit9: ; preds = %for.cond2
call void @"std::array::list.int.List__free"(%List* %array)
%21 = bitcast %Blob* %a to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob* @.__const.6 to i8*), i32 4, i1 false)
%22 = bitcast %Blob.0* %b to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.0* @.__const.7 to i8*), i32 8, i1 false)
%dive = getelementptr inbounds %Blob, %Blob* %a, i32 0, i32 0
%23 = load i32, i32* %dive, align 4
%24 = call i32 @test2.int.getValue(i32 %23)
%25 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i32 %24)
%dive10 = getelementptr inbounds %Blob.0, %Blob.0* %b, i32 0, i32 0
%26 = bitcast i64* %tempcoerce to i8*
%27 = bitcast double* %dive10 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %26, i8* align 8 %27, i32 8, i1 false)
%28 = load i64, i64* %tempcoerce, align 8
%29 = call double @test2.double.getValue(i64 %28)
%30 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), double %29)
%31 = call i32 @test2.int.getMult(i32 25)
%32 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.10, i32 0, i32 0), i32 %31)
%33 = call double @test2.double.getMult(double 3.300000e+00)
%34 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.11, i32 0, i32 0), double %33)
%23 = getelementptr inbounds %Blob, %Blob* %a, i32 0, i32 0
%24 = load i32, i32* %23, align 4
%25 = call i32 @test2.int.getValue(i32 %24)
%26 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i32 %25)
%27 = getelementptr inbounds %Blob.0, %Blob.0* %b, i32 0, i32 0
%28 = bitcast i64* %tempcoerce to i8*
%29 = bitcast double* %27 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %28, i8* align 8 %29, i32 8, i1 false)
%30 = load i64, i64* %tempcoerce, align 8
%31 = call double @test2.double.getValue(i64 %30)
%32 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), double %31)
%33 = call i32 @test2.int.getMult(i32 25)
%34 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.10, i32 0, i32 0), i32 %33)
%35 = call double @test2.double.getMult(double 3.300000e+00)
%36 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.11, i32 0, i32 0), double %35)
call void @test.helloWorld()
%35 = bitcast %Foo* %ddx to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %35, i8 0, i64 8, i1 false)
%37 = bitcast %Foo* %ddx to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %37, i8 0, i64 8, i1 false)
store i32 3, i32* %fro, align 4
%36 = bitcast [4 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %36, i8* align 4 bitcast ([4 x i32]* @.__const.12 to i8*), i32 16, i1 false)
%37 = load i32, i32* %fro, align 4
%38 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 1
%39 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0
store i64 4, i64* %38, align 8
%40 = bitcast [4 x i32]* %x to i32*
store i32* %40, i32** %39, align 8
%41 = bitcast %"int[]"* %indirectarg to i8*
%42 = bitcast %"int[]"* %vararg to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %41, i8* align 8 %42, i32 16, i1 false)
%43 = call i32 @test.sum_us(%"int[]"* %indirectarg)
%44 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.13, i32 0, i32 0), i32 %43)
%add11 = add i32 %37, %44
store i32 %add11, i32* %fro, align 4
%45 = load i32, i32* %fro, align 4
%46 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.14, i32 0, i32 0), i32 %45)
%47 = bitcast [4 x i32]* %x to i32*
%48 = insertvalue %"int[]" undef, i32* %47, 0
%49 = insertvalue %"int[]" %48, i64 4, 1
store %"int[]" %49, %"int[]"* %z, align 8
%50 = bitcast [3 x i32]* %de to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %50, i8* align 4 bitcast ([3 x i32]* @.__const.15 to i8*), i32 12, i1 false)
%51 = getelementptr inbounds %"int[]", %"int[]"* %vararg12, i32 0, i32 1
%52 = getelementptr inbounds %"int[]", %"int[]"* %vararg12, i32 0, i32 0
store i64 4, i64* %51, align 8
%53 = bitcast [4 x i32]* %x to i32*
store i32* %53, i32** %52, align 8
%54 = bitcast %"int[]"* %indirectarg13 to i8*
%55 = bitcast %"int[]"* %vararg12 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %54, i8* align 8 %55, i32 16, i1 false)
%56 = call i32 @test.sum_us(%"int[]"* %indirectarg13)
%57 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.16, i32 0, i32 0), i32 %56)
%58 = getelementptr inbounds %"int[]", %"int[]"* %vararg14, i32 0, i32 1
%59 = getelementptr inbounds %"int[]", %"int[]"* %vararg14, i32 0, i32 0
%60 = bitcast %"int[]"* %indirectarg15 to i8*
%61 = bitcast %"int[]"* %z to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %60, i8* align 8 %61, i32 16, i1 false)
%62 = call i32 @test.sum_us(%"int[]"* %indirectarg15)
%63 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.17, i32 0, i32 0), i32 %62)
%64 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 0
store i32 1, i32* %64, align 4
%65 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 1
store i32 2, i32* %65, align 4
%66 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 2
store i32 4, i32* %66, align 4
%67 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 3
store i32 5, i32* %67, align 4
%68 = getelementptr inbounds %"int[]", %"int[]"* %vararg16, i32 0, i32 1
store i64 4, i64* %68, align 8
%69 = getelementptr inbounds %"int[]", %"int[]"* %vararg16, i32 0, i32 0
%70 = bitcast [4 x i32]* %varargslots to i32*
store i32* %70, i32** %69, align 8
%71 = bitcast %"int[]"* %indirectarg17 to i8*
%72 = bitcast %"int[]"* %vararg16 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %71, i8* align 8 %72, i32 16, i1 false)
%73 = call i32 @test.sum_us(%"int[]"* %indirectarg17)
%74 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.18, i32 0, i32 0), i32 %73)
%75 = getelementptr inbounds [1 x i32], [1 x i32]* %varargslots19, i64 0, i64 0
store i32 1, i32* %75, align 4
%76 = getelementptr inbounds %"int[]", %"int[]"* %vararg18, i32 0, i32 1
store i64 1, i64* %76, align 8
%77 = getelementptr inbounds %"int[]", %"int[]"* %vararg18, i32 0, i32 0
%78 = bitcast [1 x i32]* %varargslots19 to i32*
store i32* %78, i32** %77, align 8
%79 = bitcast %"int[]"* %indirectarg20 to i8*
%80 = bitcast %"int[]"* %vararg18 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %79, i8* align 8 %80, i32 16, i1 false)
%81 = call i32 @test.sum_us(%"int[]"* %indirectarg20)
%82 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.19, i32 0, i32 0), i32 %81)
%83 = getelementptr inbounds %"int[]", %"int[]"* %vararg21, i32 0, i32 1
store i64 0, i64* %83, align 8
%84 = bitcast %"int[]"* %indirectarg22 to i8*
%85 = bitcast %"int[]"* %vararg21 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %84, i8* align 8 %85, i32 16, i1 false)
%86 = call i32 @test.sum_us(%"int[]"* %indirectarg22)
%87 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.20, i32 0, i32 0), i32 %86)
%38 = bitcast [4 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %38, i8* align 4 bitcast ([4 x i32]* @.__const.12 to i8*), i32 16, i1 false)
%39 = load i32, i32* %fro, align 4
%40 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 1
%41 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0
store i64 4, i64* %40, align 8
%42 = bitcast [4 x i32]* %x to i32*
store i32* %42, i32** %41, align 8
%43 = bitcast %"int[]"* %indirectarg to i8*
%44 = bitcast %"int[]"* %vararg to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %43, i8* align 8 %44, i32 16, i1 false)
%45 = call i32 @test.sum_us(%"int[]"* %indirectarg)
%46 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.13, i32 0, i32 0), i32 %45)
%add10 = add i32 %39, %46
store i32 %add10, i32* %fro, align 4
%47 = load i32, i32* %fro, align 4
%48 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.14, i32 0, i32 0), i32 %47)
%49 = bitcast [4 x i32]* %x to i32*
%50 = insertvalue %"int[]" undef, i32* %49, 0
%51 = insertvalue %"int[]" %50, i64 4, 1
store %"int[]" %51, %"int[]"* %z, align 8
%52 = bitcast [3 x i32]* %de to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %52, i8* align 4 bitcast ([3 x i32]* @.__const.15 to i8*), i32 12, i1 false)
%53 = getelementptr inbounds %"int[]", %"int[]"* %vararg11, i32 0, i32 1
%54 = getelementptr inbounds %"int[]", %"int[]"* %vararg11, i32 0, i32 0
store i64 4, i64* %53, align 8
%55 = bitcast [4 x i32]* %x to i32*
store i32* %55, i32** %54, align 8
%56 = bitcast %"int[]"* %indirectarg12 to i8*
%57 = bitcast %"int[]"* %vararg11 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %56, i8* align 8 %57, i32 16, i1 false)
%58 = call i32 @test.sum_us(%"int[]"* %indirectarg12)
%59 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.16, i32 0, i32 0), i32 %58)
%60 = getelementptr inbounds %"int[]", %"int[]"* %vararg13, i32 0, i32 1
%61 = getelementptr inbounds %"int[]", %"int[]"* %vararg13, i32 0, i32 0
%62 = bitcast %"int[]"* %indirectarg14 to i8*
%63 = bitcast %"int[]"* %z to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %62, i8* align 8 %63, i32 16, i1 false)
%64 = call i32 @test.sum_us(%"int[]"* %indirectarg14)
%65 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.17, i32 0, i32 0), i32 %64)
%66 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 0
store i32 1, i32* %66, align 4
%67 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 1
store i32 2, i32* %67, align 4
%68 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 2
store i32 4, i32* %68, align 4
%69 = getelementptr inbounds [4 x i32], [4 x i32]* %varargslots, i64 0, i64 3
store i32 5, i32* %69, align 4
%70 = getelementptr inbounds %"int[]", %"int[]"* %vararg15, i32 0, i32 1
store i64 4, i64* %70, align 8
%71 = getelementptr inbounds %"int[]", %"int[]"* %vararg15, i32 0, i32 0
%72 = bitcast [4 x i32]* %varargslots to i32*
store i32* %72, i32** %71, align 8
%73 = bitcast %"int[]"* %indirectarg16 to i8*
%74 = bitcast %"int[]"* %vararg15 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %73, i8* align 8 %74, i32 16, i1 false)
%75 = call i32 @test.sum_us(%"int[]"* %indirectarg16)
%76 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.18, i32 0, i32 0), i32 %75)
%77 = getelementptr inbounds [1 x i32], [1 x i32]* %varargslots18, i64 0, i64 0
store i32 1, i32* %77, align 4
%78 = getelementptr inbounds %"int[]", %"int[]"* %vararg17, i32 0, i32 1
store i64 1, i64* %78, align 8
%79 = getelementptr inbounds %"int[]", %"int[]"* %vararg17, i32 0, i32 0
%80 = bitcast [1 x i32]* %varargslots18 to i32*
store i32* %80, i32** %79, align 8
%81 = bitcast %"int[]"* %indirectarg19 to i8*
%82 = bitcast %"int[]"* %vararg17 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %81, i8* align 8 %82, i32 16, i1 false)
%83 = call i32 @test.sum_us(%"int[]"* %indirectarg19)
%84 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.19, i32 0, i32 0), i32 %83)
%85 = getelementptr inbounds %"int[]", %"int[]"* %vararg20, i32 0, i32 1
store i64 0, i64* %85, align 8
%86 = bitcast %"int[]"* %indirectarg21 to i8*
%87 = bitcast %"int[]"* %vararg20 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %86, i8* align 8 %87, i32 16, i1 false)
%88 = call i32 @test.sum_us(%"int[]"* %indirectarg21)
%89 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.20, i32 0, i32 0), i32 %88)
store i32 (double, %Bobo*)* null, i32 (double, %Bobo*)** %a1, align 8
store i32 (double, %Bobo*)* null, i32 (double, %Bobo*)** %b2, align 8
ret void
@@ -689,11 +824,11 @@ entry:
define i32 @test2.int.getValue(i32 %0)
entry:
%blob = alloca %Blob, align 4
%dive = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
store i32 %0, i32* %dive, align 4
%1 = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%2 = load i32, i32* %1, align 4
ret i32 %2
store i32 %0, i32* %1, align 4
%2 = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%3 = load i32, i32* %2, align 4
ret i32 %3
// #expect: test2.double.ll
@@ -718,10 +853,10 @@ entry:
define double @test2.double.getValue(i64 %0)
entry:
%blob = alloca %Blob, align 8
%dive = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%1 = bitcast double* %dive to i64*
store i64 %0, i64* %1, align 8
%2 = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%3 = load double, double* %2, align 8
ret double %3
%1 = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%2 = bitcast double* %1 to i64*
store i64 %0, i64* %2, align 8
%3 = getelementptr inbounds %Blob, %Blob* %blob, i32 0, i32 0
%4 = load double, double* %3, align 8
ret double %4

View File

@@ -164,37 +164,37 @@ entry:
%len = alloca i64, align 8
%i = alloca i32, align 4
%pair = bitcast %"char[]"* %seq to { i8*, i64 }*
%lo = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0
store i8* %0, i8** %lo, align 8
%hi = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %hi, align 8
%3 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0
store i8* %0, i8** %3, align 8
%4 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %4, align 8
store i32 %2, i32* %n, align 4
%len1 = getelementptr inbounds %"char[]", %"char[]"* %seq, i32 0, i32 1
%3 = load i64, i64* %len1, align 8
store i64 %3, i64* %len, align 8
%5 = getelementptr inbounds %"char[]", %"char[]"* %seq, i32 0, i32 1
%6 = load i64, i64* %5, align 8
store i64 %6, i64* %len, align 8
store i32 0, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%4 = load i32, i32* %i, align 4
%5 = load i32, i32* %n, align 4
%lt = icmp slt i32 %4, %5
%7 = load i32, i32* %i, align 4
%8 = load i32, i32* %n, align 4
%lt = icmp slt i32 %7, %8
br i1 %lt, label %for.body, label %for.exit
for.body: ; preds = %for.cond
%subarrayptr = getelementptr inbounds %"char[]", %"char[]"* %seq, i32 0, i32 0
%saptr = load i8*, i8** %subarrayptr, align 8
%6 = load i32, i32* %i, align 4
%sisiext = sext i32 %6 to i64
%7 = load i64, i64* %len, align 8
%smod = srem i64 %sisiext, %7
%sarridx = getelementptr inbounds i8, i8* %saptr, i64 %smod
%8 = load i8, i8* %sarridx, align 1
%uisiext = zext i8 %8 to i32
%9 = getelementptr inbounds %"char[]", %"char[]"* %seq, i32 0, i32 0
%10 = load i8*, i8** %9, align 8
%11 = load i32, i32* %i, align 4
%sisiext = sext i32 %11 to i64
%12 = load i64, i64* %len, align 8
%smod = srem i64 %sisiext, %12
%ptroffset = getelementptr inbounds i8, i8* %10, i64 %smod
%13 = load i8, i8* %ptroffset, align 1
%uisiext = zext i8 %13 to i32
call void @putchar(i32 %uisiext)
%9 = load i32, i32* %i, align 4
%smod2 = srem i32 %9, 60
%eq = icmp eq i32 %smod2, 59
%14 = load i32, i32* %i, align 4
%smod1 = srem i32 %14, 60
%eq = icmp eq i32 %smod1, 59
br i1 %eq, label %if.then, label %if.exit
if.then: ; preds = %for.body
@@ -205,22 +205,22 @@ if.exit: ; preds = %if.then, %for.body
br label %for.inc
for.inc: ; preds = %if.exit
%10 = load i32, i32* %i, align 4
%add = add i32 %10, 1
%15 = load i32, i32* %i, align 4
%add = add i32 %15, 1
store i32 %add, i32* %i, align 4
br label %for.cond
for.exit: ; preds = %for.cond
%11 = load i32, i32* %i, align 4
%smod3 = srem i32 %11, 60
%neq = icmp ne i32 %smod3, 0
br i1 %neq, label %if.then4, label %if.exit5
%16 = load i32, i32* %i, align 4
%smod2 = srem i32 %16, 60
%neq = icmp ne i32 %smod2, 0
br i1 %neq, label %if.then3, label %if.exit4
if.then4: ; preds = %for.exit
if.then3: ; preds = %for.exit
call void @putchar(i32 10)
br label %if.exit5
br label %if.exit4
if.exit5: ; preds = %if.then4, %for.exit
if.exit4: ; preds = %if.then3, %for.exit
ret void
}
@@ -230,118 +230,118 @@ entry:
%symb = alloca %"char[]", align 8
%probability = alloca %"double[]", align 8
%n = alloca i32, align 4
%len5 = alloca i32, align 4
%len = alloca i32, align 4
%i = alloca i32, align 4
%v = alloca double, align 8
%j = alloca i32, align 4
%pair = bitcast %"char[]"* %symb to { i8*, i64 }*
%lo = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0
store i8* %0, i8** %lo, align 8
%hi = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %hi, align 8
%5 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 0
store i8* %0, i8** %5, align 8
%6 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair, i32 0, i32 1
store i64 %1, i64* %6, align 8
%pair1 = bitcast %"double[]"* %probability to { i8*, i64 }*
%lo2 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair1, i32 0, i32 0
store i8* %2, i8** %lo2, align 8
%hi3 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair1, i32 0, i32 1
store i64 %3, i64* %hi3, align 8
%7 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair1, i32 0, i32 0
store i8* %2, i8** %7, align 8
%8 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair1, i32 0, i32 1
store i64 %3, i64* %8, align 8
store i32 %4, i32* %n, align 4
%len = getelementptr inbounds %"char[]", %"char[]"* %symb, i32 0, i32 1
%5 = load i64, i64* %len, align 8
%len4 = getelementptr inbounds %"double[]", %"double[]"* %probability, i32 0, i32 1
%6 = load i64, i64* %len4, align 8
%eq = icmp eq i64 %5, %6
%9 = getelementptr inbounds %"char[]", %"char[]"* %symb, i32 0, i32 1
%10 = load i64, i64* %9, align 8
%11 = getelementptr inbounds %"double[]", %"double[]"* %probability, i32 0, i32 1
%12 = load i64, i64* %11, align 8
%eq = icmp eq i64 %10, %12
call void @llvm.assume(i1 %eq)
%len6 = getelementptr inbounds %"double[]", %"double[]"* %probability, i32 0, i32 1
%7 = load i64, i64* %len6, align 8
%uisitrunc = trunc i64 %7 to i32
store i32 %uisitrunc, i32* %len5, align 4
%13 = getelementptr inbounds %"double[]", %"double[]"* %probability, i32 0, i32 1
%14 = load i64, i64* %13, align 8
%uisitrunc = trunc i64 %14 to i32
store i32 %uisitrunc, i32* %len, align 4
store i32 0, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc18, %entry
%8 = load i32, i32* %i, align 4
%9 = load i32, i32* %n, align 4
%lt = icmp slt i32 %8, %9
br i1 %lt, label %for.body, label %for.exit20
for.cond: ; preds = %for.inc11, %entry
%15 = load i32, i32* %i, align 4
%16 = load i32, i32* %n, align 4
%lt = icmp slt i32 %15, %16
br i1 %lt, label %for.body, label %for.exit13
for.body: ; preds = %for.cond
%10 = call float @fasta.fasta_rand(float 1.000000e+00)
%fpfpext = fpext float %10 to double
%17 = call float @fasta.fasta_rand(float 1.000000e+00)
%fpfpext = fpext float %17 to double
store double %fpfpext, double* %v, align 8
store i32 0, i32* %j, align 4
br label %for.cond7
br label %for.cond2
for.cond7: ; preds = %for.inc, %for.body
%11 = load i32, i32* %j, align 4
%12 = load i32, i32* %len5, align 4
%sub = sub i32 %12, 1
%lt8 = icmp slt i32 %11, %sub
br i1 %lt8, label %for.body9, label %for.exit
for.cond2: ; preds = %for.inc, %for.body
%18 = load i32, i32* %j, align 4
%19 = load i32, i32* %len, align 4
%sub = sub i32 %19, 1
%lt3 = icmp slt i32 %18, %sub
br i1 %lt3, label %for.body4, label %for.exit
for.body9: ; preds = %for.cond7
%13 = load double, double* %v, align 8
%subarrayptr = getelementptr inbounds %"double[]", %"double[]"* %probability, i32 0, i32 0
%saptr = load double*, double** %subarrayptr, align 8
%14 = load i32, i32* %j, align 4
%sisiext = sext i32 %14 to i64
%sarridx = getelementptr inbounds double, double* %saptr, i64 %sisiext
%15 = load double, double* %sarridx, align 8
%fsub = fsub double %13, %15
for.body4: ; preds = %for.cond2
%20 = load double, double* %v, align 8
%21 = getelementptr inbounds %"double[]", %"double[]"* %probability, i32 0, i32 0
%22 = load double*, double** %21, align 8
%23 = load i32, i32* %j, align 4
%sisiext = sext i32 %23 to i64
%ptroffset = getelementptr inbounds double, double* %22, i64 %sisiext
%24 = load double, double* %ptroffset, align 8
%fsub = fsub double %20, %24
store double %fsub, double* %v, align 8
%16 = load double, double* %v, align 8
%lt10 = fcmp olt double %16, 0.000000e+00
br i1 %lt10, label %if.then, label %if.exit
%25 = load double, double* %v, align 8
%lt5 = fcmp olt double %25, 0.000000e+00
br i1 %lt5, label %if.then, label %if.exit
if.then: ; preds = %for.body9
if.then: ; preds = %for.body4
br label %for.exit
if.exit: ; preds = %for.body9
if.exit: ; preds = %for.body4
br label %for.inc
for.inc: ; preds = %if.exit
%17 = load i32, i32* %j, align 4
%add = add i32 %17, 1
%26 = load i32, i32* %j, align 4
%add = add i32 %26, 1
store i32 %add, i32* %j, align 4
br label %for.cond7
br label %for.cond2
for.exit: ; preds = %if.then, %for.cond7
%subarrayptr11 = getelementptr inbounds %"char[]", %"char[]"* %symb, i32 0, i32 0
%saptr12 = load i8*, i8** %subarrayptr11, align 8
%18 = load i32, i32* %j, align 4
%sisiext13 = sext i32 %18 to i64
%sarridx14 = getelementptr inbounds i8, i8* %saptr12, i64 %sisiext13
%19 = load i8, i8* %sarridx14, align 1
%uisiext = zext i8 %19 to i32
for.exit: ; preds = %if.then, %for.cond2
%27 = getelementptr inbounds %"char[]", %"char[]"* %symb, i32 0, i32 0
%28 = load i8*, i8** %27, align 8
%29 = load i32, i32* %j, align 4
%sisiext6 = sext i32 %29 to i64
%ptroffset7 = getelementptr inbounds i8, i8* %28, i64 %sisiext6
%30 = load i8, i8* %ptroffset7, align 1
%uisiext = zext i8 %30 to i32
call void @putchar(i32 %uisiext)
%20 = load i32, i32* %i, align 4
%smod = srem i32 %20, 60
%eq15 = icmp eq i32 %smod, 59
br i1 %eq15, label %if.then16, label %if.exit17
%31 = load i32, i32* %i, align 4
%smod = srem i32 %31, 60
%eq8 = icmp eq i32 %smod, 59
br i1 %eq8, label %if.then9, label %if.exit10
if.then16: ; preds = %for.exit
if.then9: ; preds = %for.exit
call void @putchar(i32 10)
br label %if.exit17
br label %if.exit10
if.exit17: ; preds = %if.then16, %for.exit
br label %for.inc18
if.exit10: ; preds = %if.then9, %for.exit
br label %for.inc11
for.inc18: ; preds = %if.exit17
%21 = load i32, i32* %i, align 4
%add19 = add i32 %21, 1
store i32 %add19, i32* %i, align 4
for.inc11: ; preds = %if.exit10
%32 = load i32, i32* %i, align 4
%add12 = add i32 %32, 1
store i32 %add12, i32* %i, align 4
br label %for.cond
for.exit20: ; preds = %for.cond
%22 = load i32, i32* %i, align 4
%smod21 = srem i32 %22, 60
%neq = icmp ne i32 %smod21, 0
br i1 %neq, label %if.then22, label %if.exit23
for.exit13: ; preds = %for.cond
%33 = load i32, i32* %i, align 4
%smod14 = srem i32 %33, 60
%neq = icmp ne i32 %smod14, 0
br i1 %neq, label %if.then15, label %if.exit16
if.then22: ; preds = %for.exit20
if.then15: ; preds = %for.exit13
call void @putchar(i32 10)
br label %if.exit23
br label %if.exit16
if.exit23: ; preds = %if.then22, %for.exit20
if.exit16: ; preds = %if.then15, %for.exit13
ret void
}
@@ -360,8 +360,8 @@ entry:
if.then: ; preds = %entry
%3 = load i8**, i8*** %argv, align 8
%ptridx = getelementptr inbounds i8*, i8** %3, i64 1
%4 = load i8*, i8** %ptridx, align 8
%ptroffset = getelementptr inbounds i8*, i8** %3, i64 1
%4 = load i8*, i8** %ptroffset, align 8
%5 = call i32 @atoi(i8* %4)
store i32 %5, i32* %n, align 4
br label %if.exit
@@ -390,4 +390,4 @@ if.exit: ; preds = %if.then, %entry
%mul10 = mul i32 %11, 5
call void @fasta.random_fasta(i8* %lo6, i64 %hi7, i8* %lo8, i64 %hi9, i32 %mul10)
ret void
}
}

View File

@@ -69,11 +69,11 @@ entry:
call void @llvm.memset.p0i8.i64(i8* align 4 %2, i8 0, i64 0, i1 false)
store i32 33, i32* %foo2, align 4
store i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0), i8** %str, align 8
%3 = getelementptr inbounds i32, [3 x i32]* %literal, i32 0
%3 = getelementptr inbounds [3 x i32], [3 x i32]* %literal, i64 0, i64 0
store i32 1, i32* %3, align 4
%4 = getelementptr inbounds i32, [3 x i32]* %literal, i32 1
%4 = getelementptr inbounds [3 x i32], [3 x i32]* %literal, i64 0, i64 1
store i32 2, i32* %4, align 4
%5 = getelementptr inbounds i32, [3 x i32]* %literal, i32 2
%5 = getelementptr inbounds [3 x i32], [3 x i32]* %literal, i64 0, i64 2
store i32 3, i32* %5, align 4
%6 = bitcast [3 x i32]* %literal to i32*
%7 = insertvalue %"int[]" undef, i32* %6, 0

View File

@@ -0,0 +1,69 @@
module test;
extern fn void printf(char*, ...);
fn void test(int x)
{
int[10] y = { [0..3] = 4, [6..8] = x };
foreach (int v : y)
{
printf("%d\n", v);
}
}
fn void main()
{
test(101);
}
/* #expect: test.ll
define void @test.test(i32 %0) #0 {
entry:
%x = alloca i32, align 4
%y = alloca [10 x i32], align 16
%idx = alloca i64, align 8
%v = alloca i32, align 4
store i32 %0, i32* %x, align 4
%1 = bitcast [10 x i32]* %y to i8*
call void @llvm.memset.p0i8.i64(i8* align 16 %1, i8 0, i64 40, i1 false)
%2 = getelementptr inbounds [10 x i32], [10 x i32]* %y, i64 0, i64 0
store i32 4, i32* %2, align 4
%3 = getelementptr inbounds [10 x i32], [10 x i32]* %y, i64 0, i64 1
store i32 4, i32* %3, align 4
%4 = getelementptr inbounds [10 x i32], [10 x i32]* %y, i64 0, i64 2
store i32 4, i32* %4, align 4
%5 = getelementptr inbounds [10 x i32], [10 x i32]* %y, i64 0, i64 3
store i32 4, i32* %5, align 4
%6 = getelementptr inbounds [10 x i32], [10 x i32]* %y, i64 0, i64 6
%7 = load i32, i32* %x, align 4
store i32 %7, i32* %6, align 4
%8 = getelementptr inbounds [10 x i32], [10 x i32]* %y, i64 0, i64 7
store i32 %7, i32* %8, align 4
%9 = getelementptr inbounds [10 x i32], [10 x i32]* %y, i64 0, i64 8
store i32 %7, i32* %9, align 4
store i64 0, i64* %idx, align 8
br label %foreach.cond
foreach.cond: ; preds = %foreach.inc, %entry
%10 = load i64, i64* %idx, align 8
%lt = icmp ult i64 %10, 10
br i1 %lt, label %foreach.body, label %foreach.exit
foreach.body: ; preds = %foreach.cond
%ptroffset = getelementptr inbounds i32, [10 x i32]* %y, i64 %10
%11 = load i32, i32* %ptroffset, align 4
store i32 %11, i32* %v, align 4
%12 = load i32, i32* %v, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %12)
br label %foreach.inc
foreach.inc: ; preds = %foreach.body
%13 = load i64, i64* %idx, align 8
%14 = add i64 %13, 1
store i64 %14, i64* %idx, align 8
br label %foreach.cond
foreach.exit: ; preds = %foreach.cond
ret void
}

View File

@@ -48,7 +48,7 @@ define void @statics.test() #0 {
entry:
%b = alloca %"Bar[]", align 8
%literal = alloca [1 x %Bar], align 4
%0 = getelementptr inbounds %Bar, [1 x %Bar]* %literal, i32 0
%0 = getelementptr inbounds [1 x %Bar], [1 x %Bar]* %literal, i64 0, i64 0
%1 = getelementptr inbounds %Bar, %Bar* %0, i32 0, i32 0
store i32 1, i32* %1, align 4
%2 = getelementptr inbounds %Bar, %Bar* %0, i32 0, i32 1
@@ -57,29 +57,29 @@ entry:
%4 = insertvalue %"Bar[]" undef, %Bar* %3, 0
%5 = insertvalue %"Bar[]" %4, i64 1, 1
store %"Bar[]" %5, %"Bar[]"* %b, align 8
%subarrayptr = getelementptr inbounds %"Bar[]", %"Bar[]"* %b, i32 0, i32 0
%saptr = load %Bar*, %Bar** %subarrayptr, align 8
%sarridx = getelementptr inbounds %Bar, %Bar* %saptr, i64 0
%6 = getelementptr inbounds %Bar, %Bar* %sarridx, i32 0, i32 1
%7 = load i32, i32* %6, align 4
%saptr1 = load %Bar*, %Bar** getelementptr inbounds (%"Bar[]", %"Bar[]"* @test.c, i32 0, i32 0), align 8
%sarridx2 = getelementptr inbounds %Bar, %Bar* %saptr1, i64 0
%8 = getelementptr inbounds %Bar, %Bar* %sarridx2, i32 0, i32 1
%6 = getelementptr inbounds %"Bar[]", %"Bar[]"* %b, i32 0, i32 0
%7 = load %Bar*, %Bar** %6, align 8
%ptroffset = getelementptr inbounds %Bar, %Bar* %7, i64 0
%8 = getelementptr inbounds %Bar, %Bar* %ptroffset, i32 0, i32 1
%9 = load i32, i32* %8, align 4
%10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0), i32 %7, i32 %9)
%subarrayptr3 = getelementptr inbounds %"Bar[]", %"Bar[]"* %b, i32 0, i32 0
%saptr4 = load %Bar*, %Bar** %subarrayptr3, align 8
%sarridx5 = getelementptr inbounds %Bar, %Bar* %saptr4, i64 0
%11 = getelementptr inbounds %Bar, %Bar* %sarridx5, i32 0, i32 1
%10 = load %Bar*, %Bar** getelementptr inbounds (%"Bar[]", %"Bar[]"* @test.c, i32 0, i32 0), align 8
%ptroffset1 = getelementptr inbounds %Bar, %Bar* %10, i64 0
%11 = getelementptr inbounds %Bar, %Bar* %ptroffset1, i32 0, i32 1
%12 = load i32, i32* %11, align 4
%add = add i32 %12, 1
store i32 %add, i32* %11, align 4
%saptr6 = load %Bar*, %Bar** getelementptr inbounds (%"Bar[]", %"Bar[]"* @test.c, i32 0, i32 0), align 8
%sarridx7 = getelementptr inbounds %Bar, %Bar* %saptr6, i64 0
%13 = getelementptr inbounds %Bar, %Bar* %sarridx7, i32 0, i32 1
%14 = load i32, i32* %13, align 4
%add8 = add i32 %14, 1
store i32 %add8, i32* %13, align 4
%13 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0), i32 %9, i32 %12)
%14 = getelementptr inbounds %"Bar[]", %"Bar[]"* %b, i32 0, i32 0
%15 = load %Bar*, %Bar** %14, align 8
%ptroffset2 = getelementptr inbounds %Bar, %Bar* %15, i64 0
%16 = getelementptr inbounds %Bar, %Bar* %ptroffset2, i32 0, i32 1
%17 = load i32, i32* %16, align 4
%add = add i32 %17, 1
store i32 %add, i32* %16, align 4
%18 = load %Bar*, %Bar** getelementptr inbounds (%"Bar[]", %"Bar[]"* @test.c, i32 0, i32 0), align 8
%ptroffset3 = getelementptr inbounds %Bar, %Bar* %18, i64 0
%19 = getelementptr inbounds %Bar, %Bar* %ptroffset3, i32 0, i32 1
%20 = load i32, i32* %19, align 4
%add4 = add i32 %20, 1
store i32 %add4, i32* %19, align 4
ret void
}
@@ -91,3 +91,4 @@ entry:
call void @statics.test()
ret i32 1
}

View File

@@ -72,108 +72,108 @@ entry:
%x = alloca %"int[]", align 8
%literal = alloca [3 x i32], align 4
%y = alloca i32*, align 8
%literal3 = alloca [3 x i32], align 4
%literal2 = alloca [3 x i32], align 4
%ffe = alloca %Baz, align 8
%azz = alloca [1 x i32], align 4
%a = alloca [0 x i32], align 4
%xy = alloca i8, align 1
%literal7 = alloca [3 x i32], align 4
%literal6 = alloca [3 x i32], align 4
%b = alloca %Bar, align 4
%z = alloca %Baz, align 8
%sub = alloca %"int[]", align 8
%literal10 = alloca [0 x i32], align 4
%literal8 = alloca [0 x i32], align 4
%foo = alloca %"Bar[]", align 8
%literal11 = alloca [0 x %Bar], align 4
%literal9 = alloca [0 x %Bar], align 4
%baz = alloca [3 x %Baz], align 16
%saptr = load %Bar*, %Bar** getelementptr inbounds (%"Bar[]", %"Bar[]"* @subarrays.arrbar, i32 0, i32 0), align 8
%sarridx = getelementptr inbounds %Bar, %Bar* %saptr, i64 1
%0 = bitcast %Bar* %w to i8*
%1 = bitcast %Bar* %sarridx to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 %1, i32 8, i1 false)
%saptr1 = load %Bar*, %Bar** getelementptr inbounds (%"Bar[]", %"Bar[]"* @subarrays.arrbar, i32 0, i32 0), align 8
%sarridx2 = getelementptr inbounds %Bar, %Bar* %saptr1, i64 1
%2 = getelementptr inbounds %Bar, %Bar* %sarridx2, i32 0, i32 0
%3 = load i32, i32* %2, align 4
%4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %3)
%5 = getelementptr inbounds i32, [3 x i32]* %literal, i32 0
store i32 1, i32* %5, align 4
%6 = getelementptr inbounds i32, [3 x i32]* %literal, i32 1
store i32 2, i32* %6, align 4
%7 = getelementptr inbounds i32, [3 x i32]* %literal, i32 2
store i32 3, i32* %7, align 4
%8 = bitcast [3 x i32]* %literal to i32*
%9 = insertvalue %"int[]" undef, i32* %8, 0
%10 = insertvalue %"int[]" %9, i64 3, 1
store %"int[]" %10, %"int[]"* %x, align 8
%11 = getelementptr inbounds i32, [3 x i32]* %literal3, i32 0
store i32 123, i32* %11, align 4
%12 = getelementptr inbounds i32, [3 x i32]* %literal3, i32 1
store i32 234, i32* %12, align 4
%13 = getelementptr inbounds i32, [3 x i32]* %literal3, i32 2
store i32 567, i32* %13, align 4
%ptrptr = bitcast [3 x i32]* %literal3 to i32*
%0 = load %Bar*, %Bar** getelementptr inbounds (%"Bar[]", %"Bar[]"* @subarrays.arrbar, i32 0, i32 0), align 8
%ptroffset = getelementptr inbounds %Bar, %Bar* %0, i64 1
%1 = bitcast %Bar* %w to i8*
%2 = bitcast %Bar* %ptroffset to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %1, i8* align 4 %2, i32 8, i1 false)
%3 = load %Bar*, %Bar** getelementptr inbounds (%"Bar[]", %"Bar[]"* @subarrays.arrbar, i32 0, i32 0), align 8
%ptroffset1 = getelementptr inbounds %Bar, %Bar* %3, i64 1
%4 = getelementptr inbounds %Bar, %Bar* %ptroffset1, i32 0, i32 0
%5 = load i32, i32* %4, align 4
%6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %5)
%7 = getelementptr inbounds [3 x i32], [3 x i32]* %literal, i64 0, i64 0
store i32 1, i32* %7, align 4
%8 = getelementptr inbounds [3 x i32], [3 x i32]* %literal, i64 0, i64 1
store i32 2, i32* %8, align 4
%9 = getelementptr inbounds [3 x i32], [3 x i32]* %literal, i64 0, i64 2
store i32 3, i32* %9, align 4
%10 = bitcast [3 x i32]* %literal to i32*
%11 = insertvalue %"int[]" undef, i32* %10, 0
%12 = insertvalue %"int[]" %11, i64 3, 1
store %"int[]" %12, %"int[]"* %x, align 8
%13 = getelementptr inbounds [3 x i32], [3 x i32]* %literal2, i64 0, i64 0
store i32 123, i32* %13, align 4
%14 = getelementptr inbounds [3 x i32], [3 x i32]* %literal2, i64 0, i64 1
store i32 234, i32* %14, align 4
%15 = getelementptr inbounds [3 x i32], [3 x i32]* %literal2, i64 0, i64 2
store i32 567, i32* %15, align 4
%ptrptr = bitcast [3 x i32]* %literal2 to i32*
store i32* %ptrptr, i32** %y, align 8
%14 = call i32 @"std::io.println"(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.5, i32 0, i32 0)) #3
%len = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%15 = load i64, i64* %len, align 8
%uisitrunc = trunc i64 %15 to i32
%subarrayptr = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%saptr4 = load i32*, i32** %subarrayptr, align 8
%sarridx5 = getelementptr inbounds i32, i32* %saptr4, i64 1
%16 = load i32, i32* %sarridx5, align 4
%17 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str.6, i32 0, i32 0), i32 %uisitrunc, i32 %16)
%18 = load i32*, i32** %y, align 8
%ptridx = getelementptr inbounds i32, i32* %18, i64 1
%19 = load i32, i32* %ptridx, align 4
%20 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.7, i32 0, i32 0), i32 %19)
%21 = load i32*, i32** @subarrays.fofeo, align 8
%ptridx6 = getelementptr inbounds i32, i32* %21, i64 1
%22 = load i32, i32* %ptridx6, align 4
%23 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.8, i32 0, i32 0), i32 %22)
%24 = bitcast %Baz* %ffe to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %24, i8* align 8 bitcast ({ i32, [4 x i8] }* @.__const to i8*), i32 8, i1 false)
%25 = bitcast [1 x i32]* %azz to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %25, i8 0, i64 4, i1 false)
%26 = bitcast [0 x i32]* %a to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %26, i8 0, i64 0, i1 false)
%27 = getelementptr inbounds i32, [3 x i32]* %literal7, i32 0
store i32 1, i32* %27, align 4
%28 = getelementptr inbounds i32, [3 x i32]* %literal7, i32 1
store i32 2, i32* %28, align 4
%29 = getelementptr inbounds i32, [3 x i32]* %literal7, i32 2
store i32 3, i32* %29, align 4
%30 = bitcast [3 x i32]* %literal7 to i32*
%31 = insertvalue %"int[]" undef, i32* %30, 0
%32 = insertvalue %"int[]" %31, i64 3, 1
%len8 = extractvalue %"int[]" %32, 1
%not = icmp eq i64 %len8, 0
%33 = zext i1 %not to i8
store i8 %33, i8* %xy, align 1
%34 = load i8, i8* %xy, align 1
%35 = trunc i8 %34 to i1
%not9 = xor i1 %35, true
br i1 %not9, label %if.then, label %if.exit
%16 = call i32 @"std::io.println"(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.5, i32 0, i32 0)) #3
%17 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 1
%18 = load i64, i64* %17, align 8
%uisitrunc = trunc i64 %18 to i32
%19 = getelementptr inbounds %"int[]", %"int[]"* %x, i32 0, i32 0
%20 = load i32*, i32** %19, align 8
%ptroffset3 = getelementptr inbounds i32, i32* %20, i64 1
%21 = load i32, i32* %ptroffset3, align 4
%22 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str.6, i32 0, i32 0), i32 %uisitrunc, i32 %21)
%23 = load i32*, i32** %y, align 8
%ptroffset4 = getelementptr inbounds i32, i32* %23, i64 1
%24 = load i32, i32* %ptroffset4, align 4
%25 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.7, i32 0, i32 0), i32 %24)
%26 = load i32*, i32** @subarrays.fofeo, align 8
%ptroffset5 = getelementptr inbounds i32, i32* %26, i64 1
%27 = load i32, i32* %ptroffset5, align 4
%28 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.8, i32 0, i32 0), i32 %27)
%29 = bitcast %Baz* %ffe to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %29, i8* align 8 bitcast ({ i32, [4 x i8] }* @.__const to i8*), i32 8, i1 false)
%30 = bitcast [1 x i32]* %azz to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %30, i8 0, i64 4, i1 false)
%31 = bitcast [0 x i32]* %a to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %31, i8 0, i64 0, i1 false)
%32 = getelementptr inbounds [3 x i32], [3 x i32]* %literal6, i64 0, i64 0
store i32 1, i32* %32, align 4
%33 = getelementptr inbounds [3 x i32], [3 x i32]* %literal6, i64 0, i64 1
store i32 2, i32* %33, align 4
%34 = getelementptr inbounds [3 x i32], [3 x i32]* %literal6, i64 0, i64 2
store i32 3, i32* %34, align 4
%35 = bitcast [3 x i32]* %literal6 to i32*
%36 = insertvalue %"int[]" undef, i32* %35, 0
%37 = insertvalue %"int[]" %36, i64 3, 1
%len = extractvalue %"int[]" %37, 1
%not = icmp eq i64 %len, 0
%38 = zext i1 %not to i8
store i8 %38, i8* %xy, align 1
%39 = load i8, i8* %xy, align 1
%40 = trunc i8 %39 to i1
%not7 = xor i1 %40, true
br i1 %not7, label %if.then, label %if.exit
if.then: ; preds = %entry
%36 = call i32 @"std::io.println"(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.9, i32 0, i32 0)) #3
%41 = call i32 @"std::io.println"(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.9, i32 0, i32 0)) #3
br label %if.exit
if.exit: ; preds = %if.then, %entry
%37 = bitcast %Bar* %b to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %37, i8 0, i64 8, i1 false)
%38 = bitcast %Baz* %z to i8*
call void @llvm.memset.p0i8.i64(i8* align 8 %38, i8 0, i64 8, i1 false)
store [0 x i32] zeroinitializer, [0 x i32]* %literal10, align 4
%39 = bitcast [0 x i32]* %literal10 to i32*
%40 = insertvalue %"int[]" undef, i32* %39, 0
%41 = insertvalue %"int[]" %40, i64 0, 1
store %"int[]" %41, %"int[]"* %sub, align 8
store [0 x %Bar] zeroinitializer, [0 x %Bar]* %literal11, align 4
%42 = bitcast [0 x %Bar]* %literal11 to %Bar*
%43 = insertvalue %"Bar[]" undef, %Bar* %42, 0
%44 = insertvalue %"Bar[]" %43, i64 0, 1
store %"Bar[]" %44, %"Bar[]"* %foo, align 8
%45 = bitcast [3 x %Baz]* %baz to i8*
call void @llvm.memset.p0i8.i64(i8* align 16 %45, i8 0, i64 24, i1 false)
%42 = bitcast %Bar* %b to i8*
call void @llvm.memset.p0i8.i64(i8* align 4 %42, i8 0, i64 8, i1 false)
%43 = bitcast %Baz* %z to i8*
call void @llvm.memset.p0i8.i64(i8* align 8 %43, i8 0, i64 8, i1 false)
store [0 x i32] zeroinitializer, [0 x i32]* %literal8, align 4
%44 = bitcast [0 x i32]* %literal8 to i32*
%45 = insertvalue %"int[]" undef, i32* %44, 0
%46 = insertvalue %"int[]" %45, i64 0, 1
store %"int[]" %46, %"int[]"* %sub, align 8
store [0 x %Bar] zeroinitializer, [0 x %Bar]* %literal9, align 4
%47 = bitcast [0 x %Bar]* %literal9 to %Bar*
%48 = insertvalue %"Bar[]" undef, %Bar* %47, 0
%49 = insertvalue %"Bar[]" %48, i64 0, 1
store %"Bar[]" %49, %"Bar[]"* %foo, align 8
%50 = bitcast [3 x %Baz]* %baz to i8*
call void @llvm.memset.p0i8.i64(i8* align 16 %50, i8 0, i64 24, i1 false)
ret i32 1
}
}

View File

@@ -115,12 +115,12 @@ for.cond: ; preds = %for.inc, %entry
for.body: ; preds = %for.cond
%6 = load i16*, i16** %to, align 8
%7 = load i64, i64* %i, align 8
%ptridx = getelementptr inbounds i16, i16* %6, i64 %7
%ptroffset = getelementptr inbounds i16, i16* %6, i64 %7
%8 = load i16*, i16** %b, align 8
%9 = load i64, i64* %i, align 8
%ptridx3 = getelementptr inbounds i16, i16* %8, i64 %9
%10 = load i16, i16* %ptridx3, align 2
store i16 %10, i16* %ptridx, align 2
%ptroffset3 = getelementptr inbounds i16, i16* %8, i64 %9
%10 = load i16, i16* %ptroffset3, align 2
store i16 %10, i16* %ptroffset, align 2
br label %for.inc
for.inc: ; preds = %for.body
@@ -168,12 +168,12 @@ for.cond: ; preds = %for.inc, %entry
for.body: ; preds = %for.cond
%3 = load i8*, i8** %to, align 8
%4 = load i64, i64* %i, align 8
%ptridx = getelementptr inbounds i8, i8* %3, i64 %4
%ptroffset = getelementptr inbounds i8, i8* %3, i64 %4
%5 = load i8*, i8** %b, align 8
%6 = load i64, i64* %i, align 8
%ptridx3 = getelementptr inbounds i8, i8* %5, i64 %6
%7 = load i8, i8* %ptridx3, align 1
store i8 %7, i8* %ptridx, align 1
%ptroffset3 = getelementptr inbounds i8, i8* %5, i64 %6
%7 = load i8, i8* %ptroffset3, align 1
store i8 %7, i8* %ptroffset, align 1
br label %for.inc
for.inc: ; preds = %for.body
@@ -246,12 +246,12 @@ for.cond: ; preds = %for.inc, %entry
for.body: ; preds = %for.cond
%2 = load i32*, i32** %to, align 8
%3 = load i64, i64* %i1, align 8
%ptridx = getelementptr inbounds i32, i32* %2, i64 %3
%ptroffset = getelementptr inbounds i32, i32* %2, i64 %3
%4 = load i32*, i32** %b, align 8
%5 = load i64, i64* %i1, align 8
%ptridx2 = getelementptr inbounds i32, i32* %4, i64 %5
%6 = load i32, i32* %ptridx2, align 4
store i32 %6, i32* %ptridx, align 4
%ptroffset2 = getelementptr inbounds i32, i32* %4, i64 %5
%6 = load i32, i32* %ptroffset2, align 4
store i32 %6, i32* %ptroffset, align 4
br label %for.inc
for.inc: ; preds = %for.body
@@ -284,12 +284,12 @@ for.cond10: ; preds = %for.inc15, %expr_bl
for.body12: ; preds = %for.cond10
%12 = load i32*, i32** %to7, align 8
%13 = load i64, i64* %i9, align 8
%ptridx13 = getelementptr inbounds i32, i32* %12, i64 %13
%ptroffset13 = getelementptr inbounds i32, i32* %12, i64 %13
%14 = load i32*, i32** %b6, align 8
%15 = load i64, i64* %i9, align 8
%ptridx14 = getelementptr inbounds i32, i32* %14, i64 %15
%16 = load i32, i32* %ptridx14, align 4
store i32 %16, i32* %ptridx13, align 4
%ptroffset14 = getelementptr inbounds i32, i32* %14, i64 %15
%16 = load i32, i32* %ptroffset14, align 4
store i32 %16, i32* %ptroffset13, align 4
br label %for.inc15
for.inc15: ; preds = %for.body12
@@ -329,12 +329,12 @@ for.cond27: ; preds = %for.inc32, %expr_bl
for.body29: ; preds = %for.cond27
%25 = load i64*, i64** %to25, align 8
%26 = load i64, i64* %i26, align 8
%ptridx30 = getelementptr inbounds i64, i64* %25, i64 %26
%ptroffset30 = getelementptr inbounds i64, i64* %25, i64 %26
%27 = load i64*, i64** %b23, align 8
%28 = load i64, i64* %i26, align 8
%ptridx31 = getelementptr inbounds i64, i64* %27, i64 %28
%29 = load i64, i64* %ptridx31, align 8
store i64 %29, i64* %ptridx30, align 8
%ptroffset31 = getelementptr inbounds i64, i64* %27, i64 %28
%29 = load i64, i64* %ptroffset31, align 8
store i64 %29, i64* %ptroffset30, align 8
br label %for.inc32
for.inc32: ; preds = %for.body29
@@ -368,12 +368,12 @@ for.cond44: ; preds = %for.inc49, %expr_bl
for.body46: ; preds = %for.cond44
%35 = load i64*, i64** %to41, align 8
%36 = load i64, i64* %i43, align 8
%ptridx47 = getelementptr inbounds i64, i64* %35, i64 %36
%ptroffset47 = getelementptr inbounds i64, i64* %35, i64 %36
%37 = load i64*, i64** %b39, align 8
%38 = load i64, i64* %i43, align 8
%ptridx48 = getelementptr inbounds i64, i64* %37, i64 %38
%39 = load i64, i64* %ptridx48, align 8
store i64 %39, i64* %ptridx47, align 8
%ptroffset48 = getelementptr inbounds i64, i64* %37, i64 %38
%39 = load i64, i64* %ptroffset48, align 8
store i64 %39, i64* %ptroffset47, align 8
br label %for.inc49
for.inc49: ; preds = %for.body46
@@ -395,4 +395,4 @@ expr_block.exit52: ; preds = %for.exit51
%45 = load double, double* %d2, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i32 0, i32 0), double %43, i64 %44, double %45)
ret void
}
}

View File

@@ -24,19 +24,71 @@ func void test3(long* x)
// #expect: pointer_index.ll
define void @pointer_index.test1(i32* %0) #0 {
entry:
%x = alloca i32*, align 8
%a = alloca i32, align 4
%b = alloca i32, align 4
%c = alloca i32, align 4
%d = alloca i32, align 4
store i32* %0, i32** %x, align 8
%1 = load i32*, i32** %x, align 8
%ptroffset = getelementptr inbounds i32, i32* %1, i64 0
%2 = load i32, i32* %ptroffset, align 4
store i32 %2, i32* %a, align 4
%3 = load i32*, i32** %x, align 8
%4 = load i32, i32* %3, align 8
store i32 %4, i32* %b, align 4
%5 = load i32*, i32** %x, align 8
%ptroffset1 = getelementptr inbounds i32, i32* %5, i64 1
%6 = load i32, i32* %ptroffset1, align 4
store i32 %6, i32* %c, align 4
%7 = load i32*, i32** %x, align 8
%ptroffset2 = getelementptr inbounds i32, i32* %7, i64 -1
%8 = load i32, i32* %ptroffset2, align 4
store i32 %8, i32* %d, align 4
ret void
}
; Function Attrs: nounwind
define void @pointer_index.test2(i8* %0) #0 {
entry:
%x = alloca i8*, align 8
%a = alloca i8, align 1
%b = alloca i8, align 1
%c = alloca i8, align 1
store i8* %0, i8** %x, align 8
%1 = load i8*, i8** %x, align 8
%ptroffset = getelementptr inbounds i8, i8* %1, i64 0
%2 = load i8, i8* %ptroffset, align 1
store i8 %2, i8* %a, align 1
%3 = load i8*, i8** %x, align 8
%4 = load i8, i8* %3, align 8
store i8 %4, i8* %b, align 1
%5 = load i8*, i8** %x, align 8
%ptroffset1 = getelementptr inbounds i8, i8* %5, i64 1
%6 = load i8, i8* %ptroffset1, align 1
store i8 %6, i8* %c, align 1
ret void
}
define void @pointer_index.test3(i64* %0) #0 {
entry:
%x = alloca i64*, align 8
%a = alloca i64, align 8
%b = alloca i64, align 8
%c = alloca i64, align 8
store i64* %0, i64** %x, align 8
%1 = load i64*, i64** %x, align 8
%ptridx = getelementptr inbounds i64, i64* %1, i64 0
%2 = load i64, i64* %ptridx, align 8
%ptroffset = getelementptr inbounds i64, i64* %1, i64 0
%2 = load i64, i64* %ptroffset, align 8
store i64 %2, i64* %a, align 8
%3 = load i64*, i64** %x, align 8
%4 = load i64, i64* %3, align 8
store i64 %4, i64* %b, align 8
%5 = load i64*, i64** %x, align 8
%ptridx1 = getelementptr inbounds i64, i64* %5, i64 1
%6 = load i64, i64* %ptridx1, align 8
store i64 %6, i64* %c, align 8
%ptroffset1 = getelementptr inbounds i64, i64* %5, i64 1
%6 = load i64, i64* %ptroffset1, align 8
store i64 %6, i64* %c, align 8
ret void
}

View File

@@ -0,0 +1,78 @@
module test;
extern fn void printf(char*, ...);
fn void main()
{
int[8] x;
x[0..1] = 3;
x[1..2] = 5;
x[5..7] = 52;
foreach (i : x)
{
printf("%d\n", i);
}
x[0..7] = 123;
}
/* #expect: test.ll
@.str = private constant [4 x i8] c"%d\0A\00", align 1
; Function Attrs: nounwind
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @main() #0 {
entry:
%x = alloca [8 x i32], align 16
%idx = alloca i64, align 8
%i = alloca i32, align 4
%0 = bitcast [8 x i32]* %x to i8*
call void @llvm.memset.p0i8.i64(i8* align 16 %0, i8 0, i64 32, i1 false)
%1 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 0
store i32 3, i32* %1, align 4
%2 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 1
store i32 3, i32* %2, align 4
%3 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 1
store i32 5, i32* %3, align 4
%4 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 2
store i32 5, i32* %4, align 4
%5 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 5
store i32 52, i32* %5, align 4
%6 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 6
store i32 52, i32* %6, align 4
%7 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 7
store i32 52, i32* %7, align 4
store i64 0, i64* %idx, align 8
br label %foreach.cond
foreach.cond: ; preds = %foreach.inc, %entry
%8 = load i64, i64* %idx, align 8
%lt = icmp ult i64 %8, 8
br i1 %lt, label %foreach.body, label %foreach.exit
foreach.body: ; preds = %foreach.cond
%ptroffset = getelementptr inbounds i32, [8 x i32]* %x, i64 %8
%9 = load i32, i32* %ptroffset, align 4
store i32 %9, i32* %i, align 4
%10 = load i32, i32* %i, align 4
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %10)
br label %foreach.inc
foreach.inc: ; preds = %foreach.body
%11 = load i64, i64* %idx, align 8
%12 = add i64 %11, 1
store i64 %12, i64* %idx, align 8
br label %foreach.cond
foreach.exit: ; preds = %foreach.cond
br label %cond
cond: ; preds = %assign, %foreach.exit
%13 = phi i64 [ 0, %foreach.exit ], [ %add, %assign ]
%le = icmp sle i64 %13, 7
br i1 %le, label %assign, label %exit
assign: ; preds = %cond
%14 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 %13
store i32 123, i32* %14, align 4
%add = add i64 %13, 1
br label %cond
exit: ; preds = %cond
ret void
}

View File

@@ -17,35 +17,44 @@ func void test()
store i32 0, i32* %g, align 4
store i64 0, i64* %idx, align 8
br label %foreach.cond
foreach.cond:
foreach.cond: ; preds = %foreach.inc, %entry
%1 = load i64, i64* %idx, align 8
%lt = icmp ult i64 %1, 3
br i1 %lt, label %foreach.body, label %foreach.exit
foreach.body:
%2 = getelementptr inbounds i32, [3 x i32]* %x, i64 %1
%3 = load i32, i32* %2, align 4
store i32 %3, i32* %z, align 4
%4 = load i32, i32* %z, align 4
%gt = icmp sgt i32 %4, 0
foreach.body: ; preds = %foreach.cond
%ptroffset = getelementptr inbounds i32, [3 x i32]* %x, i64 %1
%2 = load i32, i32* %ptroffset, align 4
store i32 %2, i32* %z, align 4
%3 = load i32, i32* %z, align 4
%gt = icmp sgt i32 %3, 0
br i1 %gt, label %if.then, label %if.exit
if.then:
if.then: ; preds = %foreach.body
br label %foreach.exit
if.exit:
%5 = load i32, i32* %z, align 4
%eq = icmp eq i32 %5, 1
if.exit: ; preds = %foreach.body
%4 = load i32, i32* %z, align 4
%eq = icmp eq i32 %4, 1
br i1 %eq, label %if.then1, label %if.exit2
if.then1:
if.then1: ; preds = %if.exit
br label %foreach.inc
if.exit2:
%6 = load i32, i32* %g, align 4
%7 = load i32, i32* %z, align 4
%add = add i32 %6, %7
if.exit2: ; preds = %if.exit
%5 = load i32, i32* %g, align 4
%6 = load i32, i32* %z, align 4
%add = add i32 %5, %6
store i32 %add, i32* %g, align 4
br label %foreach.inc
foreach.inc:
%8 = load i64, i64* %idx, align 8
%9 = add i64 %8, 1
store i64 %9, i64* %idx, align 8
foreach.inc: ; preds = %if.exit2, %if.then1
%7 = load i64, i64* %idx, align 8
%8 = add i64 %7, 1
store i64 %8, i64* %idx, align 8
br label %foreach.cond
foreach.exit:
foreach.exit: ; preds = %if.then, %foreach.cond
ret void
}

View File

@@ -40,171 +40,172 @@ entry:
%a = alloca float, align 4
%idx1 = alloca i64, align 8
%a2 = alloca float*, align 8
%idx9 = alloca i64, align 8
%a10 = alloca i8*, align 8
%idx10 = alloca i64, align 8
%a11 = alloca i8*, align 8
%i = alloca i64, align 8
%a18 = alloca float, align 4
%i25 = alloca i8, align 1
%idx26 = alloca i64, align 8
%a27 = alloca double, align 8
%idx34 = alloca i64, align 8
%a35 = alloca double, align 8
%a20 = alloca float, align 4
%i28 = alloca i8, align 1
%idx29 = alloca i64, align 8
%a30 = alloca double, align 8
%idx38 = alloca i64, align 8
%a39 = alloca double, align 8
%0 = bitcast [3 x float]* %foo to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x float]* @.__const to i8*), i32 12, i1 false)
store i64 0, i64* %idx, align 8
br label %foreach.cond
foreach.cond:
foreach.cond: ; preds = %foreach.inc, %entry
%1 = load i64, i64* %idx, align 8
%lt = icmp ult i64 %1, 3
br i1 %lt, label %foreach.body, label %foreach.exit
foreach.body:
%2 = getelementptr inbounds float, [3 x float]* %foo, i64 %1
%3 = load float, float* %2, align 4
store float %3, float* %a, align 4
%4 = load float, float* %a, align 4
%fpfpext = fpext float %4 to double
foreach.body: ; preds = %foreach.cond
%ptroffset = getelementptr inbounds float, [3 x float]* %foo, i64 %1
%2 = load float, float* %ptroffset, align 4
store float %2, float* %a, align 4
%3 = load float, float* %a, align 4
%fpfpext = fpext float %3 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), double %fpfpext)
br label %foreach.inc
foreach.inc:
%5 = load i64, i64* %idx, align 8
%6 = add i64 %5, 1
store i64 %6, i64* %idx, align 8
foreach.inc: ; preds = %foreach.body
%4 = load i64, i64* %idx, align 8
%5 = add i64 %4, 1
store i64 %5, i64* %idx, align 8
br label %foreach.cond
foreach.exit:
foreach.exit: ; preds = %foreach.cond
store i64 0, i64* %idx1, align 8
br label %foreach.cond3
foreach.cond3:
%7 = load i64, i64* %idx1, align 8
%lt4 = icmp ult i64 %7, 3
br i1 %lt4, label %foreach.body5, label %foreach.exit8
foreach.cond3: ; preds = %foreach.inc8, %foreach.exit
%6 = load i64, i64* %idx1, align 8
%lt4 = icmp ult i64 %6, 3
br i1 %lt4, label %foreach.body5, label %foreach.exit9
foreach.body5:
%8 = getelementptr inbounds float, [3 x float]* %foo, i64 %7
store float* %8, float** %a2, align 8
foreach.body5: ; preds = %foreach.cond3
%ptroffset6 = getelementptr inbounds float, [3 x float]* %foo, i64 %6
store float* %ptroffset6, float** %a2, align 8
%7 = load float*, float** %a2, align 8
%8 = load float, float* %7, align 8
%fmul = fmul float %8, 2.000000e+00
store float %fmul, float* %7, align 8
%9 = load float*, float** %a2, align 8
%10 = load float, float* %9, align 8
%fmul = fmul float %10, 2.000000e+00
store float %fmul, float* %9, align 8
%11 = load float*, float** %a2, align 8
%12 = load float, float* %11, align 8
%fpfpext6 = fpext float %12 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), double %fpfpext6)
br label %foreach.inc7
%fpfpext7 = fpext float %10 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), double %fpfpext7)
br label %foreach.inc8
foreach.inc7:
%13 = load i64, i64* %idx1, align 8
%14 = add i64 %13, 1
store i64 %14, i64* %idx1, align 8
foreach.inc8: ; preds = %foreach.body5
%11 = load i64, i64* %idx1, align 8
%12 = add i64 %11, 1
store i64 %12, i64* %idx1, align 8
br label %foreach.cond3
foreach.exit8:
store i64 0, i64* %idx9, align 8
br label %foreach.cond11
foreach.exit9: ; preds = %foreach.cond3
store i64 0, i64* %idx10, align 8
br label %foreach.cond12
foreach.cond11:
%15 = load i64, i64* %idx9, align 8
%lt12 = icmp ult i64 %15, 3
br i1 %lt12, label %foreach.body13, label %foreach.exit17
foreach.cond12: ; preds = %foreach.inc18, %foreach.exit9
%13 = load i64, i64* %idx10, align 8
%lt13 = icmp ult i64 %13, 3
br i1 %lt13, label %foreach.body14, label %foreach.exit19
foreach.body13:
%16 = getelementptr inbounds float, [3 x float]* %foo, i64 %15
%ptrptr = bitcast float* %16 to i8*
store i8* %ptrptr, i8** %a10, align 8
%17 = load i8*, i8** %a10, align 8
%ptrptr14 = bitcast i8* %17 to float*
%18 = load float, float* %ptrptr14, align 8
%fpfpext15 = fpext float %18 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), double %fpfpext15)
br label %foreach.inc16
foreach.body14: ; preds = %foreach.cond12
%ptroffset15 = getelementptr inbounds float, [3 x float]* %foo, i64 %13
%ptrptr = bitcast float* %ptroffset15 to i8*
store i8* %ptrptr, i8** %a11, align 8
%14 = load i8*, i8** %a11, align 8
%ptrptr16 = bitcast i8* %14 to float*
%15 = load float, float* %ptrptr16, align 8
%fpfpext17 = fpext float %15 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), double %fpfpext17)
br label %foreach.inc18
foreach.inc16:
%19 = load i64, i64* %idx9, align 8
%20 = add i64 %19, 1
store i64 %20, i64* %idx9, align 8
br label %foreach.cond11
foreach.inc18: ; preds = %foreach.body14
%16 = load i64, i64* %idx10, align 8
%17 = add i64 %16, 1
store i64 %17, i64* %idx10, align 8
br label %foreach.cond12
foreach.exit17:
foreach.exit19: ; preds = %foreach.cond12
store i64 0, i64* %i, align 8
br label %foreach.cond19
br label %foreach.cond21
foreach.cond19:
%21 = load i64, i64* %i, align 8
%lt20 = icmp ult i64 %21, 3
br i1 %lt20, label %foreach.body21, label %foreach.exit24
foreach.cond21: ; preds = %foreach.inc26, %foreach.exit19
%18 = load i64, i64* %i, align 8
%lt22 = icmp ult i64 %18, 3
br i1 %lt22, label %foreach.body23, label %foreach.exit27
foreach.body21:
%22 = getelementptr inbounds float, [3 x float]* %foo, i64 %21
%23 = load float, float* %22, align 4
store float %23, float* %a18, align 4
%24 = load i64, i64* %i, align 8
%25 = load float, float* %a18, align 4
%fpfpext22 = fpext float %25 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.3, i32 0, i32 0), i64 %24, double %fpfpext22)
br label %foreach.inc23
foreach.body23: ; preds = %foreach.cond21
%ptroffset24 = getelementptr inbounds float, [3 x float]* %foo, i64 %18
%19 = load float, float* %ptroffset24, align 4
store float %19, float* %a20, align 4
%20 = load i64, i64* %i, align 8
%21 = load float, float* %a20, align 4
%fpfpext25 = fpext float %21 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.3, i32 0, i32 0), i64 %20, double %fpfpext25)
br label %foreach.inc26
foreach.inc23:
%26 = load i64, i64* %i, align 8
%27 = add i64 %26, 1
store i64 %27, i64* %i, align 8
br label %foreach.cond19
foreach.inc26: ; preds = %foreach.body23
%22 = load i64, i64* %i, align 8
%23 = add i64 %22, 1
store i64 %23, i64* %i, align 8
br label %foreach.cond21
foreach.exit24:
store i8 0, i8* %i25, align 1
store i64 0, i64* %idx26, align 8
br label %foreach.cond28
foreach.exit27: ; preds = %foreach.cond21
store i8 0, i8* %i28, align 1
store i64 0, i64* %idx29, align 8
br label %foreach.cond31
foreach.cond28:
%28 = load i64, i64* %idx26, align 8
%lt29 = icmp ult i64 %28, 3
br i1 %lt29, label %foreach.body30, label %foreach.exit33
foreach.cond31: ; preds = %foreach.inc36, %foreach.exit27
%24 = load i64, i64* %idx29, align 8
%lt32 = icmp ult i64 %24, 3
br i1 %lt32, label %foreach.body33, label %foreach.exit37
foreach.body30:
%29 = trunc i64 %28 to i8
store i8 %29, i8* %i25, align 1
%30 = getelementptr inbounds float, [3 x float]* %foo, i64 %28
%31 = load float, float* %30, align 4
%fpfpext31 = fpext float %31 to double
store double %fpfpext31, double* %a27, align 8
%32 = load i8, i8* %i25, align 1
%uisiext = zext i8 %32 to i32
%33 = load double, double* %a27, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.4, i32 0, i32 0), i32 %uisiext, double %33)
br label %foreach.inc32
foreach.body33: ; preds = %foreach.cond31
%25 = trunc i64 %24 to i8
store i8 %25, i8* %i28, align 1
%ptroffset34 = getelementptr inbounds float, [3 x float]* %foo, i64 %24
%26 = load float, float* %ptroffset34, align 4
%fpfpext35 = fpext float %26 to double
store double %fpfpext35, double* %a30, align 8
%27 = load i8, i8* %i28, align 1
%uisiext = zext i8 %27 to i32
%28 = load double, double* %a30, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.4, i32 0, i32 0), i32 %uisiext, double %28)
br label %foreach.inc36
foreach.inc32:
%34 = load i64, i64* %idx26, align 8
foreach.inc36: ; preds = %foreach.body33
%29 = load i64, i64* %idx29, align 8
%30 = add i64 %29, 1
store i64 %30, i64* %idx29, align 8
br label %foreach.cond31
foreach.exit37: ; preds = %foreach.cond31
store i64 0, i64* %idx38, align 8
br label %foreach.cond40
foreach.cond40: ; preds = %foreach.inc45, %foreach.exit37
%31 = load i64, i64* %idx38, align 8
%lt41 = icmp ult i64 %31, 3
br i1 %lt41, label %foreach.body42, label %foreach.exit46
foreach.body42: ; preds = %foreach.cond40
%ptroffset43 = getelementptr inbounds float, [3 x float]* %foo, i64 %31
%32 = load float, float* %ptroffset43, align 4
%fpfpext44 = fpext float %32 to double
store double %fpfpext44, double* %a39, align 8
%33 = load double, double* %a39, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.5, i32 0, i32 0), double %33)
br label %foreach.inc45
foreach.inc45: ; preds = %foreach.body42
%34 = load i64, i64* %idx38, align 8
%35 = add i64 %34, 1
store i64 %35, i64* %idx26, align 8
br label %foreach.cond28
store i64 %35, i64* %idx38, align 8
br label %foreach.cond40
foreach.exit33:
store i64 0, i64* %idx34, align 8
br label %foreach.cond36
foreach.cond36:
%36 = load i64, i64* %idx34, align 8
%lt37 = icmp ult i64 %36, 3
br i1 %lt37, label %foreach.body38, label %foreach.exit41
foreach.body38:
%37 = getelementptr inbounds float, [3 x float]* %foo, i64 %36
%38 = load float, float* %37, align 4
%fpfpext39 = fpext float %38 to double
store double %fpfpext39, double* %a35, align 8
%39 = load double, double* %a35, align 8
call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.5, i32 0, i32 0), double %39)
br label %foreach.inc40
foreach.inc40:
%40 = load i64, i64* %idx34, align 8
%41 = add i64 %40, 1
store i64 %41, i64* %idx34, align 8
br label %foreach.cond36
foreach.exit41:
foreach.exit46: ; preds = %foreach.cond40
ret void
}

View File

@@ -58,7 +58,8 @@ entry:
ret { i64, %Foo* } %6
}
define zeroext i8 @foo.FooIterator__next(%FooIterator* %0, i32* %1)
; Function Attrs: nounwind
define zeroext i8 @foo.FooIterator__next(%FooIterator* %0, i32* %1) #0 {
entry:
%it = alloca %FooIterator*, align 8
%value = alloca i32*, align 8
@@ -71,34 +72,35 @@ entry:
%6 = getelementptr inbounds %FooIterator, %FooIterator* %5, i32 0, i32 1
%7 = load %Foo*, %Foo** %6, align 8
%8 = getelementptr inbounds %Foo, %Foo* %7, i32 0, i32 0
%len = getelementptr inbounds %"int[]", %"int[]"* %8, i32 0, i32 1
%9 = load i64, i64* %len, align 8
%eq = icmp eq i64 %4, %9
%9 = getelementptr inbounds %"int[]", %"int[]"* %8, i32 0, i32 1
%10 = load i64, i64* %9, align 8
%eq = icmp eq i64 %4, %10
br i1 %eq, label %if.then, label %if.exit
if.then:
if.then: ; preds = %entry
ret i8 0
if.exit:
%10 = load i32*, i32** %value, align 8
%11 = load %FooIterator*, %FooIterator** %it, align 8
%12 = getelementptr inbounds %FooIterator, %FooIterator* %11, i32 0, i32 1
%13 = load %Foo*, %Foo** %12, align 8
%14 = getelementptr inbounds %Foo, %Foo* %13, i32 0, i32 0
%subarrayptr = getelementptr inbounds %"int[]", %"int[]"* %14, i32 0, i32 0
%saptr = load i32*, i32** %subarrayptr, align 8
%15 = load %FooIterator*, %FooIterator** %it, align 8
%16 = getelementptr inbounds %FooIterator, %FooIterator* %15, i32 0, i32 0
%17 = load i64, i64* %16, align 8
%add = add i64 %17, 1
store i64 %add, i64* %16, align 8
%sarridx = getelementptr inbounds i32, i32* %saptr, i64 %17
%18 = load i32, i32* %sarridx, align 4
store i32 %18, i32* %10, align 8
if.exit: ; preds = %entry
%11 = load i32*, i32** %value, align 8
%12 = load %FooIterator*, %FooIterator** %it, align 8
%13 = getelementptr inbounds %FooIterator, %FooIterator* %12, i32 0, i32 1
%14 = load %Foo*, %Foo** %13, align 8
%15 = getelementptr inbounds %Foo, %Foo* %14, i32 0, i32 0
%16 = getelementptr inbounds %"int[]", %"int[]"* %15, i32 0, i32 0
%17 = load i32*, i32** %16, align 8
%18 = load %FooIterator*, %FooIterator** %it, align 8
%19 = getelementptr inbounds %FooIterator, %FooIterator* %18, i32 0, i32 0
%20 = load i64, i64* %19, align 8
%add = add i64 %20, 1
store i64 %add, i64* %19, align 8
%ptroffset = getelementptr inbounds i32, i32* %17, i64 %20
%21 = load i32, i32* %ptroffset, align 4
store i32 %21, i32* %11, align 8
ret i8 1
}
define void @main()
; Function Attrs: nounwind
define void @main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8
@@ -121,19 +123,19 @@ entry:
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %7, i8* align 8 %8, i32 16, i1 false)
br label %for.cond
for.cond:
for.cond: ; preds = %entry
%9 = call i8 @foo.FooIterator__next(%FooIterator* %.iterator, i32* %f)
%10 = trunc i8 %9 to i1
br i1 %10, label %for.body, label %for.exit
for.body:
for.body: ; preds = %for.cond
%11 = load i32, i32* %f, align 4
%12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %11)
br label %while.begin
while.begin:
while.begin: ; preds = %for.body
br label %for.exit
for.exit:
for.exit: ; preds = %while.begin, %for.cond
ret void
}
}

View File

@@ -38,7 +38,8 @@ extern func int printf(char *fmt, ...);
// #expect: foo.ll
define void @main()
define void @main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8
%f = alloca i32, align 4
@@ -84,9 +85,9 @@ for.cond: ; preds = %expr_block.exit
%16 = getelementptr inbounds %FooIterator, %FooIterator* %15, i32 0, i32 1
%17 = load %Foo*, %Foo** %16, align 8
%18 = getelementptr inbounds %Foo, %Foo* %17, i32 0, i32 0
%len = getelementptr inbounds %"int[]", %"int[]"* %18, i32 0, i32 1
%19 = load i64, i64* %len, align 8
%eq = icmp eq i64 %14, %19
%19 = getelementptr inbounds %"int[]", %"int[]"* %18, i32 0, i32 1
%20 = load i64, i64* %19, align 8
%eq = icmp eq i64 %14, %20
br i1 %eq, label %if.then, label %if.exit
if.then: ; preds = %for.cond
@@ -94,32 +95,32 @@ if.then: ; preds = %for.cond
br label %expr_block.exit3
if.exit: ; preds = %for.cond
%20 = load i32*, i32** %value, align 8
%21 = load %FooIterator*, %FooIterator** %it, align 8
%22 = getelementptr inbounds %FooIterator, %FooIterator* %21, i32 0, i32 1
%23 = load %Foo*, %Foo** %22, align 8
%24 = getelementptr inbounds %Foo, %Foo* %23, i32 0, i32 0
%subarrayptr = getelementptr inbounds %"int[]", %"int[]"* %24, i32 0, i32 0
%saptr = load i32*, i32** %subarrayptr, align 8
%25 = load %FooIterator*, %FooIterator** %it, align 8
%26 = getelementptr inbounds %FooIterator, %FooIterator* %25, i32 0, i32 0
%27 = load i64, i64* %26, align 8
%add = add i64 %27, 1
store i64 %add, i64* %26, align 8
%sarridx = getelementptr inbounds i32, i32* %saptr, i64 %27
%28 = load i32, i32* %sarridx, align 4
store i32 %28, i32* %20, align 8
%21 = load i32*, i32** %value, align 8
%22 = load %FooIterator*, %FooIterator** %it, align 8
%23 = getelementptr inbounds %FooIterator, %FooIterator* %22, i32 0, i32 1
%24 = load %Foo*, %Foo** %23, align 8
%25 = getelementptr inbounds %Foo, %Foo* %24, i32 0, i32 0
%26 = getelementptr inbounds %"int[]", %"int[]"* %25, i32 0, i32 0
%27 = load i32*, i32** %26, align 8
%28 = load %FooIterator*, %FooIterator** %it, align 8
%29 = getelementptr inbounds %FooIterator, %FooIterator* %28, i32 0, i32 0
%30 = load i64, i64* %29, align 8
%add = add i64 %30, 1
store i64 %add, i64* %29, align 8
%ptroffset = getelementptr inbounds i32, i32* %27, i64 %30
%31 = load i32, i32* %ptroffset, align 4
store i32 %31, i32* %21, align 8
store i8 1, i8* %blockret2, align 1
br label %expr_block.exit3
expr_block.exit3: ; preds = %if.exit, %if.then
%29 = load i8, i8* %blockret2, align 1
%30 = trunc i8 %29 to i1
br i1 %30, label %for.body, label %for.exit
%32 = load i8, i8* %blockret2, align 1
%33 = trunc i8 %32 to i1
br i1 %33, label %for.body, label %for.exit
for.body: ; preds = %expr_block.exit3
%31 = load i32, i32* %f, align 4
%32 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %31)
%34 = load i32, i32* %f, align 4
%35 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %34)
br label %while.begin
while.begin: ; preds = %for.body
@@ -127,4 +128,4 @@ while.begin: ; preds = %for.body
for.exit: ; preds = %while.begin, %expr_block.exit3
ret void
}
}

View File

@@ -3,7 +3,7 @@ module test;
func void test1()
{
bool! x = 0;
if (x) // #error: 'bool!' cannot be converted to 'bool'
if (x) // #error: 'bool!' to 'bool'
{
x = 100;
}
@@ -12,7 +12,7 @@ func void test1()
func void test2()
{
bool! x = 0;
while (x) // #error: 'bool!' cannot be converted to 'bool'
while (x) // #error: 'bool!' to 'bool'
{
x = false;
}
@@ -30,5 +30,5 @@ func void test3()
{
x = !x;
}
while (x); // #error: 'bool!' cannot be converted to 'bool'
while (x); // #error: A failable 'bool!' cannot be implicitly converted to a regular boolean value
}

View File

@@ -28,9 +28,9 @@ func void test_check_nums()
Foo f = A;
switch (f)
{
case 2:
case (Foo)(2):
break;
case 0:
case (Foo)(0):
break;
}
}
@@ -66,7 +66,7 @@ func void test_duplicate_case2(Foo i)
{
case A:
break;
case 2:
case (Foo)(2):
break;
case A: // #error: same case value appears
break;
@@ -79,7 +79,7 @@ func void test_duplicate_case3(Foo i)
{
case A:
break;
case 0: // #error: same case value appears
case (Foo)(0): // #error: same case value appears
break;
}
}

View File

@@ -46,7 +46,7 @@ func Event test(int x)
cond.phi: ; preds = %cond.rhs, %cond.lhs
%val = phi %Event [ %4, %cond.lhs ], [ %5, %cond.rhs ]
store %Event %val, %Event* %taddr, align 4
%dive = getelementptr inbounds %Event, %Event* %taddr, i32 0, i32 0
%6 = load i32, i32* %dive, align 4
ret i32 %6
%6 = getelementptr inbounds %Event, %Event* %taddr, i32 0, i32 0
%7 = load i32, i32* %6, align 4
ret i32 %7
}

View File

@@ -28,18 +28,19 @@ func Event test(int x)
%intbool = icmp ne i32 %3, 0
br i1 %intbool, label %cond.lhs, label %cond.rhs
cond.lhs:
cond.lhs: ; preds = %entry
%4 = load %Event, %Event* %foo, align 4
br label %cond.phi
cond.rhs:
cond.rhs: ; preds = %entry
%5 = load %Event, %Event* %bar, align 4
br label %cond.phi
cond.phi:
cond.phi: ; preds = %cond.rhs, %cond.lhs
%val = phi %Event [ %4, %cond.lhs ], [ %5, %cond.rhs ]
store %Event %val, %Event* %taddr, align 4
%dive = getelementptr inbounds %Event, %Event* %taddr, i32 0, i32 0
%6 = load i32, i32* %dive, align 4
%7 = zext i32 %6 to i64
ret i64 %7
%6 = getelementptr inbounds %Event, %Event* %taddr, i32 0, i32 0
%7 = load i32, i32* %6, align 4
%8 = zext i32 %7 to i64
ret i64 %8
}

View File

@@ -38,11 +38,11 @@ entry:
%y = alloca %"char[]", align 8
%z = alloca %"char[]", align 8
%cmp.idx = alloca i64, align 8
%cmp.idx4 = alloca i64, align 8
%cmp.idx5 = alloca i64, align 8
%switch = alloca %"char[]", align 8
%cmp.idx17 = alloca i64, align 8
%cmp.idx28 = alloca i64, align 8
%cmp.idx41 = alloca i64, align 8
%cmp.idx18 = alloca i64, align 8
%cmp.idx29 = alloca i64, align 8
%cmp.idx42 = alloca i64, align 8
store %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0), i64 4 }, %"char[]"* %y, align 8
store %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.1, i32 0, i32 0), i64 4 }, %"char[]"* %z, align 8
%0 = load %"char[]", %"char[]"* %y, align 8
@@ -61,14 +61,14 @@ subarray_loop_start: ; preds = %subarray_loop_compa
br i1 %lt, label %subarray_loop_comparison, label %subarray_cmp_exit
subarray_loop_comparison: ; preds = %subarray_loop_start
%lhs.ptr = getelementptr inbounds i8, i8* %2, i64 %3
%rhs.ptr = getelementptr inbounds i8, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i32 0, i32 0), i64 %3
%4 = load i8, i8* %lhs.ptr, align 1
%5 = load i8, i8* %rhs.ptr, align 1
%eq1 = icmp eq i8 %4, %5
%ptroffset = getelementptr inbounds i8, i8* %2, i64 %3
%ptroffset1 = getelementptr inbounds i8, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i32 0, i32 0), i64 %3
%4 = load i8, i8* %ptroffset, align 1
%5 = load i8, i8* %ptroffset1, align 1
%eq2 = icmp eq i8 %4, %5
%6 = add i64 %3, 1
store i64 %6, i64* %cmp.idx, align 8
br i1 %eq1, label %subarray_loop_start, label %subarray_cmp_exit
br i1 %eq2, label %subarray_loop_start, label %subarray_cmp_exit
subarray_cmp_exit: ; preds = %subarray_loop_comparison, %subarray_loop_start, %entry
%subarray_cmp_phi = phi i1 [ true, %subarray_loop_start ], [ false, %entry ], [ false, %subarray_loop_comparison ]
@@ -85,149 +85,149 @@ if.exit: ; preds = %if.then, %subarray_
%10 = extractvalue %"char[]" %8, 1
%11 = extractvalue %"char[]" %7, 0
%12 = extractvalue %"char[]" %8, 0
%eq2 = icmp eq i64 %9, %10
br i1 %eq2, label %subarray_cmp_values3, label %subarray_cmp_exit11
%eq3 = icmp eq i64 %9, %10
br i1 %eq3, label %subarray_cmp_values4, label %subarray_cmp_exit12
subarray_cmp_values3: ; preds = %if.exit
store i64 0, i64* %cmp.idx4, align 8
br label %subarray_loop_start5
subarray_cmp_values4: ; preds = %if.exit
store i64 0, i64* %cmp.idx5, align 8
br label %subarray_loop_start6
subarray_loop_start5: ; preds = %subarray_loop_comparison7, %subarray_cmp_values3
%13 = load i64, i64* %cmp.idx4, align 8
%lt6 = icmp ult i64 %13, %9
br i1 %lt6, label %subarray_loop_comparison7, label %subarray_cmp_exit11
subarray_loop_start6: ; preds = %subarray_loop_comparison8, %subarray_cmp_values4
%13 = load i64, i64* %cmp.idx5, align 8
%lt7 = icmp ult i64 %13, %9
br i1 %lt7, label %subarray_loop_comparison8, label %subarray_cmp_exit12
subarray_loop_comparison7: ; preds = %subarray_loop_start5
%lhs.ptr8 = getelementptr inbounds i8, i8* %11, i64 %13
%rhs.ptr9 = getelementptr inbounds i8, i8* %12, i64 %13
%14 = load i8, i8* %lhs.ptr8, align 1
%15 = load i8, i8* %rhs.ptr9, align 1
%eq10 = icmp eq i8 %14, %15
subarray_loop_comparison8: ; preds = %subarray_loop_start6
%ptroffset9 = getelementptr inbounds i8, i8* %11, i64 %13
%ptroffset10 = getelementptr inbounds i8, i8* %12, i64 %13
%14 = load i8, i8* %ptroffset9, align 1
%15 = load i8, i8* %ptroffset10, align 1
%eq11 = icmp eq i8 %14, %15
%16 = add i64 %13, 1
store i64 %16, i64* %cmp.idx4, align 8
br i1 %eq10, label %subarray_loop_start5, label %subarray_cmp_exit11
store i64 %16, i64* %cmp.idx5, align 8
br i1 %eq11, label %subarray_loop_start6, label %subarray_cmp_exit12
subarray_cmp_exit11: ; preds = %subarray_loop_comparison7, %subarray_loop_start5, %if.exit
%subarray_cmp_phi12 = phi i1 [ true, %subarray_loop_start5 ], [ false, %if.exit ], [ false, %subarray_loop_comparison7 ]
br i1 %subarray_cmp_phi12, label %if.then13, label %if.exit14
subarray_cmp_exit12: ; preds = %subarray_loop_comparison8, %subarray_loop_start6, %if.exit
%subarray_cmp_phi13 = phi i1 [ true, %subarray_loop_start6 ], [ false, %if.exit ], [ false, %subarray_loop_comparison8 ]
br i1 %subarray_cmp_phi13, label %if.then14, label %if.exit15
if.then13: ; preds = %subarray_cmp_exit11
if.then14: ; preds = %subarray_cmp_exit12
call void (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.4, i32 0, i32 0))
br label %if.exit14
br label %if.exit15
if.exit14: ; preds = %if.then13, %subarray_cmp_exit11
if.exit15: ; preds = %if.then14, %subarray_cmp_exit12
%17 = bitcast %"char[]"* %switch to i8*
%18 = bitcast %"char[]"* %y to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %17, i8* align 8 %18, i32 16, i1 false)
br label %switch.entry
switch.entry: ; preds = %if.exit14
switch.entry: ; preds = %if.exit15
%19 = load %"char[]", %"char[]"* %switch, align 8
%20 = extractvalue %"char[]" %19, 1
%21 = extractvalue %"char[]" %19, 0
%eq15 = icmp eq i64 4, %20
br i1 %eq15, label %subarray_cmp_values16, label %subarray_cmp_exit24
%eq16 = icmp eq i64 4, %20
br i1 %eq16, label %subarray_cmp_values17, label %subarray_cmp_exit25
subarray_cmp_values16: ; preds = %switch.entry
store i64 0, i64* %cmp.idx17, align 8
br label %subarray_loop_start18
subarray_cmp_values17: ; preds = %switch.entry
store i64 0, i64* %cmp.idx18, align 8
br label %subarray_loop_start19
subarray_loop_start18: ; preds = %subarray_loop_comparison20, %subarray_cmp_values16
%22 = load i64, i64* %cmp.idx17, align 8
%lt19 = icmp ult i64 %22, 4
br i1 %lt19, label %subarray_loop_comparison20, label %subarray_cmp_exit24
subarray_loop_start19: ; preds = %subarray_loop_comparison21, %subarray_cmp_values17
%22 = load i64, i64* %cmp.idx18, align 8
%lt20 = icmp ult i64 %22, 4
br i1 %lt20, label %subarray_loop_comparison21, label %subarray_cmp_exit25
subarray_loop_comparison20: ; preds = %subarray_loop_start18
%lhs.ptr21 = getelementptr inbounds i8, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.5, i32 0, i32 0), i64 %22
%rhs.ptr22 = getelementptr inbounds i8, i8* %21, i64 %22
%23 = load i8, i8* %lhs.ptr21, align 1
%24 = load i8, i8* %rhs.ptr22, align 1
%eq23 = icmp eq i8 %23, %24
subarray_loop_comparison21: ; preds = %subarray_loop_start19
%ptroffset22 = getelementptr inbounds i8, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.5, i32 0, i32 0), i64 %22
%ptroffset23 = getelementptr inbounds i8, i8* %21, i64 %22
%23 = load i8, i8* %ptroffset22, align 1
%24 = load i8, i8* %ptroffset23, align 1
%eq24 = icmp eq i8 %23, %24
%25 = add i64 %22, 1
store i64 %25, i64* %cmp.idx17, align 8
br i1 %eq23, label %subarray_loop_start18, label %subarray_cmp_exit24
store i64 %25, i64* %cmp.idx18, align 8
br i1 %eq24, label %subarray_loop_start19, label %subarray_cmp_exit25
subarray_cmp_exit24: ; preds = %subarray_loop_comparison20, %subarray_loop_start18, %switch.entry
%subarray_cmp_phi25 = phi i1 [ true, %subarray_loop_start18 ], [ false, %switch.entry ], [ false, %subarray_loop_comparison20 ]
br i1 %subarray_cmp_phi25, label %switch.case, label %next_if
subarray_cmp_exit25: ; preds = %subarray_loop_comparison21, %subarray_loop_start19, %switch.entry
%subarray_cmp_phi26 = phi i1 [ true, %subarray_loop_start19 ], [ false, %switch.entry ], [ false, %subarray_loop_comparison21 ]
br i1 %subarray_cmp_phi26, label %switch.case, label %next_if
switch.case: ; preds = %subarray_cmp_exit24
switch.case: ; preds = %subarray_cmp_exit25
call void (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i32 0, i32 0))
br label %switch.exit
next_if: ; preds = %subarray_cmp_exit24
next_if: ; preds = %subarray_cmp_exit25
%26 = extractvalue %"char[]" %19, 1
%27 = extractvalue %"char[]" %19, 0
%eq26 = icmp eq i64 5, %26
br i1 %eq26, label %subarray_cmp_values27, label %subarray_cmp_exit35
%eq27 = icmp eq i64 5, %26
br i1 %eq27, label %subarray_cmp_values28, label %subarray_cmp_exit36
subarray_cmp_values27: ; preds = %next_if
store i64 0, i64* %cmp.idx28, align 8
br label %subarray_loop_start29
subarray_cmp_values28: ; preds = %next_if
store i64 0, i64* %cmp.idx29, align 8
br label %subarray_loop_start30
subarray_loop_start29: ; preds = %subarray_loop_comparison31, %subarray_cmp_values27
%28 = load i64, i64* %cmp.idx28, align 8
%lt30 = icmp ult i64 %28, 5
br i1 %lt30, label %subarray_loop_comparison31, label %subarray_cmp_exit35
subarray_loop_start30: ; preds = %subarray_loop_comparison32, %subarray_cmp_values28
%28 = load i64, i64* %cmp.idx29, align 8
%lt31 = icmp ult i64 %28, 5
br i1 %lt31, label %subarray_loop_comparison32, label %subarray_cmp_exit36
subarray_loop_comparison31: ; preds = %subarray_loop_start29
%lhs.ptr32 = getelementptr inbounds i8, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.7, i32 0, i32 0), i64 %28
%rhs.ptr33 = getelementptr inbounds i8, i8* %27, i64 %28
%29 = load i8, i8* %lhs.ptr32, align 1
%30 = load i8, i8* %rhs.ptr33, align 1
%eq34 = icmp eq i8 %29, %30
subarray_loop_comparison32: ; preds = %subarray_loop_start30
%ptroffset33 = getelementptr inbounds i8, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.7, i32 0, i32 0), i64 %28
%ptroffset34 = getelementptr inbounds i8, i8* %27, i64 %28
%29 = load i8, i8* %ptroffset33, align 1
%30 = load i8, i8* %ptroffset34, align 1
%eq35 = icmp eq i8 %29, %30
%31 = add i64 %28, 1
store i64 %31, i64* %cmp.idx28, align 8
br i1 %eq34, label %subarray_loop_start29, label %subarray_cmp_exit35
store i64 %31, i64* %cmp.idx29, align 8
br i1 %eq35, label %subarray_loop_start30, label %subarray_cmp_exit36
subarray_cmp_exit35: ; preds = %subarray_loop_comparison31, %subarray_loop_start29, %next_if
%subarray_cmp_phi36 = phi i1 [ true, %subarray_loop_start29 ], [ false, %next_if ], [ false, %subarray_loop_comparison31 ]
br i1 %subarray_cmp_phi36, label %switch.case37, label %next_if38
subarray_cmp_exit36: ; preds = %subarray_loop_comparison32, %subarray_loop_start30, %next_if
%subarray_cmp_phi37 = phi i1 [ true, %subarray_loop_start30 ], [ false, %next_if ], [ false, %subarray_loop_comparison32 ]
br i1 %subarray_cmp_phi37, label %switch.case38, label %next_if39
switch.case37: ; preds = %subarray_cmp_exit35
switch.case38: ; preds = %subarray_cmp_exit36
call void (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.8, i32 0, i32 0))
br label %switch.exit
next_if38: ; preds = %subarray_cmp_exit35
next_if39: ; preds = %subarray_cmp_exit36
%32 = extractvalue %"char[]" %19, 1
%33 = extractvalue %"char[]" %19, 0
%eq39 = icmp eq i64 4, %32
br i1 %eq39, label %subarray_cmp_values40, label %subarray_cmp_exit48
%eq40 = icmp eq i64 4, %32
br i1 %eq40, label %subarray_cmp_values41, label %subarray_cmp_exit49
subarray_cmp_values40: ; preds = %next_if38
store i64 0, i64* %cmp.idx41, align 8
br label %subarray_loop_start42
subarray_cmp_values41: ; preds = %next_if39
store i64 0, i64* %cmp.idx42, align 8
br label %subarray_loop_start43
subarray_loop_start42: ; preds = %subarray_loop_comparison44, %subarray_cmp_values40
%34 = load i64, i64* %cmp.idx41, align 8
%lt43 = icmp ult i64 %34, 4
br i1 %lt43, label %subarray_loop_comparison44, label %subarray_cmp_exit48
subarray_loop_start43: ; preds = %subarray_loop_comparison45, %subarray_cmp_values41
%34 = load i64, i64* %cmp.idx42, align 8
%lt44 = icmp ult i64 %34, 4
br i1 %lt44, label %subarray_loop_comparison45, label %subarray_cmp_exit49
subarray_loop_comparison44: ; preds = %subarray_loop_start42
%lhs.ptr45 = getelementptr inbounds i8, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.9, i32 0, i32 0), i64 %34
%rhs.ptr46 = getelementptr inbounds i8, i8* %33, i64 %34
%35 = load i8, i8* %lhs.ptr45, align 1
%36 = load i8, i8* %rhs.ptr46, align 1
%eq47 = icmp eq i8 %35, %36
subarray_loop_comparison45: ; preds = %subarray_loop_start43
%ptroffset46 = getelementptr inbounds i8, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.9, i32 0, i32 0), i64 %34
%ptroffset47 = getelementptr inbounds i8, i8* %33, i64 %34
%35 = load i8, i8* %ptroffset46, align 1
%36 = load i8, i8* %ptroffset47, align 1
%eq48 = icmp eq i8 %35, %36
%37 = add i64 %34, 1
store i64 %37, i64* %cmp.idx41, align 8
br i1 %eq47, label %subarray_loop_start42, label %subarray_cmp_exit48
store i64 %37, i64* %cmp.idx42, align 8
br i1 %eq48, label %subarray_loop_start43, label %subarray_cmp_exit49
subarray_cmp_exit48: ; preds = %subarray_loop_comparison44, %subarray_loop_start42, %next_if38
%subarray_cmp_phi49 = phi i1 [ true, %subarray_loop_start42 ], [ false, %next_if38 ], [ false, %subarray_loop_comparison44 ]
br i1 %subarray_cmp_phi49, label %switch.case50, label %next_if51
subarray_cmp_exit49: ; preds = %subarray_loop_comparison45, %subarray_loop_start43, %next_if39
%subarray_cmp_phi50 = phi i1 [ true, %subarray_loop_start43 ], [ false, %next_if39 ], [ false, %subarray_loop_comparison45 ]
br i1 %subarray_cmp_phi50, label %switch.case51, label %next_if52
switch.case50: ; preds = %subarray_cmp_exit48
switch.case51: ; preds = %subarray_cmp_exit49
call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.10, i32 0, i32 0))
br label %switch.exit
next_if51: ; preds = %subarray_cmp_exit48
next_if52: ; preds = %subarray_cmp_exit49
br label %switch.default
switch.default: ; preds = %next_if51
switch.default: ; preds = %next_if52
call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.11, i32 0, i32 0))
br label %switch.exit
switch.exit: ; preds = %switch.default, %switch.case50, %switch.case37, %switch.case
switch.exit: ; preds = %switch.default, %switch.case51, %switch.case38, %switch.case
ret void
}
}

View File

@@ -10,8 +10,7 @@ func void test()
%y = alloca %"int[]", align 8
%0 = bitcast [3 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
%1 = bitcast [3 x i32]* %x to i32*
%offset = getelementptr inbounds i32, i32* %1, i64 1
%2 = insertvalue %"int[]" undef, i32* %offset, 0
%1 = getelementptr inbounds [3 x i32], [3 x i32]* %x, i64 0, i64 1
%2 = insertvalue %"int[]" undef, i32* %1, 0
%3 = insertvalue %"int[]" %2, i64 2, 1
store %"int[]" %3, %"int[]"* %y, align 8

View File

@@ -11,9 +11,8 @@ func void test()
%y = alloca %"int[]", align 8
%0 = bitcast [3 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
%1 = bitcast [3 x i32]* %x to i32*
%offset = getelementptr inbounds i32, i32* %1, i64 1
%2 = insertvalue %"int[]" undef, i32* %offset, 0
%1 = getelementptr inbounds [3 x i32], [3 x i32]* %x, i64 0, i64 1
%2 = insertvalue %"int[]" undef, i32* %1, 0
%3 = insertvalue %"int[]" %2, i64 2, 1
store %"int[]" %3, %"int[]"* %y, align 8

View File

@@ -10,8 +10,7 @@ func void test()
%y = alloca %"int[]", align 8
%0 = bitcast [3 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
%1 = bitcast [3 x i32]* %x to i32*
%offset = getelementptr inbounds i32, i32* %1, i64 1
%2 = insertvalue %"int[]" undef, i32* %offset, 0
%1 = getelementptr inbounds [3 x i32], [3 x i32]* %x, i64 0, i64 1
%2 = insertvalue %"int[]" undef, i32* %1, 0
%3 = insertvalue %"int[]" %2, i64 1, 1
store %"int[]" %3, %"int[]"* %y, align 8

View File

@@ -10,8 +10,7 @@ func void test()
%y = alloca %"int[]", align 8
%0 = bitcast [3 x i32]* %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false)
%1 = bitcast [3 x i32]* %x to i32*
%offset = getelementptr inbounds i32, i32* %1, i64 0
%2 = insertvalue %"int[]" undef, i32* %offset, 0
%1 = getelementptr inbounds [3 x i32], [3 x i32]* %x, i64 0, i64 0
%2 = insertvalue %"int[]" undef, i32* %1, 0
%3 = insertvalue %"int[]" %2, i64 3, 1
store %"int[]" %3, %"int[]"* %y, align 8

View File

@@ -0,0 +1,14 @@
errtype MyError
{
FOO
}
fn void test()
{
int x = 0;
switch (x)
{
case MyError.FOO!: // #error: You cannot have a failable here
x = x + 1;
}
}

View File

@@ -34,7 +34,7 @@ func void enumInferenceTest()
return;
case B:
return;
case 111:
case (Inf2)(111):
x1 += 1;
return;
default:

View File

@@ -2,6 +2,35 @@
#include <llvm/ADT/ArrayRef.h>
#include <llvm/Support/raw_ostream.h>
// For hacking the C API
#include "llvm-c/Core.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <system_error>
namespace lld {
namespace coff {
bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
@@ -79,8 +108,27 @@ static bool llvm_link(ObjFormat format, const char **args, int arg_count, const
return false;
}
extern "C" {
LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices, unsigned NumIndices) {
llvm::ArrayRef<llvm::Constant *> IdxList(llvm::unwrap<llvm::Constant>(ConstantIndices, NumIndices),
NumIndices);
llvm::Constant *Val = llvm::unwrap<llvm::Constant>(ConstantVal);
return wrap(llvm::ConstantExpr::getGetElementPtr(llvm::unwrap(Ty), Val, IdxList));
}
LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty,
LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices,
unsigned NumIndices) {
llvm::ArrayRef<llvm::Constant *> IdxList(llvm::unwrap<llvm::Constant>(ConstantIndices, NumIndices),
NumIndices);
llvm::Constant *Val = llvm::unwrap<llvm::Constant>(ConstantVal);
return wrap(llvm::ConstantExpr::getInBoundsGetElementPtr(llvm::unwrap(Ty), Val, IdxList));
}
bool llvm_link_elf(const char **args, int arg_count, const char** error_string)
{
return llvm_link(ELF, args, arg_count, error_string);