mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Make typeid switches always use subtype matching. Update seeder mixing.
This commit is contained in:
committed by
Christoffer Lerno
parent
7aca8a02cb
commit
eac19814e1
@@ -33,11 +33,11 @@ else()
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-3 -O3 -fno-exceptions")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gdwarf-3 -fno-exceptions")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-3 -O3 -fsanitize=undefined -fno-exceptions")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -gdwarf-3 -O1 -fsanitize=undefined -fno-exceptions")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-3 -O3 -fsanitize=undefined -fno-exceptions")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gdwarf-3 -O1 -fsanitize=undefined -fno-exceptions")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fno-exceptions")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-3 -O3 -fsanitize=undefined,address -fno-exceptions")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -gdwarf-3 -O1 -fsanitize=undefined,address -fno-exceptions")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-3 -O3 -fsanitize=undefined,address -fno-exceptions")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gdwarf-3 -O1 -fsanitize=undefined,address -fno-exceptions")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined,address -fno-exceptions")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -74,6 +74,24 @@ macro any_to_int(any v, $Type)
|
||||
}
|
||||
}
|
||||
|
||||
fn bool typeid.is_subtype_of(self, typeid other)
|
||||
{
|
||||
while (self != void.typeid)
|
||||
{
|
||||
if (self == other) return true;
|
||||
self = self.parentof;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
macro bool is_subtype_of($Type, $OtherType)
|
||||
{
|
||||
var $typeid = $Type.typeid;
|
||||
$switch ($Type)
|
||||
$case $OtherType: return true;
|
||||
$default: return false;
|
||||
$endswitch
|
||||
}
|
||||
macro bool is_numerical($Type)
|
||||
{
|
||||
var $kind = $Type.kindof;
|
||||
|
||||
@@ -27,6 +27,7 @@ fn void seeder(char[] input, char[] out_buffer)
|
||||
{
|
||||
ulong[] words = tmalloc(ulong, (out_chars + 7) / 8);
|
||||
words[..] = ODD_PHI64;
|
||||
usz words_len_2 = words.len * 2;
|
||||
|
||||
// Add word at a time
|
||||
for (usz i = 0; i < input.len / 8; i++)
|
||||
@@ -47,7 +48,7 @@ fn void seeder(char[] input, char[] out_buffer)
|
||||
}
|
||||
|
||||
// Mix between words
|
||||
for (isz i = words.len * 2 - 1; i >= 0; i--)
|
||||
for (isz i = words_len_2 - 1; i >= 0; i--)
|
||||
{
|
||||
isz j = i % words.len;
|
||||
words[j] -= words[(i + 1) % words.len] * MUL_LCG64;
|
||||
@@ -55,7 +56,7 @@ fn void seeder(char[] input, char[] out_buffer)
|
||||
}
|
||||
|
||||
// Mix within words
|
||||
for (usz i = 0; i < 2; i++)
|
||||
for (usz i = 0; i < words_len_2; i++)
|
||||
{
|
||||
usz j = i % words.len;
|
||||
words[j] *= MUL_MCG64;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
## 0.5.0 Change List
|
||||
|
||||
### Changes / improvements
|
||||
- Subtype matching in type switches.
|
||||
- Added parentof typeid property.
|
||||
- Slice assignment is expanded.
|
||||
- Strong optional handling requirements.
|
||||
|
||||
@@ -3734,13 +3734,33 @@ static void llvm_emit_float_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
|
||||
|
||||
void llvm_emit_lhs_is_subtype(GenContext *c, BEValue *result, BEValue *lhs, BEValue *rhs)
|
||||
{
|
||||
Type *canonical_typeid = type_lowering(type_typeid);
|
||||
llvm_value_rvalue(c, lhs);
|
||||
llvm_value_rvalue(c, rhs);
|
||||
LLVMValueRef switch_val = lhs->value;
|
||||
LLVMBasicBlockRef start_block = c->current_block;
|
||||
LLVMBasicBlockRef retry_block = llvm_basic_block_new(c, "check_subtype");
|
||||
LLVMBasicBlockRef result_block = llvm_basic_block_new(c, "result_block");
|
||||
LLVMBasicBlockRef parent_type_block = llvm_basic_block_new(c, "parent_type_block");
|
||||
llvm_emit_br(c, retry_block);
|
||||
llvm_emit_comp(c, result, lhs, rhs, BINARYOP_EQ);
|
||||
LLVMBasicBlockRef next_block = llvm_basic_block_new(c, "next_block");
|
||||
TODO
|
||||
llvm_emit_block(c, retry_block);
|
||||
LLVMValueRef phi = LLVMBuildPhi(c->builder, c->typeid_type, "");
|
||||
BEValue cond;
|
||||
llvm_emit_int_comp_raw(c, &cond, canonical_typeid, canonical_typeid, switch_val, phi, BINARYOP_EQ);
|
||||
llvm_emit_cond_br(c, &cond, result_block, parent_type_block);
|
||||
llvm_emit_block(c, parent_type_block);
|
||||
LLVMValueRef introspect_ptr = LLVMBuildIntToPtr(c->builder, phi, c->ptr_type, "");
|
||||
AlignSize alignment;
|
||||
LLVMValueRef parent = llvm_emit_struct_gep_raw(c, introspect_ptr, c->introspect_type, INTROSPECT_INDEX_PARENTOF,
|
||||
type_abi_alignment(type_voidptr), &alignment);
|
||||
LLVMValueRef parent_value = llvm_load(c, c->typeid_type, parent, alignment, "typeid.parent");
|
||||
LLVMValueRef is_zero = LLVMBuildICmp(c->builder, LLVMIntEQ, parent_value, LLVMConstNull(c->typeid_type), "");
|
||||
llvm_emit_cond_br_raw(c, is_zero, result_block, retry_block);
|
||||
llvm_set_phi(phi, rhs->value, start_block, parent_value, parent_type_block);
|
||||
llvm_emit_block(c, result_block);
|
||||
LLVMValueRef phi2 = LLVMBuildPhi(c->builder, c->bool_type, "");
|
||||
llvm_set_phi(phi2, LLVMConstNull(c->bool_type), parent_type_block, LLVMConstAllOnes(c->bool_type), retry_block);
|
||||
llvm_value_set(result, phi2, type_bool);
|
||||
}
|
||||
|
||||
void llvm_emit_comp(GenContext *c, BEValue *result, BEValue *lhs, BEValue *rhs, BinaryOp binary_op)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "llvm_codegen_internal.h"
|
||||
|
||||
static void llvm_emit_switch_body(GenContext *c, BEValue *switch_value, Ast *switch_ast);
|
||||
static void llvm_emit_switch_body(GenContext *c, BEValue *switch_value, Ast *switch_ast, bool is_typeid);
|
||||
|
||||
// Emit a regular compound statement.
|
||||
void llvm_emit_compound_stmt(GenContext *c, Ast *ast)
|
||||
@@ -332,7 +332,7 @@ static void llvm_emit_if_stmt(GenContext *c, Ast *ast)
|
||||
llvm_emit_cond_br(c, &comp, then_block, else_block);
|
||||
llvm_emit_br(c, then_block);
|
||||
llvm_emit_block(c, then_block);
|
||||
llvm_emit_switch_body(c, &be_value, then_body);
|
||||
llvm_emit_switch_body(c, &be_value, then_body, false);
|
||||
llvm_emit_br(c, exit_block);
|
||||
goto EMIT_ELSE;
|
||||
}
|
||||
@@ -615,7 +615,8 @@ static void llvm_emit_switch_body_if_chain(GenContext *c,
|
||||
Ast **cases,
|
||||
Ast *default_case,
|
||||
BEValue *switch_value,
|
||||
LLVMBasicBlockRef exit_block)
|
||||
LLVMBasicBlockRef exit_block,
|
||||
bool is_type_switch)
|
||||
{
|
||||
LLVMBasicBlockRef next = NULL;
|
||||
VECEACH(cases, i)
|
||||
@@ -631,6 +632,7 @@ static void llvm_emit_switch_body_if_chain(GenContext *c,
|
||||
Expr *to_expr = exprptrzero(case_stmt->case_stmt.to_expr);
|
||||
if (to_expr)
|
||||
{
|
||||
assert(!is_type_switch);
|
||||
BEValue to_value;
|
||||
llvm_emit_expr(c, &to_value, to_expr);
|
||||
llvm_value_rvalue(c, &to_value);
|
||||
@@ -642,11 +644,11 @@ static void llvm_emit_switch_body_if_chain(GenContext *c,
|
||||
}
|
||||
else
|
||||
{
|
||||
/*if (expr->type == type_typeid)
|
||||
if (is_type_switch)
|
||||
{
|
||||
llvm_emit_lhs_is_subtype(c, &equals, &be_value, switch_value);
|
||||
}
|
||||
else*/
|
||||
else
|
||||
{
|
||||
llvm_emit_comp(c, &equals, &be_value, switch_value, BINARYOP_EQ);
|
||||
}
|
||||
@@ -752,11 +754,10 @@ static void llvm_emit_switch_jump_table(GenContext *c,
|
||||
#endif
|
||||
}
|
||||
|
||||
static void llvm_emit_switch_body(GenContext *c, BEValue *switch_value, Ast *switch_ast)
|
||||
static void llvm_emit_switch_body(GenContext *c, BEValue *switch_value, Ast *switch_ast, bool is_typeid)
|
||||
{
|
||||
bool is_if_chain = switch_ast->switch_stmt.flow.if_chain;
|
||||
Type *switch_type = switch_ast->ast_kind == AST_IF_CATCH_SWITCH_STMT ? type_lowering(type_anyfault) : switch_value->type;
|
||||
|
||||
Ast **cases = switch_ast->switch_stmt.cases;
|
||||
ArraySize case_count = vec_size(cases);
|
||||
if (!case_count)
|
||||
@@ -821,9 +822,10 @@ static void llvm_emit_switch_body(GenContext *c, BEValue *switch_value, Ast *swi
|
||||
|
||||
if (is_if_chain)
|
||||
{
|
||||
llvm_emit_switch_body_if_chain(c, cases, default_case, &switch_current_val, exit_block);
|
||||
llvm_emit_switch_body_if_chain(c, cases, default_case, &switch_current_val, exit_block, is_typeid);
|
||||
return;
|
||||
}
|
||||
assert(!is_typeid);
|
||||
|
||||
c->current_block = NULL;
|
||||
LLVMValueRef switch_stmt = LLVMBuildSwitch(c->builder, switch_current_val.value, default_case ? default_case->case_stmt.backend_block : exit_block, case_count);
|
||||
@@ -875,6 +877,7 @@ void llvm_emit_switch(GenContext *c, Ast *ast)
|
||||
{
|
||||
BEValue switch_value;
|
||||
Expr *expr = exprptrzero(ast->switch_stmt.cond);
|
||||
bool is_typeid = expr && expr->type->canonical == type_typeid;
|
||||
if (expr)
|
||||
{
|
||||
// Regular switch
|
||||
@@ -885,7 +888,7 @@ void llvm_emit_switch(GenContext *c, Ast *ast)
|
||||
// Match switch, so set the value to true
|
||||
llvm_value_set(&switch_value, llvm_const_int(c, type_bool, 1), type_bool);
|
||||
}
|
||||
llvm_emit_switch_body(c, &switch_value, ast);
|
||||
llvm_emit_switch_body(c, &switch_value, ast, is_typeid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2438,7 +2438,17 @@ static inline bool sema_analyse_ct_switch_stmt(SemaContext *context, Ast *statem
|
||||
goto FAILED;
|
||||
}
|
||||
}
|
||||
if (expr_const_in_range(switch_expr_const, const_expr, const_to_expr))
|
||||
if (is_type)
|
||||
{
|
||||
assert(const_expr == const_to_expr);
|
||||
Type *switch_type = switch_expr_const->typeid;
|
||||
Type *case_type = const_expr->typeid;
|
||||
if (matched_case > i && type_is_subtype(case_type->canonical, switch_type->canonical))
|
||||
{
|
||||
matched_case = (int)i;
|
||||
}
|
||||
}
|
||||
else if (expr_const_in_range(switch_expr_const, const_expr, const_to_expr))
|
||||
{
|
||||
matched_case = (int)i;
|
||||
}
|
||||
|
||||
@@ -1617,27 +1617,19 @@ Type *type_find_parent_type(Type *type)
|
||||
* Check if a type is contained in another type.
|
||||
*
|
||||
* @param type canonical type
|
||||
* @param possible_subtype canonical type
|
||||
* @param possible_subtype is this a subtype of the former, i.e. type is the parent.
|
||||
* @return true if it is a subtype
|
||||
*/
|
||||
bool type_is_subtype(Type *type, Type *possible_subtype)
|
||||
{
|
||||
assert(type == type->canonical && possible_subtype == possible_subtype->canonical);
|
||||
while (1)
|
||||
assert(type == type->canonical);
|
||||
while (possible_subtype)
|
||||
{
|
||||
possible_subtype = possible_subtype->canonical;
|
||||
if (type == possible_subtype) return true;
|
||||
if (type->type_kind != possible_subtype->type_kind) return false;
|
||||
if (type->type_kind != TYPE_STRUCT) return false;
|
||||
|
||||
if (!possible_subtype->decl->strukt.members) return false;
|
||||
|
||||
Decl *first_element = possible_subtype->decl->strukt.members[0];
|
||||
|
||||
if (first_element->decl_kind != DECL_VAR) return false;
|
||||
|
||||
possible_subtype = first_element->type->canonical;
|
||||
possible_subtype = type_find_parent_type(possible_subtype);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *type_from_token(TokenType type)
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.622"
|
||||
#define COMPILER_VERSION "0.4.623"
|
||||
@@ -79,8 +79,8 @@ entry:
|
||||
%a = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
%zy = alloca i32, align 4
|
||||
%switch17 = alloca i32, align 4
|
||||
%switch27 = alloca i8, align 1
|
||||
%switch25 = alloca i32, align 4
|
||||
%switch35 = alloca i8, align 1
|
||||
store i64 ptrtoint (ptr @"mymodule.ByeErr$BAR" to i64), ptr %x.f, align 8
|
||||
store i64 ptrtoint (ptr @"$ct.int" to i64), ptr %z, align 8
|
||||
br label %testblock
|
||||
@@ -142,104 +142,157 @@ if.exit: ; preds = %switch.exit, %end_b
|
||||
|
||||
switch.entry5: ; preds = %if.exit
|
||||
%4 = load i64, ptr %switch4, align 8
|
||||
%eq6 = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4
|
||||
br i1 %eq6, label %switch.case7, label %next_if8
|
||||
br label %check_subtype
|
||||
|
||||
switch.case7: ; preds = %switch.entry5
|
||||
check_subtype: ; preds = %parent_type_block, %switch.entry5
|
||||
%5 = phi i64 [ %4, %switch.entry5 ], [ %typeid.parent, %parent_type_block ]
|
||||
%eq6 = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5
|
||||
br i1 %eq6, label %result_block, label %parent_type_block
|
||||
|
||||
parent_type_block: ; preds = %check_subtype
|
||||
%6 = inttoptr i64 %5 to ptr
|
||||
%7 = getelementptr inbounds %.introspect, ptr %6, i32 0, i32 1
|
||||
%typeid.parent = load i64, ptr %7, align 8
|
||||
%8 = icmp eq i64 %typeid.parent, 0
|
||||
br i1 %8, label %result_block, label %check_subtype
|
||||
|
||||
result_block: ; preds = %parent_type_block, %check_subtype
|
||||
%9 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
|
||||
br i1 %9, label %switch.case7, label %next_if8
|
||||
|
||||
switch.case7: ; preds = %result_block
|
||||
call void (ptr, ...) @printf(ptr @.str.5)
|
||||
br label %switch.exit16
|
||||
br label %switch.exit24
|
||||
|
||||
next_if8: ; preds = %switch.entry5
|
||||
%eq9 = icmp eq i64 ptrtoint (ptr @"$ct.bool" to i64), %4
|
||||
br i1 %eq9, label %switch.case10, label %next_if11
|
||||
next_if8: ; preds = %result_block
|
||||
br label %check_subtype9
|
||||
|
||||
switch.case10: ; preds = %next_if8
|
||||
br label %switch.case13
|
||||
check_subtype9: ; preds = %parent_type_block11, %next_if8
|
||||
%10 = phi i64 [ %4, %next_if8 ], [ %typeid.parent12, %parent_type_block11 ]
|
||||
%eq10 = icmp eq i64 ptrtoint (ptr @"$ct.bool" to i64), %10
|
||||
br i1 %eq10, label %result_block13, label %parent_type_block11
|
||||
|
||||
next_if11: ; preds = %next_if8
|
||||
%eq12 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %4
|
||||
br i1 %eq12, label %switch.case13, label %next_if14
|
||||
parent_type_block11: ; preds = %check_subtype9
|
||||
%11 = inttoptr i64 %10 to ptr
|
||||
%12 = getelementptr inbounds %.introspect, ptr %11, i32 0, i32 1
|
||||
%typeid.parent12 = load i64, ptr %12, align 8
|
||||
%13 = icmp eq i64 %typeid.parent12, 0
|
||||
br i1 %13, label %result_block13, label %check_subtype9
|
||||
|
||||
switch.case13: ; preds = %next_if11, %switch.case10
|
||||
br label %switch.default15
|
||||
result_block13: ; preds = %parent_type_block11, %check_subtype9
|
||||
%14 = phi i1 [ false, %parent_type_block11 ], [ true, %check_subtype9 ]
|
||||
br i1 %14, label %switch.case14, label %next_if15
|
||||
|
||||
next_if14: ; preds = %next_if11
|
||||
br label %switch.default15
|
||||
switch.case14: ; preds = %result_block13
|
||||
br label %switch.case21
|
||||
|
||||
switch.default15: ; preds = %next_if14, %switch.case13
|
||||
next_if15: ; preds = %result_block13
|
||||
br label %check_subtype16
|
||||
|
||||
check_subtype16: ; preds = %parent_type_block18, %next_if15
|
||||
%15 = phi i64 [ %4, %next_if15 ], [ %typeid.parent19, %parent_type_block18 ]
|
||||
%eq17 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %15
|
||||
br i1 %eq17, label %result_block20, label %parent_type_block18
|
||||
|
||||
parent_type_block18: ; preds = %check_subtype16
|
||||
%16 = inttoptr i64 %15 to ptr
|
||||
%17 = getelementptr inbounds %.introspect, ptr %16, i32 0, i32 1
|
||||
%typeid.parent19 = load i64, ptr %17, align 8
|
||||
%18 = icmp eq i64 %typeid.parent19, 0
|
||||
br i1 %18, label %result_block20, label %check_subtype16
|
||||
|
||||
result_block20: ; preds = %parent_type_block18, %check_subtype16
|
||||
%19 = phi i1 [ false, %parent_type_block18 ], [ true, %check_subtype16 ]
|
||||
br i1 %19, label %switch.case21, label %next_if22
|
||||
|
||||
switch.case21: ; preds = %result_block20, %switch.case14
|
||||
br label %switch.default23
|
||||
|
||||
next_if22: ; preds = %result_block20
|
||||
br label %switch.default23
|
||||
|
||||
switch.default23: ; preds = %next_if22, %switch.case21
|
||||
call void (ptr, ...) @printf(ptr @.str.6)
|
||||
br label %switch.exit16
|
||||
br label %switch.exit24
|
||||
|
||||
switch.exit16: ; preds = %switch.default15, %switch.case7
|
||||
switch.exit24: ; preds = %switch.default23, %switch.case7
|
||||
store i32 1, ptr %a, align 4
|
||||
store i32 2, ptr %b, align 4
|
||||
%5 = load i32, ptr %b, align 4
|
||||
%6 = load i32, ptr %a, align 4
|
||||
%add = add i32 %5, %6
|
||||
%20 = load i32, ptr %b, align 4
|
||||
%21 = load i32, ptr %a, align 4
|
||||
%add = add i32 %20, %21
|
||||
store i32 %add, ptr %zy, align 4
|
||||
%7 = load i32, ptr %zy, align 4
|
||||
store i32 %7, ptr %switch17, align 4
|
||||
br label %switch.entry18
|
||||
%22 = load i32, ptr %zy, align 4
|
||||
store i32 %22, ptr %switch25, align 4
|
||||
br label %switch.entry26
|
||||
|
||||
switch.entry18: ; preds = %switch.exit16
|
||||
%8 = load i32, ptr %switch17, align 4
|
||||
%9 = load i32, ptr %a, align 4
|
||||
%eq19 = icmp eq i32 %9, %8
|
||||
br i1 %eq19, label %switch.case20, label %next_if21
|
||||
switch.entry26: ; preds = %switch.exit24
|
||||
%23 = load i32, ptr %switch25, align 4
|
||||
%24 = load i32, ptr %a, align 4
|
||||
%eq27 = icmp eq i32 %24, %23
|
||||
br i1 %eq27, label %switch.case28, label %next_if29
|
||||
|
||||
switch.case20: ; preds = %switch.entry18
|
||||
switch.case28: ; preds = %switch.entry26
|
||||
call void (ptr, ...) @printf(ptr @.str.7)
|
||||
br label %switch.exit26
|
||||
br label %switch.exit34
|
||||
|
||||
next_if21: ; preds = %switch.entry18
|
||||
%10 = load i32, ptr %b, align 4
|
||||
%eq22 = icmp eq i32 %10, %8
|
||||
br i1 %eq22, label %switch.case23, label %next_if24
|
||||
next_if29: ; preds = %switch.entry26
|
||||
%25 = load i32, ptr %b, align 4
|
||||
%eq30 = icmp eq i32 %25, %23
|
||||
br i1 %eq30, label %switch.case31, label %next_if32
|
||||
|
||||
switch.case23: ; preds = %next_if21
|
||||
switch.case31: ; preds = %next_if29
|
||||
call void (ptr, ...) @printf(ptr @.str.8)
|
||||
br label %switch.exit26
|
||||
br label %switch.exit34
|
||||
|
||||
next_if24: ; preds = %next_if21
|
||||
br label %switch.default25
|
||||
next_if32: ; preds = %next_if29
|
||||
br label %switch.default33
|
||||
|
||||
switch.default25: ; preds = %next_if24
|
||||
switch.default33: ; preds = %next_if32
|
||||
call void (ptr, ...) @printf(ptr @.str.9)
|
||||
br label %switch.exit26
|
||||
br label %switch.exit34
|
||||
|
||||
switch.exit26: ; preds = %switch.default25, %switch.case23, %switch.case20
|
||||
store i8 1, ptr %switch27, align 1
|
||||
br label %switch.entry28
|
||||
switch.exit34: ; preds = %switch.default33, %switch.case31, %switch.case28
|
||||
store i8 1, ptr %switch35, align 1
|
||||
br label %switch.entry36
|
||||
|
||||
switch.entry28: ; preds = %switch.exit26
|
||||
%11 = load i8, ptr %switch27, align 1
|
||||
%12 = trunc i8 %11 to i1
|
||||
%13 = load i32, ptr %a, align 4
|
||||
%lt = icmp slt i32 %13, 0
|
||||
%eq29 = icmp eq i1 %lt, %12
|
||||
br i1 %eq29, label %switch.case30, label %next_if31
|
||||
switch.entry36: ; preds = %switch.exit34
|
||||
%26 = load i8, ptr %switch35, align 1
|
||||
%27 = trunc i8 %26 to i1
|
||||
%28 = load i32, ptr %a, align 4
|
||||
%lt = icmp slt i32 %28, 0
|
||||
%eq37 = icmp eq i1 %lt, %27
|
||||
br i1 %eq37, label %switch.case38, label %next_if39
|
||||
|
||||
switch.case30: ; preds = %switch.entry28
|
||||
switch.case38: ; preds = %switch.entry36
|
||||
call void (ptr, ...) @printf(ptr @.str.10)
|
||||
br label %switch.exit37
|
||||
br label %switch.exit45
|
||||
|
||||
next_if31: ; preds = %switch.entry28
|
||||
%14 = load i32, ptr %a, align 4
|
||||
%eq32 = icmp eq i32 %14, 1
|
||||
%eq33 = icmp eq i1 %eq32, %12
|
||||
br i1 %eq33, label %switch.case34, label %next_if35
|
||||
next_if39: ; preds = %switch.entry36
|
||||
%29 = load i32, ptr %a, align 4
|
||||
%eq40 = icmp eq i32 %29, 1
|
||||
%eq41 = icmp eq i1 %eq40, %27
|
||||
br i1 %eq41, label %switch.case42, label %next_if43
|
||||
|
||||
switch.case34: ; preds = %next_if31
|
||||
switch.case42: ; preds = %next_if39
|
||||
call void (ptr, ...) @printf(ptr @.str.11)
|
||||
br label %switch.exit37
|
||||
br label %switch.exit45
|
||||
|
||||
next_if35: ; preds = %next_if31
|
||||
br label %switch.default36
|
||||
next_if43: ; preds = %next_if39
|
||||
br label %switch.default44
|
||||
|
||||
switch.default36: ; preds = %next_if35
|
||||
switch.default44: ; preds = %next_if43
|
||||
call void (ptr, ...) @printf(ptr @.str.12)
|
||||
br label %switch.exit37
|
||||
br label %switch.exit45
|
||||
|
||||
switch.exit37: ; preds = %switch.default36, %switch.case34, %switch.case30
|
||||
switch.exit45: ; preds = %switch.default44, %switch.case42, %switch.case38
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @mymodule.main() #0 {
|
||||
entry:
|
||||
call void @mymodule.test()
|
||||
call void (ptr, ...) @printf(ptr @.str.13)
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ entry:
|
||||
%z = alloca %any, align 8
|
||||
%switch = alloca i64, align 8
|
||||
%z1 = alloca ptr, align 8
|
||||
%z4 = alloca ptr, align 8
|
||||
%z8 = alloca ptr, align 8
|
||||
store i64 %0, ptr %z, align 8
|
||||
%ptroffset = getelementptr inbounds ptr, ptr %z, i64 1
|
||||
store ptr %1, ptr %ptroffset, align 8
|
||||
@@ -78,42 +78,73 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%4 = load i64, ptr %switch, align 8
|
||||
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
br label %check_subtype
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
%5 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
||||
%6 = load ptr, ptr %5, align 8
|
||||
store ptr %6, ptr %z1, align 8
|
||||
%7 = load ptr, ptr %z1, align 8
|
||||
%8 = load i32, ptr %7, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str, i32 %8)
|
||||
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
|
||||
%7 = getelementptr inbounds %.introspect, ptr %6, i32 0, i32 1
|
||||
%typeid.parent = load i64, ptr %7, align 8
|
||||
%8 = icmp eq i64 %typeid.parent, 0
|
||||
br i1 %8, label %result_block, label %check_subtype
|
||||
|
||||
result_block: ; preds = %parent_type_block, %check_subtype
|
||||
%9 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
|
||||
br i1 %9, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %result_block
|
||||
%10 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
||||
%11 = load ptr, ptr %10, align 8
|
||||
store ptr %11, ptr %z1, align 8
|
||||
%12 = load ptr, ptr %z1, align 8
|
||||
%13 = load i32, ptr %12, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str, i32 %13)
|
||||
br label %switch.exit
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq2 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %4
|
||||
br i1 %eq2, label %switch.case3, label %next_if5
|
||||
next_if: ; preds = %result_block
|
||||
br label %check_subtype2
|
||||
|
||||
switch.case3: ; preds = %next_if
|
||||
%9 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
||||
%10 = load ptr, ptr %9, align 8
|
||||
store ptr %10, ptr %z4, align 8
|
||||
%11 = load ptr, ptr %z4, align 8
|
||||
%12 = load double, ptr %11, align 8
|
||||
call void (ptr, ...) @printf(ptr @.str.1, double %12)
|
||||
check_subtype2: ; preds = %parent_type_block4, %next_if
|
||||
%14 = phi i64 [ %4, %next_if ], [ %typeid.parent5, %parent_type_block4 ]
|
||||
%eq3 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %14
|
||||
br i1 %eq3, label %result_block6, label %parent_type_block4
|
||||
|
||||
parent_type_block4: ; preds = %check_subtype2
|
||||
%15 = inttoptr i64 %14 to ptr
|
||||
%16 = getelementptr inbounds %.introspect, ptr %15, i32 0, i32 1
|
||||
%typeid.parent5 = load i64, ptr %16, align 8
|
||||
%17 = icmp eq i64 %typeid.parent5, 0
|
||||
br i1 %17, label %result_block6, label %check_subtype2
|
||||
|
||||
result_block6: ; preds = %parent_type_block4, %check_subtype2
|
||||
%18 = phi i1 [ false, %parent_type_block4 ], [ true, %check_subtype2 ]
|
||||
br i1 %18, label %switch.case7, label %next_if9
|
||||
|
||||
switch.case7: ; preds = %result_block6
|
||||
%19 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
||||
%20 = load ptr, ptr %19, align 8
|
||||
store ptr %20, ptr %z8, align 8
|
||||
%21 = load ptr, ptr %z8, align 8
|
||||
%22 = load double, ptr %21, align 8
|
||||
call void (ptr, ...) @printf(ptr @.str.1, double %22)
|
||||
br label %switch.exit
|
||||
|
||||
next_if5: ; preds = %next_if
|
||||
next_if9: ; preds = %result_block6
|
||||
br label %switch.default
|
||||
|
||||
switch.default: ; preds = %next_if5
|
||||
switch.default: ; preds = %next_if9
|
||||
call void (ptr, ...) @printf(ptr @.str.2)
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit: ; preds = %switch.default, %switch.case3, %switch.case
|
||||
switch.exit: ; preds = %switch.default, %switch.case7, %switch.case
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @foo.test2(i64 %0, ptr %1) #0 {
|
||||
entry:
|
||||
%y = alloca %any, align 8
|
||||
@@ -121,7 +152,7 @@ entry:
|
||||
%switch = alloca i64, align 8
|
||||
%z = alloca ptr, align 8
|
||||
%taddr = alloca i32, align 4
|
||||
%z3 = alloca ptr, align 8
|
||||
%z7 = alloca ptr, align 8
|
||||
store i64 %0, ptr %y, align 8
|
||||
%ptroffset = getelementptr inbounds ptr, ptr %y, i64 1
|
||||
store ptr %1, ptr %ptroffset, align 8
|
||||
@@ -133,43 +164,73 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%4 = load i64, ptr %switch, align 8
|
||||
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
br label %check_subtype
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
%5 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
||||
%6 = load ptr, ptr %5, align 8
|
||||
store ptr %6, ptr %z, align 8
|
||||
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
|
||||
%7 = getelementptr inbounds %.introspect, ptr %6, i32 0, i32 1
|
||||
%typeid.parent = load i64, ptr %7, align 8
|
||||
%8 = icmp eq i64 %typeid.parent, 0
|
||||
br i1 %8, label %result_block, label %check_subtype
|
||||
|
||||
result_block: ; preds = %parent_type_block, %check_subtype
|
||||
%9 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
|
||||
br i1 %9, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %result_block
|
||||
%10 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
||||
%11 = load ptr, ptr %10, align 8
|
||||
store ptr %11, ptr %z, align 8
|
||||
store i32 12, ptr %taddr, align 4
|
||||
%7 = insertvalue %any undef, ptr %taddr, 0
|
||||
%8 = insertvalue %any %7, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
||||
store %any %8, ptr %y, align 8
|
||||
%9 = load ptr, ptr %z, align 8
|
||||
%10 = load i32, ptr %9, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str.3, i32 %10)
|
||||
%12 = insertvalue %any undef, ptr %taddr, 0
|
||||
%13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
||||
store %any %13, ptr %y, align 8
|
||||
%14 = load ptr, ptr %z, align 8
|
||||
%15 = load i32, ptr %14, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str.3, i32 %15)
|
||||
br label %switch.exit
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq1 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %4
|
||||
br i1 %eq1, label %switch.case2, label %next_if4
|
||||
next_if: ; preds = %result_block
|
||||
br label %check_subtype1
|
||||
|
||||
switch.case2: ; preds = %next_if
|
||||
%11 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
||||
%12 = load ptr, ptr %11, align 8
|
||||
store ptr %12, ptr %z3, align 8
|
||||
%13 = load ptr, ptr %z3, align 8
|
||||
%14 = load double, ptr %13, align 8
|
||||
call void (ptr, ...) @printf(ptr @.str.4, double %14)
|
||||
check_subtype1: ; preds = %parent_type_block3, %next_if
|
||||
%16 = phi i64 [ %4, %next_if ], [ %typeid.parent4, %parent_type_block3 ]
|
||||
%eq2 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %16
|
||||
br i1 %eq2, label %result_block5, label %parent_type_block3
|
||||
|
||||
parent_type_block3: ; preds = %check_subtype1
|
||||
%17 = inttoptr i64 %16 to ptr
|
||||
%18 = getelementptr inbounds %.introspect, ptr %17, i32 0, i32 1
|
||||
%typeid.parent4 = load i64, ptr %18, align 8
|
||||
%19 = icmp eq i64 %typeid.parent4, 0
|
||||
br i1 %19, label %result_block5, label %check_subtype1
|
||||
|
||||
result_block5: ; preds = %parent_type_block3, %check_subtype1
|
||||
%20 = phi i1 [ false, %parent_type_block3 ], [ true, %check_subtype1 ]
|
||||
br i1 %20, label %switch.case6, label %next_if8
|
||||
|
||||
switch.case6: ; preds = %result_block5
|
||||
%21 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
||||
%22 = load ptr, ptr %21, align 8
|
||||
store ptr %22, ptr %z7, align 8
|
||||
%23 = load ptr, ptr %z7, align 8
|
||||
%24 = load double, ptr %23, align 8
|
||||
call void (ptr, ...) @printf(ptr @.str.4, double %24)
|
||||
br label %switch.exit
|
||||
|
||||
next_if4: ; preds = %next_if
|
||||
next_if8: ; preds = %result_block5
|
||||
br label %switch.default
|
||||
|
||||
switch.default: ; preds = %next_if4
|
||||
switch.default: ; preds = %next_if8
|
||||
call void (ptr, ...) @printf(ptr @.str.5)
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit: ; preds = %switch.default, %switch.case2, %switch.case
|
||||
switch.exit: ; preds = %switch.default, %switch.case6, %switch.case
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -179,7 +240,7 @@ entry:
|
||||
%.anon = alloca %any, align 8
|
||||
%switch = alloca i64, align 8
|
||||
%z = alloca i32, align 4
|
||||
%z3 = alloca double, align 8
|
||||
%z7 = alloca double, align 8
|
||||
store i64 %0, ptr %y, align 8
|
||||
%ptroffset = getelementptr inbounds ptr, ptr %y, i64 1
|
||||
store ptr %1, ptr %ptroffset, align 8
|
||||
@@ -191,39 +252,69 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%4 = load i64, ptr %switch, align 8
|
||||
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
br label %check_subtype
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
%5 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
||||
%6 = load ptr, ptr %5, align 8
|
||||
%7 = load i32, ptr %6, align 4
|
||||
store i32 %7, ptr %z, align 4
|
||||
%8 = load i32, ptr %z, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str.6, i32 %8)
|
||||
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
|
||||
%7 = getelementptr inbounds %.introspect, ptr %6, i32 0, i32 1
|
||||
%typeid.parent = load i64, ptr %7, align 8
|
||||
%8 = icmp eq i64 %typeid.parent, 0
|
||||
br i1 %8, label %result_block, label %check_subtype
|
||||
|
||||
result_block: ; preds = %parent_type_block, %check_subtype
|
||||
%9 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
|
||||
br i1 %9, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %result_block
|
||||
%10 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
||||
%11 = load ptr, ptr %10, align 8
|
||||
%12 = load i32, ptr %11, align 4
|
||||
store i32 %12, ptr %z, align 4
|
||||
%13 = load i32, ptr %z, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str.6, i32 %13)
|
||||
br label %switch.exit
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq1 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %4
|
||||
br i1 %eq1, label %switch.case2, label %next_if4
|
||||
next_if: ; preds = %result_block
|
||||
br label %check_subtype1
|
||||
|
||||
switch.case2: ; preds = %next_if
|
||||
%9 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
||||
%10 = load ptr, ptr %9, align 8
|
||||
%11 = load double, ptr %10, align 8
|
||||
store double %11, ptr %z3, align 8
|
||||
%12 = load double, ptr %z3, align 8
|
||||
call void (ptr, ...) @printf(ptr @.str.7, double %12)
|
||||
check_subtype1: ; preds = %parent_type_block3, %next_if
|
||||
%14 = phi i64 [ %4, %next_if ], [ %typeid.parent4, %parent_type_block3 ]
|
||||
%eq2 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %14
|
||||
br i1 %eq2, label %result_block5, label %parent_type_block3
|
||||
|
||||
parent_type_block3: ; preds = %check_subtype1
|
||||
%15 = inttoptr i64 %14 to ptr
|
||||
%16 = getelementptr inbounds %.introspect, ptr %15, i32 0, i32 1
|
||||
%typeid.parent4 = load i64, ptr %16, align 8
|
||||
%17 = icmp eq i64 %typeid.parent4, 0
|
||||
br i1 %17, label %result_block5, label %check_subtype1
|
||||
|
||||
result_block5: ; preds = %parent_type_block3, %check_subtype1
|
||||
%18 = phi i1 [ false, %parent_type_block3 ], [ true, %check_subtype1 ]
|
||||
br i1 %18, label %switch.case6, label %next_if8
|
||||
|
||||
switch.case6: ; preds = %result_block5
|
||||
%19 = getelementptr inbounds %any, ptr %.anon, i32 0, i32 0
|
||||
%20 = load ptr, ptr %19, align 8
|
||||
%21 = load double, ptr %20, align 8
|
||||
store double %21, ptr %z7, align 8
|
||||
%22 = load double, ptr %z7, align 8
|
||||
call void (ptr, ...) @printf(ptr @.str.7, double %22)
|
||||
br label %switch.exit
|
||||
|
||||
next_if4: ; preds = %next_if
|
||||
next_if8: ; preds = %result_block5
|
||||
br label %switch.default
|
||||
|
||||
switch.default: ; preds = %next_if4
|
||||
switch.default: ; preds = %next_if8
|
||||
call void (ptr, ...) @printf(ptr @.str.8)
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit: ; preds = %switch.default, %switch.case2, %switch.case
|
||||
switch.exit: ; preds = %switch.default, %switch.case6, %switch.case
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ entry:
|
||||
%z = alloca %any, align 8
|
||||
%switch = alloca i64, align 8
|
||||
%z1 = alloca ptr, align 8
|
||||
%z4 = alloca ptr, align 8
|
||||
%z8 = alloca ptr, align 8
|
||||
store i64 %0, ptr %z, align 8
|
||||
%ptroffset = getelementptr inbounds ptr, ptr %z, i64 1
|
||||
store ptr %1, ptr %ptroffset, align 8
|
||||
@@ -50,51 +50,81 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%4 = load i64, ptr %switch, align 8
|
||||
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
br label %check_subtype
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
%5 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
||||
%6 = load ptr, ptr %5, align 8
|
||||
store ptr %6, ptr %z1, align 8
|
||||
%7 = load ptr, ptr %z1, align 8
|
||||
%8 = load i32, ptr %7, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str, i32 %8)
|
||||
%9 = load ptr, ptr %z1, align 8
|
||||
store i32 3, ptr %9, align 4
|
||||
br label %switch.exit
|
||||
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
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq2 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %4
|
||||
br i1 %eq2, label %switch.case3, label %next_if5
|
||||
parent_type_block: ; preds = %check_subtype
|
||||
%6 = inttoptr i64 %5 to ptr
|
||||
%7 = getelementptr inbounds %.introspect, ptr %6, i32 0, i32 1
|
||||
%typeid.parent = load i64, ptr %7, align 8
|
||||
%8 = icmp eq i64 %typeid.parent, 0
|
||||
br i1 %8, label %result_block, label %check_subtype
|
||||
|
||||
switch.case3: ; preds = %next_if
|
||||
result_block: ; preds = %parent_type_block, %check_subtype
|
||||
%9 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
|
||||
br i1 %9, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %result_block
|
||||
%10 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
||||
%11 = load ptr, ptr %10, align 8
|
||||
store ptr %11, ptr %z4, align 8
|
||||
%12 = load ptr, ptr %z4, align 8
|
||||
%13 = load double, ptr %12, align 8
|
||||
call void (ptr, ...) @printf(ptr @.str.1, double %13)
|
||||
store ptr %11, ptr %z1, align 8
|
||||
%12 = load ptr, ptr %z1, align 8
|
||||
%13 = load i32, ptr %12, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str, i32 %13)
|
||||
%14 = load ptr, ptr %z1, align 8
|
||||
store i32 3, ptr %14, align 4
|
||||
br label %switch.exit
|
||||
|
||||
next_if5: ; preds = %next_if
|
||||
next_if: ; preds = %result_block
|
||||
br label %check_subtype2
|
||||
|
||||
check_subtype2: ; preds = %parent_type_block4, %next_if
|
||||
%15 = phi i64 [ %4, %next_if ], [ %typeid.parent5, %parent_type_block4 ]
|
||||
%eq3 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %15
|
||||
br i1 %eq3, label %result_block6, label %parent_type_block4
|
||||
|
||||
parent_type_block4: ; preds = %check_subtype2
|
||||
%16 = inttoptr i64 %15 to ptr
|
||||
%17 = getelementptr inbounds %.introspect, ptr %16, i32 0, i32 1
|
||||
%typeid.parent5 = load i64, ptr %17, align 8
|
||||
%18 = icmp eq i64 %typeid.parent5, 0
|
||||
br i1 %18, label %result_block6, label %check_subtype2
|
||||
|
||||
result_block6: ; preds = %parent_type_block4, %check_subtype2
|
||||
%19 = phi i1 [ false, %parent_type_block4 ], [ true, %check_subtype2 ]
|
||||
br i1 %19, label %switch.case7, label %next_if9
|
||||
|
||||
switch.case7: ; preds = %result_block6
|
||||
%20 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
||||
%21 = load ptr, ptr %20, align 8
|
||||
store ptr %21, ptr %z8, align 8
|
||||
%22 = load ptr, ptr %z8, align 8
|
||||
%23 = load double, ptr %22, align 8
|
||||
call void (ptr, ...) @printf(ptr @.str.1, double %23)
|
||||
br label %switch.exit
|
||||
|
||||
next_if9: ; preds = %result_block6
|
||||
br label %switch.default
|
||||
|
||||
switch.default: ; preds = %next_if5
|
||||
switch.default: ; preds = %next_if9
|
||||
call void (ptr, ...) @printf(ptr @.str.2)
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit: ; preds = %switch.default, %switch.case3, %switch.case
|
||||
%14 = getelementptr inbounds %any, ptr %z, i32 0, i32 1
|
||||
%15 = load i64, ptr %14, align 8
|
||||
%eq6 = icmp eq i64 %15, ptrtoint (ptr @"$ct.int" to i64)
|
||||
br i1 %eq6, label %if.then, label %if.exit
|
||||
switch.exit: ; preds = %switch.default, %switch.case7, %switch.case
|
||||
%24 = getelementptr inbounds %any, ptr %z, i32 0, i32 1
|
||||
%25 = load i64, ptr %24, align 8
|
||||
%eq10 = icmp eq i64 %25, ptrtoint (ptr @"$ct.int" to i64)
|
||||
br i1 %eq10, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %switch.exit
|
||||
%16 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
||||
%17 = load ptr, ptr %16, align 8
|
||||
%18 = load i32, ptr %17, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str.3, i32 %18)
|
||||
%26 = getelementptr inbounds %any, ptr %z, i32 0, i32 0
|
||||
%27 = load ptr, ptr %26, align 8
|
||||
%28 = load i32, ptr %27, align 4
|
||||
call void (ptr, ...) @printf(ptr @.str.3, i32 %28)
|
||||
br label %if.exit
|
||||
|
||||
if.exit: ; preds = %if.then, %switch.exit
|
||||
|
||||
@@ -86,45 +86,105 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%4 = load i64, ptr %switch, align 8
|
||||
%eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
br label %check_subtype
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
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
|
||||
%7 = getelementptr inbounds %.introspect, ptr %6, i32 0, i32 1
|
||||
%typeid.parent = load i64, ptr %7, align 8
|
||||
%8 = icmp eq i64 %typeid.parent, 0
|
||||
br i1 %8, label %result_block, label %check_subtype
|
||||
|
||||
result_block: ; preds = %parent_type_block, %check_subtype
|
||||
%9 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ]
|
||||
br i1 %9, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %result_block
|
||||
call void (ptr, ...) @printf(ptr @.str)
|
||||
br label %switch.exit
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq1 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %4
|
||||
br i1 %eq1, label %switch.case2, label %next_if3
|
||||
next_if: ; preds = %result_block
|
||||
br label %check_subtype1
|
||||
|
||||
switch.case2: ; preds = %next_if
|
||||
check_subtype1: ; preds = %parent_type_block3, %next_if
|
||||
%10 = phi i64 [ %4, %next_if ], [ %typeid.parent4, %parent_type_block3 ]
|
||||
%eq2 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %10
|
||||
br i1 %eq2, label %result_block5, label %parent_type_block3
|
||||
|
||||
parent_type_block3: ; preds = %check_subtype1
|
||||
%11 = inttoptr i64 %10 to ptr
|
||||
%12 = getelementptr inbounds %.introspect, ptr %11, i32 0, i32 1
|
||||
%typeid.parent4 = load i64, ptr %12, align 8
|
||||
%13 = icmp eq i64 %typeid.parent4, 0
|
||||
br i1 %13, label %result_block5, label %check_subtype1
|
||||
|
||||
result_block5: ; preds = %parent_type_block3, %check_subtype1
|
||||
%14 = phi i1 [ false, %parent_type_block3 ], [ true, %check_subtype1 ]
|
||||
br i1 %14, label %switch.case6, label %next_if7
|
||||
|
||||
switch.case6: ; preds = %result_block5
|
||||
call void (ptr, ...) @printf(ptr @.str.1)
|
||||
br label %switch.exit
|
||||
|
||||
next_if3: ; preds = %next_if
|
||||
%eq4 = icmp eq i64 ptrtoint (ptr @"$ct.any" to i64), %4
|
||||
br i1 %eq4, label %switch.case5, label %next_if6
|
||||
next_if7: ; preds = %result_block5
|
||||
br label %check_subtype8
|
||||
|
||||
switch.case5: ; preds = %next_if3
|
||||
check_subtype8: ; preds = %parent_type_block10, %next_if7
|
||||
%15 = phi i64 [ %4, %next_if7 ], [ %typeid.parent11, %parent_type_block10 ]
|
||||
%eq9 = icmp eq i64 ptrtoint (ptr @"$ct.any" to i64), %15
|
||||
br i1 %eq9, label %result_block12, label %parent_type_block10
|
||||
|
||||
parent_type_block10: ; preds = %check_subtype8
|
||||
%16 = inttoptr i64 %15 to ptr
|
||||
%17 = getelementptr inbounds %.introspect, ptr %16, i32 0, i32 1
|
||||
%typeid.parent11 = load i64, ptr %17, align 8
|
||||
%18 = icmp eq i64 %typeid.parent11, 0
|
||||
br i1 %18, label %result_block12, label %check_subtype8
|
||||
|
||||
result_block12: ; preds = %parent_type_block10, %check_subtype8
|
||||
%19 = phi i1 [ false, %parent_type_block10 ], [ true, %check_subtype8 ]
|
||||
br i1 %19, label %switch.case13, label %next_if14
|
||||
|
||||
switch.case13: ; preds = %result_block12
|
||||
call void (ptr, ...) @printf(ptr @.str.2)
|
||||
br label %switch.exit
|
||||
|
||||
next_if6: ; preds = %next_if3
|
||||
%eq7 = icmp eq i64 ptrtoint (ptr @"$ct.p$int" to i64), %4
|
||||
br i1 %eq7, label %switch.case8, label %next_if9
|
||||
next_if14: ; preds = %result_block12
|
||||
br label %check_subtype15
|
||||
|
||||
switch.case8: ; preds = %next_if6
|
||||
check_subtype15: ; preds = %parent_type_block17, %next_if14
|
||||
%20 = phi i64 [ %4, %next_if14 ], [ %typeid.parent18, %parent_type_block17 ]
|
||||
%eq16 = icmp eq i64 ptrtoint (ptr @"$ct.p$int" to i64), %20
|
||||
br i1 %eq16, label %result_block19, label %parent_type_block17
|
||||
|
||||
parent_type_block17: ; preds = %check_subtype15
|
||||
%21 = inttoptr i64 %20 to ptr
|
||||
%22 = getelementptr inbounds %.introspect, ptr %21, i32 0, i32 1
|
||||
%typeid.parent18 = load i64, ptr %22, align 8
|
||||
%23 = icmp eq i64 %typeid.parent18, 0
|
||||
br i1 %23, label %result_block19, label %check_subtype15
|
||||
|
||||
result_block19: ; preds = %parent_type_block17, %check_subtype15
|
||||
%24 = phi i1 [ false, %parent_type_block17 ], [ true, %check_subtype15 ]
|
||||
br i1 %24, label %switch.case20, label %next_if21
|
||||
|
||||
switch.case20: ; preds = %result_block19
|
||||
call void (ptr, ...) @printf(ptr @.str.3)
|
||||
br label %switch.exit
|
||||
|
||||
next_if9: ; preds = %next_if6
|
||||
next_if21: ; preds = %result_block19
|
||||
br label %switch.default
|
||||
|
||||
switch.default: ; preds = %next_if9
|
||||
switch.default: ; preds = %next_if21
|
||||
call void (ptr, ...) @printf(ptr @.str.4)
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit: ; preds = %switch.default, %switch.case8, %switch.case5, %switch.case2, %switch.case
|
||||
switch.exit: ; preds = %switch.default, %switch.case20, %switch.case13, %switch.case6, %switch.case
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
91
test/unit/regression/subtype.c3
Normal file
91
test/unit/regression/subtype.c3
Normal file
@@ -0,0 +1,91 @@
|
||||
module switch_subtype @test;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
inline Baz g;
|
||||
int a;
|
||||
}
|
||||
struct Bar
|
||||
{
|
||||
inline Foo f;
|
||||
}
|
||||
struct Baz
|
||||
{
|
||||
int z;
|
||||
}
|
||||
fn void switch_subtyping()
|
||||
{
|
||||
Foo f = {};
|
||||
f.z = 123;
|
||||
any x = &f;
|
||||
switch (x)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Baz:
|
||||
assert(true);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
switch (x)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Foo:
|
||||
assert(true);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
switch (x)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Bar:
|
||||
assert(false);
|
||||
default:
|
||||
assert(true);
|
||||
}
|
||||
switch (Bar.typeid)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Baz:
|
||||
assert(true);
|
||||
case Foo:
|
||||
assert(false);
|
||||
case Bar:
|
||||
assert(false);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
switch (Bar.typeid)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Foo:
|
||||
assert(true);
|
||||
case Bar:
|
||||
assert(false);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
$switch (Bar.typeid)
|
||||
$case Foo:
|
||||
assert(true);
|
||||
$case Bar:
|
||||
assert(false);
|
||||
$default:
|
||||
assert(false);
|
||||
$endswitch
|
||||
}
|
||||
|
||||
fn void is_subtype()
|
||||
{
|
||||
$assert(types::is_subtype_of(Bar, Baz));
|
||||
$assert(!types::is_subtype_of(Baz, Bar));
|
||||
typeid baz = Baz.typeid;
|
||||
typeid bar = Bar.typeid;
|
||||
assert(bar.is_subtype_of(baz));
|
||||
assert(!bar.is_subtype_of(double.typeid));
|
||||
assert(!baz.is_subtype_of(bar));
|
||||
}
|
||||
Reference in New Issue
Block a user