Removal of any-switches

This commit is contained in:
Christoffer Lerno
2025-03-03 15:02:25 +01:00
parent 13f824e349
commit 0925010c07
13 changed files with 101 additions and 521 deletions

View File

@@ -479,10 +479,9 @@ fn usz! Formatter.vprintf(&self, String format, any[] anys)
nextcase;
case 'h':
char[] out @noinit;
switch (current)
switch (current.type)
{
case char[]:
out = *current;
case ichar[]:
out = *(char[]*)current;
default:

View File

@@ -52,40 +52,40 @@ fn uint128! int_from_any(any arg, bool *is_neg) @private
break;
}
*is_neg = false;
switch (arg)
switch (arg.type)
{
case bool:
return (uint128)*arg;
return *(uint128*)arg;
case ichar:
int val = *arg;
int val = *(ichar*)arg;
return (*is_neg = val < 0) ? (~(uint128)val) + 1 : (uint128)val;
case short:
int val = *arg;
int val = *(short*)arg;
return (*is_neg = val < 0) ? (~(uint128)val) + 1 : (uint128)val;
case int:
int val = *arg;
int val = *(int*)arg;
return (*is_neg = val < 0) ? (~(uint128)val) + 1 : (uint128)val;
case long:
long val = *arg;
long val = *(long*)arg;
return (*is_neg = val < 0) ? (~(uint128)val) + 1 : (uint128)val;
case int128:
int128 val = *arg;
int128 val = *(int128*)arg;
return (*is_neg = val < 0) ? (~(uint128)val) + 1 : (uint128)val;
case char:
return *arg;
return *(char*)arg;
case ushort:
return *arg;
return *(ushort*)arg;
case uint:
return *arg;
return *(uint*)arg;
case ulong:
return *arg;
return *(ulong*)arg;
case uint128:
return *arg;
return *(uint128*)arg;
case float:
float f = *arg;
float f = *(float*)arg;
return (uint128)((*is_neg = f < 0) ? -f : f);
case double:
double d = *arg;
double d = *(double*)arg;
return (uint128)((*is_neg = d < 0) ? -d : d);
default:
return FormattingFault.BAD_FORMAT?;
@@ -101,34 +101,34 @@ fn FloatType! float_from_any(any arg) @private
{
return float_from_any(arg.as_inner());
}
switch (arg)
switch (arg.type)
{
case bool:
return (FloatType)*arg;
return (FloatType)*(bool*)arg;
case ichar:
return *arg;
return *(ichar*)arg;
case short:
return *arg;
return *(short*)arg;
case int:
return *arg;
return *(int*)arg;
case long:
return *arg;
return *(long*)arg;
case int128:
return *arg;
return *(int128*)arg;
case char:
return *arg;
return *(char*)arg;
case ushort:
return *arg;
return *(ushort*)arg;
case uint:
return *arg;
return *(uint*)arg;
case ulong:
return *arg;
return *(ulong*)arg;
case uint128:
return *arg;
return *(uint128*)arg;
case float:
return (FloatType)*arg;
return (FloatType)*(float*)arg;
case double:
return (FloatType)*arg;
return (FloatType)*(double*)arg;
default:
return FormattingFault.BAD_FORMAT?;
}

View File

@@ -15,6 +15,7 @@
- Disallow inline use of nested generics (e.g. `List{List{int}}`.
- Remove `.allocator = allocator` syntax for functions.
- Remove `@operator(construct)`.
- Removal of "any-switch".
### Fixes
- Fix address sanitizer to work on MachO targets (e.g. MacOS).

View File

@@ -1057,22 +1057,6 @@ typedef struct
BuiltinFunction builtin;
} ExprBuiltin;
typedef struct
{
bool is_assign : 1;
bool is_deref : 1;
union
{
struct
{
const char *new_ident;
SourceSpan span;
Expr *any_expr;
};
Decl *variable;
};
} ExprAnySwitch;
typedef struct
{
ExprId parent;
@@ -1132,7 +1116,6 @@ struct Expr_
union {
ExprResolvedAccess access_resolved_expr;
ExprUnresolvedAccess access_unresolved_expr;// 16
ExprAnySwitch any_switch; // 32
ExprBinary binary_expr; // 12
ExprBinary veccomp_expr;
ExprBodyExpansion body_expansion_expr; // 24
@@ -3486,7 +3469,6 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc)
case EXPR_TYPEINFO:
case EXPR_UNARY:
case EXPR_UNRESOLVED_IDENTIFIER:
case EXPR_ANYSWITCH:
case EXPR_VASPLAT:
case EXPR_MACRO_BODY:
case EXPR_DEFAULT_ARG:

View File

@@ -295,7 +295,6 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
switch (source_expr->expr_kind)
{
case EXPR_TYPECALL:
case EXPR_ANYSWITCH:
case EXPR_CT_SUBSCRIPT:
UNREACHABLE
case EXPR_OTHER_CONTEXT:

View File

@@ -716,7 +716,6 @@ typedef enum
{
EXPR_ACCESS_RESOLVED,
EXPR_ACCESS_UNRESOLVED,
EXPR_ANYSWITCH,
EXPR_ASM,
EXPR_BENCHMARK_HOOK,
EXPR_BINARY,
@@ -1601,7 +1600,7 @@ typedef enum
case EXPR_CT_CASTABLE: case EXPR_CT_IS_CONST: \
case EXPR_CT_ARG: case EXPR_TYPEINFO: case EXPR_CT_IDENT: case EXPR_HASH_IDENT: \
case EXPR_COMPILER_CONST: case EXPR_CT_CALL: \
case EXPR_SPLAT: case EXPR_ANYSWITCH: case EXPR_STRINGIFY: case EXPR_TYPECALL: \
case EXPR_SPLAT: case EXPR_STRINGIFY: case EXPR_TYPECALL: \
case EXPR_CT_EVAL
static_assert(EXPR_LAST < 128, "Too many expression types");

View File

@@ -14,7 +14,6 @@ const char *expr_kind_to_string(ExprKind kind)
{
case EXPR_ACCESS_UNRESOLVED: return "access_unresolved";
case EXPR_ACCESS_RESOLVED: return "access_resolved";
case EXPR_ANYSWITCH: return "anyswitch";
case EXPR_ASM: return "asm";
case EXPR_BENCHMARK_HOOK: return "benchmark_hook";
case EXPR_BINARY: return "binary";
@@ -307,7 +306,6 @@ bool expr_is_runtime_const(Expr *expr)
case EXPR_CT_EVAL:
case EXPR_BENCHMARK_HOOK:
case EXPR_TEST_HOOK:
case EXPR_ANYSWITCH:
case EXPR_BITASSIGN:
case EXPR_TYPECALL:
case EXPR_BINARY:
@@ -816,7 +814,6 @@ bool expr_is_pure(Expr *expr)
case EXPR_MEMBER_GET:
return true;
case EXPR_BITASSIGN:
case EXPR_ANYSWITCH:
return false;
case EXPR_BINARY:
// Anything with assignment is impure, otherwise true if sub expr are pure.

View File

@@ -551,7 +551,6 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
case EXPR_HASH_IDENT:
case EXPR_POISONED:
case EXPR_ADDR_CONVERSION:
case EXPR_ANYSWITCH:
case EXPR_ASM:
case EXPR_BENCHMARK_HOOK:
case EXPR_BINARY:
@@ -708,7 +707,6 @@ static bool expr_may_ref(Expr *expr)
case EXPR_EXPRESSION_LIST:
if (!vec_size(expr->expression_list)) return false;
return expr_may_ref(VECLAST(expr->expression_list));
case EXPR_ANYSWITCH:
case EXPR_ASM:
case EXPR_BENCHMARK_HOOK:
case EXPR_BINARY:
@@ -9158,7 +9156,6 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
case EXPR_TRY_UNRESOLVED:
case EXPR_TRY:
case EXPR_TRY_UNWRAP_CHAIN:
case EXPR_ANYSWITCH:
case EXPR_OPERATOR_CHARS:
case EXPR_MACRO_BODY_EXPANSION:
case EXPR_BUILTIN_ACCESS:
@@ -9530,7 +9527,6 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
{
switch (expr->expr_kind)
{
case EXPR_ANYSWITCH:
case EXPR_ASM:
case EXPR_BENCHMARK_HOOK:
case EXPR_CATCH_UNRESOLVED:
@@ -10051,7 +10047,6 @@ IDENT_CHECK:;
case EXPR_INT_TO_BOOL:
case EXPR_DISCARD:
case EXPR_ADDR_CONVERSION:
case EXPR_ANYSWITCH:
case EXPR_ASM:
case EXPR_BENCHMARK_HOOK:
case EXPR_BINARY:

View File

@@ -46,7 +46,7 @@ static inline bool sema_check_type_case(SemaContext *context, Ast *case_stmt, As
static inline bool sema_check_value_case(SemaContext *context, Type *switch_type, Ast *case_stmt, Ast **cases,
unsigned index, bool *if_chained, bool *max_ranged, uint64_t *actual_cases_ref,
Int *low, Int *high);
static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, SourceSpan expr_span, Type *switch_type, Ast **cases, ExprAnySwitch *any_switch, Decl *var_holder);
static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, SourceSpan expr_span, Type *switch_type, Ast **cases);
static inline bool sema_analyse_statement_inner(SemaContext *context, Ast *statement);
static bool sema_analyse_require(SemaContext *context, Ast *directive, AstId **asserts, SourceSpan source);
@@ -773,7 +773,6 @@ static inline bool sema_expr_valid_try_expression(Expr *expr)
case EXPR_TRY_UNWRAP_CHAIN:
case EXPR_TYPEID_INFO:
case EXPR_TYPEINFO:
case EXPR_ANYSWITCH:
case EXPR_ACCESS_RESOLVED:
case EXPR_ASM:
case EXPR_DEFAULT_ARG:
@@ -1017,63 +1016,6 @@ static inline bool sema_analyse_last_cond(SemaContext *context, Expr *expr, Cond
default:
break;
}
if (cond_type != COND_TYPE_EVALTYPE_VALUE) goto NORMAL_EXPR;
// Now we're analysing the last expression in a switch.
// Case 1: switch (var = variant_expr)
if (expr->expr_kind == EXPR_BINARY && expr->binary_expr.operator == BINARYOP_ASSIGN)
{
// No variable on the lhs? Then it can't be an any unwrap.
Expr *left = exprptr(expr->binary_expr.left);
if (left->resolve_status == RESOLVE_DONE || left->expr_kind != EXPR_UNRESOLVED_IDENTIFIER || left->unresolved_ident_expr.path) goto NORMAL_EXPR;
// Does the identifier exist in the parent scope?
// then again it can't be an any unwrap.
BoolErr defined_in_scope = sema_symbol_is_defined_in_scope(context, left->unresolved_ident_expr.ident);
if (defined_in_scope == BOOL_ERR) return false;
if (defined_in_scope == BOOL_TRUE) goto NORMAL_EXPR;
Expr *right = exprptr(expr->binary_expr.right);
bool is_deref = right->expr_kind == EXPR_UNARY && right->unary_expr.operator == UNARYOP_DEREF;
if (is_deref) right = right->unary_expr.expr;
if (!sema_analyse_expr_rhs(context, NULL, right, false, NULL, false)) return false;
Type *type = right->type->canonical;
if (type == type_get_ptr(type_any) && is_deref)
{
is_deref = false;
right = exprptr(expr->binary_expr.right);
if (!sema_analyse_expr_rhs(context, NULL, right, false, NULL, false)) return false;
}
if (type != type_any) goto NORMAL_EXPR;
// Found an expansion here
expr->expr_kind = EXPR_ANYSWITCH;
expr->any_switch.new_ident = left->unresolved_ident_expr.ident;
expr->any_switch.span = left->span;
expr->any_switch.any_expr = right;
expr->any_switch.is_deref = is_deref;
expr->any_switch.is_assign = true;
expr->resolve_status = RESOLVE_DONE;
expr->type = type_typeid;
return true;
}
if (!sema_analyse_expr(context, expr)) return false;
Type *type = expr->type->canonical;
if (type != type_any) return true;
if (expr->expr_kind == EXPR_IDENTIFIER)
{
Decl *decl = expr->ident_expr;
expr->expr_kind = EXPR_ANYSWITCH;
expr->any_switch.is_deref = false;
expr->any_switch.is_assign = false;
expr->any_switch.variable = decl;
expr->type = type_typeid;
expr->resolve_status = RESOLVE_DONE;
return true;
}
return true;
NORMAL_EXPR:;
return sema_analyse_expr(context, expr);
}
/**
@@ -2400,7 +2342,7 @@ DONE:;
scratch_buffer_append(" - either add them or use 'default'.");
return scratch_buffer_to_string();
}
static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, SourceSpan expr_span, Type *switch_type, Ast **cases, ExprAnySwitch *any_switch, Decl *var_holder)
static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, SourceSpan expr_span, Type *switch_type, Ast **cases)
{
if (!type_is_comparable(switch_type))
{
@@ -2476,42 +2418,6 @@ static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, Sourc
Ast *next = (i < case_count - 1) ? cases[i + 1] : NULL;
PUSH_NEXT(next, statement);
Ast *body = stmt->case_stmt.body;
if (stmt->ast_kind == AST_CASE_STMT && body && type_switch && var_holder && sema_cast_const(exprptr(stmt->case_stmt.expr)))
{
if (any_switch->is_assign)
{
Type *real_type = type_get_ptr(exprptr(stmt->case_stmt.expr)->const_expr.typeid);
Decl *new_var = decl_new_var(any_switch->new_ident, any_switch->span,
type_info_new_base(any_switch->is_deref
? real_type->pointer : real_type, any_switch->span),
VARDECL_LOCAL);
Expr *var_result = expr_variable(var_holder);
if (!cast_explicit(context, var_result, real_type)) return false;
if (any_switch->is_deref)
{
expr_rewrite_insert_deref(var_result);
}
new_var->var.init_expr = var_result;
Ast *decl_ast = new_ast(AST_DECLARE_STMT, new_var->span);
decl_ast->declare_stmt = new_var;
ast_prepend(&body->compound_stmt.first_stmt, decl_ast);
}
else
{
Expr *expr = exprptr(stmt->case_stmt.expr);
Type *type = type_get_ptr(expr->const_expr.typeid);
Decl *alias = decl_new_var(var_holder->name, var_holder->span,
type_info_new_base(type, expr->span),
VARDECL_LOCAL);
Expr *ident_converted = expr_variable(var_holder);
if (!cast_explicit(context, ident_converted, type)) return false;
alias->var.init_expr = ident_converted;
alias->var.shadow = true;
Ast *decl_ast = new_ast(AST_DECLARE_STMT, alias->span);
decl_ast->declare_stmt = alias;
ast_prepend(&body->compound_stmt.first_stmt, decl_ast);
}
}
success = success && (!body || sema_analyse_compound_statement_no_scope(context, body));
POP_BREAK();
POP_NEXT();
@@ -2859,38 +2765,12 @@ static inline bool sema_analyse_switch_stmt(SemaContext *context, Ast *statement
Expr *cond = exprptrzero(statement->switch_stmt.cond);
Type *switch_type;
ExprAnySwitch var_switch;
Decl *any_decl = NULL;
if (statement->ast_kind == AST_SWITCH_STMT)
{
CondResult res = COND_MISSING;
if (cond && !sema_analyse_cond(context, cond, COND_TYPE_EVALTYPE_VALUE, &res)) return false;
Expr *last = cond ? VECLAST(cond->cond_expr) : NULL;
switch_type = last ? last->type->canonical : type_bool;
if (last && last->expr_kind == EXPR_ANYSWITCH)
{
var_switch = last->any_switch;
Expr *inner;
if (var_switch.is_assign)
{
inner = expr_new(EXPR_DECL, last->span);
any_decl = decl_new_generated_var(type_any, VARDECL_LOCAL, last->span);
any_decl->var.init_expr = var_switch.any_expr;
inner->decl_expr = any_decl;
if (!sema_analyse_expr(context, inner)) return false;
}
else
{
inner = expr_new(EXPR_IDENTIFIER, last->span);
any_decl = var_switch.variable;
expr_resolve_ident(inner, any_decl);
inner->type = type_any;
}
expr_rewrite_to_builtin_access(last, inner, ACCESS_TYPEOFANY, type_typeid);
switch_type = type_typeid;
cond->type = type_typeid;
}
}
else
{
@@ -2900,7 +2780,7 @@ static inline bool sema_analyse_switch_stmt(SemaContext *context, Ast *statement
statement->switch_stmt.defer = context->active_scope.defer_last;
if (!sema_analyse_switch_body(context, statement, cond ? cond->span : statement->span,
switch_type->canonical,
statement->switch_stmt.cases, any_decl ? &var_switch : NULL, any_decl))
statement->switch_stmt.cases))
{
return SCOPE_POP_ERROR();
}

View File

@@ -5,38 +5,12 @@ extern fn void printf(char*, ...);
fn void test(any z)
{
switch (z)
switch (z.type)
{
case int:
printf("int: %d\n", *z);
printf("int: %d\n", *(int*)z);
case double:
printf("double %f\n", *z);
default:
printf("Unknown type.\n");
}
}
fn void test2(any y)
{
switch (z = y)
{
case int:
y = &&12;
printf("int: %d\n", *z);
case double:
printf("double %f\n", *z);
default:
printf("Unknown type.\n");
}
}
fn void test3(any y)
{
switch (z = *y)
{
case int:
printf("int: %d\n", z);
case double:
printf("double %f\n", z);
printf("double %f\n", *(double*)z);
default:
printf("Unknown type.\n");
}
@@ -47,12 +21,6 @@ fn int main()
test(&&123.0);
test(&&1);
test(&&true);
test2(&&123.5);
test2(&&1);
test2(&&true);
test3(&&124.0);
test3(&&2);
test3(&&true);
return 0;
}
@@ -66,8 +34,6 @@ define void @foo.test(i64 %0, ptr %1) #0 {
entry:
%z = alloca %any, align 8
%switch = alloca i64, align 8
%z3 = alloca ptr, align 8
%z11 = alloca ptr, align 8
store i64 %0, ptr %z, align 8
%ptradd = getelementptr inbounds i8, ptr %z, i64 8
store ptr %1, ptr %ptradd, align 8
@@ -98,218 +64,46 @@ result_block: ; preds = %parent_type_block,
switch.case: ; preds = %result_block
%8 = load ptr, ptr %z, align 8
store ptr %8, ptr %z3, align 8
%9 = load ptr, ptr %z3, align 8
%10 = load i32, ptr %9, align 4
call void (ptr, ...) @printf(ptr @.str, i32 %10)
%9 = load i32, ptr %8, align 4
call void (ptr, ...) @printf(ptr @.str, i32 %9)
br label %switch.exit
next_if: ; preds = %result_block
br label %check_subtype4
br label %check_subtype3
check_subtype4: ; preds = %parent_type_block6, %next_if
%11 = phi i64 [ %3, %next_if ], [ %typeid.parent8, %parent_type_block6 ]
%eq5 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %11
br i1 %eq5, label %result_block9, label %parent_type_block6
check_subtype3: ; preds = %parent_type_block5, %next_if
%10 = phi i64 [ %3, %next_if ], [ %typeid.parent7, %parent_type_block5 ]
%eq4 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %10
br i1 %eq4, label %result_block8, label %parent_type_block5
parent_type_block6: ; preds = %check_subtype4
%12 = inttoptr i64 %11 to ptr
%ptradd7 = getelementptr inbounds i8, ptr %12, i64 8
%typeid.parent8 = load i64, ptr %ptradd7, align 8
%13 = icmp eq i64 %typeid.parent8, 0
br i1 %13, label %result_block9, label %check_subtype4
parent_type_block5: ; preds = %check_subtype3
%11 = inttoptr i64 %10 to ptr
%ptradd6 = getelementptr inbounds i8, ptr %11, i64 8
%typeid.parent7 = load i64, ptr %ptradd6, align 8
%12 = icmp eq i64 %typeid.parent7, 0
br i1 %12, label %result_block8, label %check_subtype3
result_block9: ; preds = %parent_type_block6, %check_subtype4
%14 = phi i1 [ false, %parent_type_block6 ], [ true, %check_subtype4 ]
br i1 %14, label %switch.case10, label %next_if12
result_block8: ; preds = %parent_type_block5, %check_subtype3
%13 = phi i1 [ false, %parent_type_block5 ], [ true, %check_subtype3 ]
br i1 %13, label %switch.case9, label %next_if10
switch.case10: ; preds = %result_block9
%15 = load ptr, ptr %z, align 8
store ptr %15, ptr %z11, align 8
%16 = load ptr, ptr %z11, align 8
%17 = load double, ptr %16, align 8
call void (ptr, ...) @printf(ptr @.str.1, double %17)
switch.case9: ; preds = %result_block8
%14 = load ptr, ptr %z, align 8
%15 = load double, ptr %14, align 8
call void (ptr, ...) @printf(ptr @.str.1, double %15)
br label %switch.exit
next_if12: ; preds = %result_block9
next_if10: ; preds = %result_block8
br label %switch.default
switch.default: ; preds = %next_if12
switch.default: ; preds = %next_if10
call void (ptr, ...) @printf(ptr @.str.2)
br label %switch.exit
switch.exit: ; preds = %switch.default, %switch.case10, %switch.case
switch.exit: ; preds = %switch.default, %switch.case9, %switch.case
ret void
}
; Function Attrs:
define void @foo.test2(i64 %0, ptr %1) #0 {
entry:
%y = alloca %any, align 8
%switch = alloca i64, align 8
%z = alloca ptr, align 8
%taddr = alloca i32, align 4
%z9 = alloca ptr, align 8
store i64 %0, ptr %y, align 8
%ptradd = getelementptr inbounds i8, ptr %y, i64 8
store ptr %1, ptr %ptradd, align 8
%2 = load %any, ptr %y, align 8
%3 = extractvalue %any %2, 1
store i64 %3, ptr %switch, align 8
br label %switch.entry
switch.entry: ; preds = %entry
%4 = load i64, ptr %switch, align 8
br label %check_subtype
check_subtype: ; preds = %parent_type_block, %switch.entry
%5 = phi i64 [ %4, %switch.entry ], [ %typeid.parent, %parent_type_block ]
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5
br i1 %eq, label %result_block, label %parent_type_block
parent_type_block: ; preds = %check_subtype
%6 = inttoptr i64 %5 to ptr
%ptradd1 = getelementptr inbounds i8, ptr %6, i64 8
%typeid.parent = load i64, ptr %ptradd1, align 8
%7 = icmp eq i64 %typeid.parent, 0
br i1 %7, label %result_block, label %check_subtype
result_block: ; preds = %parent_type_block, %check_subtype
%8 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
br i1 %8, label %switch.case, label %next_if
switch.case: ; preds = %result_block
%9 = extractvalue %any %2, 0
store ptr %9, ptr %z, align 8
store i32 12, ptr %taddr, align 4
%10 = insertvalue %any undef, ptr %taddr, 0
%11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.int" to i64), 1
store %any %11, ptr %y, align 8
%12 = load ptr, ptr %z, align 8
%13 = load i32, ptr %12, align 4
call void (ptr, ...) @printf(ptr @.str.3, i32 %13)
br label %switch.exit
next_if: ; preds = %result_block
br label %check_subtype2
check_subtype2: ; preds = %parent_type_block4, %next_if
%14 = phi i64 [ %4, %next_if ], [ %typeid.parent6, %parent_type_block4 ]
%eq3 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %14
br i1 %eq3, label %result_block7, label %parent_type_block4
parent_type_block4: ; preds = %check_subtype2
%15 = inttoptr i64 %14 to ptr
%ptradd5 = getelementptr inbounds i8, ptr %15, i64 8
%typeid.parent6 = load i64, ptr %ptradd5, align 8
%16 = icmp eq i64 %typeid.parent6, 0
br i1 %16, label %result_block7, label %check_subtype2
result_block7: ; preds = %parent_type_block4, %check_subtype2
%17 = phi i1 [ false, %parent_type_block4 ], [ true, %check_subtype2 ]
br i1 %17, label %switch.case8, label %next_if10
switch.case8: ; preds = %result_block7
%18 = extractvalue %any %2, 0
store ptr %18, ptr %z9, align 8
%19 = load ptr, ptr %z9, align 8
%20 = load double, ptr %19, align 8
call void (ptr, ...) @printf(ptr @.str.4, double %20)
br label %switch.exit
next_if10: ; preds = %result_block7
br label %switch.default
switch.default: ; preds = %next_if10
call void (ptr, ...) @printf(ptr @.str.5)
br label %switch.exit
switch.exit: ; preds = %switch.default, %switch.case8, %switch.case
ret void
}
; Function Attrs:
define void @foo.test3(i64 %0, ptr %1) #0 {
entry:
%y = alloca %any, align 8
%switch = alloca i64, align 8
%z = alloca i32, align 4
%z9 = alloca double, align 8
store i64 %0, ptr %y, align 8
%ptradd = getelementptr inbounds i8, ptr %y, i64 8
store ptr %1, ptr %ptradd, align 8
%2 = load %any, ptr %y, align 8
%3 = extractvalue %any %2, 1
store i64 %3, ptr %switch, align 8
br label %switch.entry
switch.entry: ; preds = %entry
%4 = load i64, ptr %switch, align 8
br label %check_subtype
check_subtype: ; preds = %parent_type_block, %switch.entry
%5 = phi i64 [ %4, %switch.entry ], [ %typeid.parent, %parent_type_block ]
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5
br i1 %eq, label %result_block, label %parent_type_block
parent_type_block: ; preds = %check_subtype
%6 = inttoptr i64 %5 to ptr
%ptradd1 = getelementptr inbounds i8, ptr %6, i64 8
%typeid.parent = load i64, ptr %ptradd1, align 8
%7 = icmp eq i64 %typeid.parent, 0
br i1 %7, label %result_block, label %check_subtype
result_block: ; preds = %parent_type_block, %check_subtype
%8 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
br i1 %8, label %switch.case, label %next_if
switch.case: ; preds = %result_block
%9 = extractvalue %any %2, 0
%10 = load i32, ptr %9, align 4
store i32 %10, ptr %z, align 4
%11 = load i32, ptr %z, align 4
call void (ptr, ...) @printf(ptr @.str.6, i32 %11)
br label %switch.exit
next_if: ; preds = %result_block
br label %check_subtype2
check_subtype2: ; preds = %parent_type_block4, %next_if
%12 = phi i64 [ %4, %next_if ], [ %typeid.parent6, %parent_type_block4 ]
%eq3 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %12
br i1 %eq3, label %result_block7, label %parent_type_block4
parent_type_block4: ; preds = %check_subtype2
%13 = inttoptr i64 %12 to ptr
%ptradd5 = getelementptr inbounds i8, ptr %13, i64 8
%typeid.parent6 = load i64, ptr %ptradd5, align 8
%14 = icmp eq i64 %typeid.parent6, 0
br i1 %14, label %result_block7, label %check_subtype2
result_block7: ; preds = %parent_type_block4, %check_subtype2
%15 = phi i1 [ false, %parent_type_block4 ], [ true, %check_subtype2 ]
br i1 %15, label %switch.case8, label %next_if10
switch.case8: ; preds = %result_block7
%16 = extractvalue %any %2, 0
%17 = load double, ptr %16, align 8
store double %17, ptr %z9, align 8
%18 = load double, ptr %z9, align 8
call void (ptr, ...) @printf(ptr @.str.7, double %18)
br label %switch.exit
next_if10: ; preds = %result_block7
br label %switch.default
switch.default: ; preds = %next_if10
call void (ptr, ...) @printf(ptr @.str.8)
br label %switch.exit
switch.exit: ; preds = %switch.default, %switch.case8, %switch.case
ret void
}
; Function Attrs:
define i32 @main() #0 {
entry:
%taddr = alloca double, align 8
@@ -318,18 +112,6 @@ entry:
%taddr3 = alloca %any, align 8
%taddr7 = alloca i8, align 1
%taddr8 = alloca %any, align 8
%taddr12 = alloca double, align 8
%taddr13 = alloca %any, align 8
%taddr17 = alloca i32, align 4
%taddr18 = alloca %any, align 8
%taddr22 = alloca i8, align 1
%taddr23 = alloca %any, align 8
%taddr27 = alloca double, align 8
%taddr28 = alloca %any, align 8
%taddr32 = alloca i32, align 4
%taddr33 = alloca %any, align 8
%taddr37 = alloca i8, align 1
%taddr38 = alloca %any, align 8
store double 1.230000e+02, ptr %taddr, align 8
%0 = insertvalue %any undef, ptr %taddr, 0
%1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.double" to i64), 1
@@ -354,53 +136,5 @@ entry:
%ptradd10 = getelementptr inbounds i8, ptr %taddr8, i64 8
%hi11 = load ptr, ptr %ptradd10, align 8
call void @foo.test(i64 %lo9, ptr %hi11)
store double 1.235000e+02, ptr %taddr12, align 8
%6 = insertvalue %any undef, ptr %taddr12, 0
%7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.double" to i64), 1
store %any %7, ptr %taddr13, align 8
%lo14 = load i64, ptr %taddr13, align 8
%ptradd15 = getelementptr inbounds i8, ptr %taddr13, i64 8
%hi16 = load ptr, ptr %ptradd15, align 8
call void @foo.test2(i64 %lo14, ptr %hi16)
store i32 1, ptr %taddr17, align 4
%8 = insertvalue %any undef, ptr %taddr17, 0
%9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.int" to i64), 1
store %any %9, ptr %taddr18, align 8
%lo19 = load i64, ptr %taddr18, align 8
%ptradd20 = getelementptr inbounds i8, ptr %taddr18, i64 8
%hi21 = load ptr, ptr %ptradd20, align 8
call void @foo.test2(i64 %lo19, ptr %hi21)
store i8 1, ptr %taddr22, align 1
%10 = insertvalue %any undef, ptr %taddr22, 0
%11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.bool" to i64), 1
store %any %11, ptr %taddr23, align 8
%lo24 = load i64, ptr %taddr23, align 8
%ptradd25 = getelementptr inbounds i8, ptr %taddr23, i64 8
%hi26 = load ptr, ptr %ptradd25, align 8
call void @foo.test2(i64 %lo24, ptr %hi26)
store double 1.240000e+02, ptr %taddr27, align 8
%12 = insertvalue %any undef, ptr %taddr27, 0
%13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.double" to i64), 1
store %any %13, ptr %taddr28, align 8
%lo29 = load i64, ptr %taddr28, align 8
%ptradd30 = getelementptr inbounds i8, ptr %taddr28, i64 8
%hi31 = load ptr, ptr %ptradd30, align 8
call void @foo.test3(i64 %lo29, ptr %hi31)
store i32 2, ptr %taddr32, align 4
%14 = insertvalue %any undef, ptr %taddr32, 0
%15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.int" to i64), 1
store %any %15, ptr %taddr33, align 8
%lo34 = load i64, ptr %taddr33, align 8
%ptradd35 = getelementptr inbounds i8, ptr %taddr33, i64 8
%hi36 = load ptr, ptr %ptradd35, align 8
call void @foo.test3(i64 %lo34, ptr %hi36)
store i8 1, ptr %taddr37, align 1
%16 = insertvalue %any undef, ptr %taddr37, 0
%17 = insertvalue %any %16, i64 ptrtoint (ptr @"$ct.bool" to i64), 1
store %any %17, ptr %taddr38, align 8
%lo39 = load i64, ptr %taddr38, align 8
%ptradd40 = getelementptr inbounds i8, ptr %taddr38, i64 8
%hi41 = load ptr, ptr %ptradd40, align 8
call void @foo.test3(i64 %lo39, ptr %hi41)
ret i32 0
}
}

View File

@@ -5,13 +5,13 @@ extern fn void printf(char*, ...);
fn void test(any z)
{
switch (z)
switch (z.type)
{
case int:
printf("int: %d\n", *z);
*z = 3;
printf("int: %d\n", *(int*)z);
*(int*)z = 3;
case double:
printf("double %f\n", *z);
printf("double %f\n", *(double*)z);
default:
printf("Unknown type.\n");
}
@@ -38,8 +38,6 @@ define void @foo.test(i64 %0, ptr %1) #0 {
entry:
%z = alloca %any, align 8
%switch = alloca i64, align 8
%z3 = alloca ptr, align 8
%z11 = alloca ptr, align 8
store i64 %0, ptr %z, align 8
%ptradd = getelementptr inbounds i8, ptr %z, i64 8
store ptr %1, ptr %ptradd, align 8
@@ -70,58 +68,54 @@ result_block: ; preds = %parent_type_block,
switch.case: ; preds = %result_block
%8 = load ptr, ptr %z, align 8
store ptr %8, ptr %z3, align 8
%9 = load ptr, ptr %z3, align 8
%10 = load i32, ptr %9, align 4
call void (ptr, ...) @printf(ptr @.str, i32 %10)
%11 = load ptr, ptr %z3, align 8
store i32 3, ptr %11, align 4
%9 = load i32, ptr %8, align 4
call void (ptr, ...) @printf(ptr @.str, i32 %9)
%10 = load ptr, ptr %z, align 8
store i32 3, ptr %10, align 4
br label %switch.exit
next_if: ; preds = %result_block
br label %check_subtype4
br label %check_subtype3
check_subtype4: ; preds = %parent_type_block6, %next_if
%12 = phi i64 [ %3, %next_if ], [ %typeid.parent8, %parent_type_block6 ]
%eq5 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %12
br i1 %eq5, label %result_block9, label %parent_type_block6
check_subtype3: ; preds = %parent_type_block5, %next_if
%11 = phi i64 [ %3, %next_if ], [ %typeid.parent7, %parent_type_block5 ]
%eq4 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %11
br i1 %eq4, label %result_block8, label %parent_type_block5
parent_type_block6: ; preds = %check_subtype4
%13 = inttoptr i64 %12 to ptr
%ptradd7 = getelementptr inbounds i8, ptr %13, i64 8
%typeid.parent8 = load i64, ptr %ptradd7, align 8
%14 = icmp eq i64 %typeid.parent8, 0
br i1 %14, label %result_block9, label %check_subtype4
parent_type_block5: ; preds = %check_subtype3
%12 = inttoptr i64 %11 to ptr
%ptradd6 = getelementptr inbounds i8, ptr %12, i64 8
%typeid.parent7 = load i64, ptr %ptradd6, align 8
%13 = icmp eq i64 %typeid.parent7, 0
br i1 %13, label %result_block8, label %check_subtype3
result_block9: ; preds = %parent_type_block6, %check_subtype4
%15 = phi i1 [ false, %parent_type_block6 ], [ true, %check_subtype4 ]
br i1 %15, label %switch.case10, label %next_if12
result_block8: ; preds = %parent_type_block5, %check_subtype3
%14 = phi i1 [ false, %parent_type_block5 ], [ true, %check_subtype3 ]
br i1 %14, label %switch.case9, label %next_if10
switch.case10: ; preds = %result_block9
%16 = load ptr, ptr %z, align 8
store ptr %16, ptr %z11, align 8
%17 = load ptr, ptr %z11, align 8
%18 = load double, ptr %17, align 8
call void (ptr, ...) @printf(ptr @.str.1, double %18)
switch.case9: ; preds = %result_block8
%15 = load ptr, ptr %z, align 8
%16 = load double, ptr %15, align 8
call void (ptr, ...) @printf(ptr @.str.1, double %16)
br label %switch.exit
next_if12: ; preds = %result_block9
next_if10: ; preds = %result_block8
br label %switch.default
switch.default: ; preds = %next_if12
switch.default: ; preds = %next_if10
call void (ptr, ...) @printf(ptr @.str.2)
br label %switch.exit
switch.exit: ; preds = %switch.default, %switch.case10, %switch.case
%ptradd13 = getelementptr inbounds i8, ptr %z, i64 8
%19 = load i64, ptr %ptradd13, align 8
%eq14 = icmp eq i64 %19, ptrtoint (ptr @"$ct.int" to i64)
br i1 %eq14, label %if.then, label %if.exit
switch.exit: ; preds = %switch.default, %switch.case9, %switch.case
%ptradd11 = getelementptr inbounds i8, ptr %z, i64 8
%17 = load i64, ptr %ptradd11, align 8
%eq12 = icmp eq i64 %17, ptrtoint (ptr @"$ct.int" to i64)
br i1 %eq12, label %if.then, label %if.exit
if.then: ; preds = %switch.exit
%20 = load ptr, ptr %z, align 8
%21 = load i32, ptr %20, align 4
call void (ptr, ...) @printf(ptr @.str.3, i32 %21)
%18 = load ptr, ptr %z, align 8
%19 = load i32, ptr %18, align 4
call void (ptr, ...) @printf(ptr @.str.3, i32 %19)
br label %if.exit
if.exit: ; preds = %if.then, %switch.exit

View File

@@ -15,7 +15,7 @@ fn void test_aliasing()
{
int x;
AnyAlias z = &x;
switch (z)
switch (z.type)
{
case int:
assert(true);

View File

@@ -18,7 +18,7 @@ fn void switch_subtyping()
Foo f = {};
f.z = 123;
any x = &f;
switch (x)
switch (x.type)
{
case int:
assert(false);
@@ -27,7 +27,7 @@ fn void switch_subtyping()
default:
assert(false);
}
switch (x)
switch (x.type)
{
case int:
assert(false);
@@ -36,7 +36,7 @@ fn void switch_subtyping()
default:
assert(false);
}
switch (x)
switch (x.type)
{
case int:
assert(false);