mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Make errors usable from other units. Order subarray elements correctly. Correct subarray -> pointer cast. Prevent unwrapping of catch in switch.
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
module std::io;
|
||||
|
||||
errtype IoError
|
||||
{
|
||||
FILE_NOT_FOUND
|
||||
}
|
||||
/*
|
||||
extern File *stdin @cname(__stdinp);
|
||||
extern File *stdout @cname(__stdoutp);
|
||||
|
||||
@@ -714,6 +714,29 @@ void llvm_codegen_setup()
|
||||
intrinsics_setup = true;
|
||||
}
|
||||
|
||||
static void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value)
|
||||
{
|
||||
if (decl->module != c->code_module)
|
||||
{
|
||||
LLVMSetLinkage(value, LLVMLinkOnceODRLinkage);
|
||||
LLVMSetVisibility(value, LLVMDefaultVisibility);
|
||||
return;
|
||||
}
|
||||
switch (decl->visibility)
|
||||
{
|
||||
case VISIBLE_MODULE:
|
||||
case VISIBLE_PUBLIC:
|
||||
LLVMSetLinkage(value, LLVMLinkOnceODRLinkage);
|
||||
LLVMSetVisibility(value, LLVMDefaultVisibility);
|
||||
break;
|
||||
case VISIBLE_EXTERN:
|
||||
case VISIBLE_LOCAL:
|
||||
LLVMSetVisibility(value, LLVMHiddenVisibility);
|
||||
LLVMSetLinkage(value, LLVMLinkerPrivateLinkage);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
void gencontext_emit_introspection_type(GenContext *c, Decl *decl)
|
||||
{
|
||||
llvm_get_type(c, decl->type);
|
||||
@@ -739,6 +762,7 @@ void gencontext_emit_introspection_type(GenContext *c, Decl *decl)
|
||||
scratch_buffer_append("$elements");
|
||||
LLVMValueRef enum_elements = LLVMAddGlobal(c->module, elements_type, scratch_buffer_to_string());
|
||||
LLVMSetGlobalConstant(enum_elements, 1);
|
||||
llvm_set_linkage(c, decl, enum_elements);
|
||||
LLVMSetInitializer(enum_elements, LLVMConstNull(elements_type));
|
||||
for (unsigned i = 0; i < elements; i++)
|
||||
{
|
||||
@@ -750,20 +774,8 @@ void gencontext_emit_introspection_type(GenContext *c, Decl *decl)
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false));
|
||||
decl->type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));
|
||||
llvm_set_linkage(c, decl, global_name);
|
||||
|
||||
switch (decl->visibility)
|
||||
{
|
||||
case VISIBLE_MODULE:
|
||||
case VISIBLE_PUBLIC:
|
||||
LLVMSetLinkage(global_name, LLVMLinkOnceODRLinkage);
|
||||
LLVMSetVisibility(global_name, LLVMDefaultVisibility);
|
||||
break;
|
||||
case VISIBLE_EXTERN:
|
||||
case VISIBLE_LOCAL:
|
||||
LLVMSetVisibility(global_name, LLVMHiddenVisibility);
|
||||
LLVMSetLinkage(global_name, LLVMLinkerPrivateLinkage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -578,8 +578,8 @@ AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_ty
|
||||
if (offset < 16) return abi_type_new_plain(type_voidptr);
|
||||
break;
|
||||
case TYPE_SUBARRAY:
|
||||
if (offset < 8) return abi_type_new_plain(type_ulong);
|
||||
if (offset < 16) return abi_type_new_plain(type_voidptr);
|
||||
if (offset < 8) return abi_type_new_plain(type_voidptr);
|
||||
if (offset < 16) return abi_type_new_plain(type_ulong);
|
||||
break;
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
|
||||
@@ -578,12 +578,10 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_
|
||||
llvm_emit_arr_to_subarray_cast(c, value, to_type);
|
||||
break;
|
||||
case CAST_SAPTR:
|
||||
llvm_value_fold_failable(c, value);
|
||||
if (llvm_value_is_addr(value))
|
||||
{
|
||||
llvm_value_fold_failable(c, value);
|
||||
value->value = llvm_emit_load_aligned(c, llvm_get_type(c, to_type),
|
||||
LLVMBuildStructGEP(c->builder, value->value, 0, ""),
|
||||
value->alignment, "");
|
||||
value->value = LLVMBuildStructGEP(c->builder, value->value, 0, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2675,6 +2673,7 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
case CONST_ERR:
|
||||
{
|
||||
Decl *decl = expr->const_expr.err_val;
|
||||
|
||||
LLVMValueRef value;
|
||||
if (decl)
|
||||
{
|
||||
@@ -2796,9 +2795,9 @@ void llvm_emit_subarray_pointer(GenContext *c, BEValue *subarray, BEValue *point
|
||||
{
|
||||
llvm_value_addr(c, subarray);
|
||||
unsigned alignment = 0;
|
||||
LLVMValueRef len_addr = llvm_emit_struct_gep_raw(c, subarray->value, llvm_get_type(c, subarray->type), 0, subarray->alignment,
|
||||
LLVMValueRef pointer_addr = llvm_emit_struct_gep_raw(c, subarray->value, llvm_get_type(c, subarray->type), 0, subarray->alignment,
|
||||
0, &alignment);
|
||||
llvm_value_set_address_align(pointer, len_addr, type_get_ptr(subarray->type->array.base), alignment);
|
||||
llvm_value_set_address_align(pointer, pointer_addr, type_get_ptr(subarray->type->array.base), alignment);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -647,7 +647,10 @@ void llvm_emit_extern_decl(GenContext *context, Decl *decl)
|
||||
// TODO // Fix typeid
|
||||
break;
|
||||
case DECL_ENUM:
|
||||
llvm_emit_methods(context, decl->methods);
|
||||
break;
|
||||
case DECL_ERRTYPE:
|
||||
gencontext_emit_introspection_type(context, decl);
|
||||
llvm_emit_methods(context, decl->methods);
|
||||
// TODO // Fix typeid
|
||||
return;
|
||||
|
||||
@@ -225,6 +225,7 @@ void llvm_emit_convert_value_from_coerced(GenContext *c, BEValue *result, LLVMTy
|
||||
void llvm_emit_coerce_store(GenContext *c, LLVMValueRef addr, AlignSize alignment, LLVMTypeRef coerced, LLVMValueRef value, LLVMTypeRef target_type);
|
||||
void llvm_emit_function_body(GenContext *context, Decl *decl);
|
||||
void llvm_emit_function_decl(GenContext *c, Decl *decl);
|
||||
void gencontext_emit_introspection_type(GenContext *c, Decl *decl);
|
||||
LLVMValueRef llvm_emit_call_intrinsic(GenContext *c, unsigned intrinsic_id, LLVMTypeRef *types, unsigned type_count, LLVMValueRef *values, unsigned arg_count);
|
||||
void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_type, Type *from_type);
|
||||
void llvm_emit_cond_br(GenContext *context, BEValue *value, LLVMBasicBlockRef then_block, LLVMBasicBlockRef else_block);
|
||||
|
||||
@@ -2240,6 +2240,8 @@ static inline bool sema_expr_analyse_type_access(Context *context, Expr *expr, T
|
||||
}
|
||||
break;
|
||||
case DECL_ERRTYPE:
|
||||
context_register_external_symbol(context, decl);
|
||||
|
||||
if (type == TOKEN_CONST_IDENT)
|
||||
{
|
||||
if (!sema_expr_analyse_enum_constant(expr, identifier_token, decl))
|
||||
|
||||
@@ -395,13 +395,23 @@ static void sema_remove_unwraps_from_try(Context *c, Expr *cond)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_last_cond(Context *context, Expr *expr)
|
||||
static inline bool sema_analyse_last_cond(Context *context, Expr *expr, bool may_unwrap)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_TRY_UNWRAP_CHAIN:
|
||||
if (!may_unwrap)
|
||||
{
|
||||
SEMA_ERROR(expr, "Try unwrapping is only allowed inside of a 'while' or 'if' conditional.");
|
||||
return false;
|
||||
}
|
||||
return sema_analyse_try_unwrap_chain(context, expr);
|
||||
case EXPR_CATCH_UNWRAP:
|
||||
if (!may_unwrap)
|
||||
{
|
||||
SEMA_ERROR(expr, "Catch unwrapping is only allowed inside of a 'while' or 'if' conditional, maybe catch(...) will do what you need?");
|
||||
return false;
|
||||
}
|
||||
return sema_analyse_catch_unwrap(context, expr);
|
||||
default:
|
||||
return sema_analyse_expr(context, NULL, expr);
|
||||
@@ -435,7 +445,7 @@ static inline bool sema_analyse_cond_list(Context *context, Expr *expr, bool may
|
||||
if (!sema_analyse_expr(context, NULL, dexprs[i])) return false;
|
||||
}
|
||||
|
||||
if (!sema_analyse_last_cond(context, dexprs[entries - 1])) return false;
|
||||
if (!sema_analyse_last_cond(context, dexprs[entries - 1], may_unwrap)) return false;
|
||||
|
||||
expr_set_type(expr, dexprs[entries - 1]->type);
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
@@ -454,12 +464,12 @@ static inline bool sema_analyse_cond_list(Context *context, Expr *expr, bool may
|
||||
* @param cast_to_bool if the result is to be cast to bool after
|
||||
* @return true if it passes analysis.
|
||||
*/
|
||||
static inline bool sema_analyse_cond(Context *context, Expr *expr, bool cast_to_bool)
|
||||
static inline bool sema_analyse_cond(Context *context, Expr *expr, bool cast_to_bool, bool may_unwrap)
|
||||
{
|
||||
assert(expr->expr_kind == EXPR_COND && "Conditional expressions should always be of type EXPR_DECL_LIST");
|
||||
|
||||
// 1. Analyse the declaration list.
|
||||
if (!sema_analyse_cond_list(context, expr, true)) return false;
|
||||
if (!sema_analyse_cond_list(context, expr, may_unwrap)) return false;
|
||||
|
||||
// 2. If we get "void", either through a void call or an empty list,
|
||||
// signal that.
|
||||
@@ -537,7 +547,7 @@ static inline bool sema_analyse_while_stmt(Context *context, Ast *statement)
|
||||
SCOPE_START_WITH_LABEL(statement->while_stmt.flow.label)
|
||||
|
||||
// 2. Analyze the condition
|
||||
if (!sema_analyse_cond(context, cond, true))
|
||||
if (!sema_analyse_cond(context, cond, true, true))
|
||||
{
|
||||
// 2a. In case of error, pop context and exit.
|
||||
return SCOPE_POP_ERROR();
|
||||
@@ -1320,7 +1330,7 @@ static inline bool sema_analyse_if_stmt(Context *context, Ast *statement)
|
||||
Expr *cond = statement->if_stmt.cond;
|
||||
SCOPE_OUTER_START
|
||||
bool cast_to_bool = statement->if_stmt.then_body->ast_kind != AST_IF_CATCH_SWITCH_STMT;
|
||||
success = sema_analyse_cond(context, cond, cast_to_bool);
|
||||
success = sema_analyse_cond(context, cond, cast_to_bool, true);
|
||||
|
||||
Ast *then = statement->if_stmt.then_body;
|
||||
bool then_has_braces = then->ast_kind == AST_COMPOUND_STMT || then->ast_kind == AST_IF_CATCH_SWITCH_STMT;
|
||||
@@ -1966,7 +1976,7 @@ static bool sema_analyse_switch_stmt(Context *context, Ast *statement)
|
||||
|
||||
if (statement->ast_kind == AST_SWITCH_STMT)
|
||||
{
|
||||
if (!sema_analyse_cond(context, cond, false)) return false;
|
||||
if (!sema_analyse_cond(context, cond, false, false)) return false;
|
||||
switch_type = VECLAST(cond->cond_expr)->type->canonical;
|
||||
}
|
||||
else
|
||||
|
||||
89
test/test_suite/from_docs/examples_defer.c3t
Normal file
89
test/test_suite/from_docs/examples_defer.c3t
Normal file
@@ -0,0 +1,89 @@
|
||||
// #target: x64-darwin
|
||||
module defer1;
|
||||
import std::io;
|
||||
|
||||
func void test(int x)
|
||||
{
|
||||
defer io::println();
|
||||
defer io::print("A");
|
||||
if (x == 1) return;
|
||||
{
|
||||
defer io::print("B");
|
||||
if (x == 0) return;
|
||||
}
|
||||
io::print("!");
|
||||
}
|
||||
|
||||
func void main()
|
||||
{
|
||||
test(1); // Prints "A"
|
||||
test(0); // Prints "BA"
|
||||
test(10); // Prints "B!A"
|
||||
}
|
||||
|
||||
// #expect: defer1.ll
|
||||
|
||||
define void @defer1.test(i32 %0) #0 {
|
||||
entry:
|
||||
%x = alloca i32, align 4
|
||||
store i32 %0, i32* %x, align 4
|
||||
%1 = load i32, i32* %x, align 4
|
||||
%eq = icmp eq i32 %1, 1
|
||||
br i1 %eq, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %entry
|
||||
%2 = call i32 @"std::io.print"(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0))
|
||||
br label %exit
|
||||
|
||||
exit: ; preds = %if.then
|
||||
%3 = call i32 @"std::io.println"(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.1, i32 0, i32 0)) #1
|
||||
br label %exit1
|
||||
|
||||
exit1: ; preds = %exit
|
||||
ret void
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
%4 = load i32, i32* %x, align 4
|
||||
%eq2 = icmp eq i32 %4, 0
|
||||
br i1 %eq2, label %if.then3, label %if.exit7
|
||||
|
||||
if.then3: ; preds = %if.exit
|
||||
%5 = call i32 @"std::io.print"(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.2, i32 0, i32 0))
|
||||
br label %exit4
|
||||
|
||||
exit4: ; preds = %if.then3
|
||||
%6 = call i32 @"std::io.print"(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.3, i32 0, i32 0))
|
||||
br label %exit5
|
||||
|
||||
exit5: ; preds = %exit4
|
||||
%7 = call i32 @"std::io.println"(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.4, i32 0, i32 0)) #1
|
||||
br label %exit6
|
||||
|
||||
exit6: ; preds = %exit5
|
||||
ret void
|
||||
|
||||
if.exit7: ; preds = %if.exit
|
||||
%8 = call i32 @"std::io.print"(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.5, i32 0, i32 0))
|
||||
br label %exit8
|
||||
|
||||
exit8: ; preds = %if.exit7
|
||||
%9 = call i32 @"std::io.print"(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.6, i32 0, i32 0))
|
||||
%10 = call i32 @"std::io.print"(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.7, i32 0, i32 0))
|
||||
br label %exit9
|
||||
|
||||
exit9: ; preds = %exit8
|
||||
%11 = call i32 @"std::io.println"(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.8, i32 0, i32 0)) #1
|
||||
br label %exit10
|
||||
|
||||
exit10: ; preds = %exit9
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @main() #0 {
|
||||
entry:
|
||||
call void @defer1.test(i32 1)
|
||||
call void @defer1.test(i32 0)
|
||||
call void @defer1.test(i32 10)
|
||||
ret void
|
||||
}
|
||||
245
test/test_suite/from_docs/examples_forswitch.c3t
Normal file
245
test/test_suite/from_docs/examples_forswitch.c3t
Normal file
@@ -0,0 +1,245 @@
|
||||
// #target: x64-darwin
|
||||
module examples;
|
||||
|
||||
import std::io;
|
||||
|
||||
func void example_for()
|
||||
{
|
||||
// the for-loop is the same as C99.
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
io::printf("%d\n", i);
|
||||
}
|
||||
|
||||
// also equal
|
||||
for (;;)
|
||||
{
|
||||
// ..
|
||||
}
|
||||
}
|
||||
|
||||
enum Height : uint
|
||||
{
|
||||
LOW = 0,
|
||||
MEDIUM,
|
||||
HIGH,
|
||||
}
|
||||
|
||||
func void demo_enum(Height h)
|
||||
{
|
||||
switch (h)
|
||||
{
|
||||
case LOW:
|
||||
case MEDIUM:
|
||||
io::println("Not high");
|
||||
// Implicit break.
|
||||
case HIGH:
|
||||
io::println("High");
|
||||
}
|
||||
|
||||
// This also works
|
||||
switch (h)
|
||||
{
|
||||
case LOW:
|
||||
case MEDIUM:
|
||||
io::println("Not high");
|
||||
// Implicit break.
|
||||
case Height.HIGH:
|
||||
io::println("High");
|
||||
}
|
||||
|
||||
// Completely empty cases are not allowed.
|
||||
switch (h)
|
||||
{
|
||||
case LOW:
|
||||
break; // Explicit break required, since switches can't be empty.
|
||||
case MEDIUM:
|
||||
io::println("Medium");
|
||||
case HIGH:
|
||||
break;
|
||||
}
|
||||
|
||||
// special checking of switching on enum types
|
||||
switch (h)
|
||||
{
|
||||
case LOW:
|
||||
case MEDIUM:
|
||||
case HIGH:
|
||||
break;
|
||||
default: // warning: default label in switch which covers all enumeration value
|
||||
break;
|
||||
}
|
||||
|
||||
// Using "nextcase" will fallthrough to the next case statement,
|
||||
// and each case statement starts its own scope.
|
||||
switch (h)
|
||||
{
|
||||
case LOW:
|
||||
int a = 1;
|
||||
io::println("A");
|
||||
nextcase;
|
||||
case MEDIUM:
|
||||
int a = 2;
|
||||
io::println("B");
|
||||
nextcase;
|
||||
case HIGH:
|
||||
// a is not defined here
|
||||
io::println("C");
|
||||
}
|
||||
}
|
||||
// #expect: examples.ll
|
||||
|
||||
define void @examples.example_for() #0 {
|
||||
entry:
|
||||
%i = alloca i32, align 4
|
||||
store i32 0, i32* %i, align 4
|
||||
br label %for.cond
|
||||
|
||||
for.cond: ; preds = %for.inc, %entry
|
||||
%0 = load i32, i32* %i, align 4
|
||||
%lt = icmp slt i32 %0, 10
|
||||
br i1 %lt, label %for.body, label %for.exit
|
||||
|
||||
for.body: ; preds = %for.cond
|
||||
%1 = load i32, i32* %i, align 4
|
||||
%2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1)
|
||||
br label %for.inc
|
||||
|
||||
for.inc: ; preds = %for.body
|
||||
%3 = load i32, i32* %i, align 4
|
||||
%add = add i32 %3, 1
|
||||
store i32 %add, i32* %i, align 4
|
||||
br label %for.cond
|
||||
|
||||
for.exit: ; preds = %for.cond
|
||||
br label %infiniteloop
|
||||
|
||||
infiniteloop: ; preds = %infiniteloop, %for.exit
|
||||
br label %infiniteloop
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @examples.demo_enum(i32 %0) #0 {
|
||||
entry:
|
||||
%h = alloca i32, align 4
|
||||
%switch = alloca i32, align 4
|
||||
%switch2 = alloca i32, align 4
|
||||
%switch7 = alloca i32, align 4
|
||||
%switch13 = alloca i32, align 4
|
||||
%switch17 = alloca i32, align 4
|
||||
%a = alloca i32, align 4
|
||||
%a21 = alloca i32, align 4
|
||||
store i32 %0, i32* %h, align 4
|
||||
%1 = load i32, i32* %h, align 4
|
||||
store i32 %1, i32* %switch, align 4
|
||||
br label %switch.entry
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%2 = load i32, i32* %switch, align 4
|
||||
switch i32 %2, label %switch.exit [
|
||||
i32 0, label %switch.case
|
||||
i32 1, label %switch.case
|
||||
i32 2, label %switch.case1
|
||||
]
|
||||
|
||||
switch.case: ; preds = %switch.entry, %switch.entry
|
||||
%3 = call i32 @"std::io.println"(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i32 0, i32 0)) #1
|
||||
br label %switch.exit
|
||||
|
||||
switch.case1: ; preds = %switch.entry
|
||||
%4 = call i32 @"std::io.println"(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i32 0, i32 0)) #1
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit: ; preds = %switch.case1, %switch.case, %switch.entry
|
||||
%5 = load i32, i32* %h, align 4
|
||||
store i32 %5, i32* %switch2, align 4
|
||||
br label %switch.entry3
|
||||
|
||||
switch.entry3: ; preds = %switch.exit
|
||||
%6 = load i32, i32* %switch2, align 4
|
||||
switch i32 %6, label %switch.exit6 [
|
||||
i32 0, label %switch.case4
|
||||
i32 1, label %switch.case4
|
||||
i32 2, label %switch.case5
|
||||
]
|
||||
|
||||
switch.case4: ; preds = %switch.entry3, %switch.entry3
|
||||
%7 = call i32 @"std::io.println"(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.3, i32 0, i32 0)) #1
|
||||
br label %switch.exit6
|
||||
|
||||
switch.case5: ; preds = %switch.entry3
|
||||
%8 = call i32 @"std::io.println"(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.4, i32 0, i32 0)) #1
|
||||
br label %switch.exit6
|
||||
|
||||
switch.exit6: ; preds = %switch.case5, %switch.case4, %switch.entry3
|
||||
%9 = load i32, i32* %h, align 4
|
||||
store i32 %9, i32* %switch7, align 4
|
||||
br label %switch.entry8
|
||||
|
||||
switch.entry8: ; preds = %switch.exit6
|
||||
%10 = load i32, i32* %switch7, align 4
|
||||
switch i32 %10, label %switch.exit12 [
|
||||
i32 0, label %switch.case9
|
||||
i32 1, label %switch.case10
|
||||
i32 2, label %switch.case11
|
||||
]
|
||||
|
||||
switch.case9: ; preds = %switch.entry8
|
||||
br label %switch.exit12
|
||||
|
||||
switch.case10: ; preds = %switch.entry8
|
||||
%11 = call i32 @"std::io.println"(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.5, i32 0, i32 0)) #1
|
||||
br label %switch.exit12
|
||||
|
||||
switch.case11: ; preds = %switch.entry8
|
||||
br label %switch.exit12
|
||||
|
||||
switch.exit12: ; preds = %switch.case11, %switch.case10, %switch.case9, %switch.entry8
|
||||
%12 = load i32, i32* %h, align 4
|
||||
store i32 %12, i32* %switch13, align 4
|
||||
br label %switch.entry14
|
||||
|
||||
switch.entry14: ; preds = %switch.exit12
|
||||
%13 = load i32, i32* %switch13, align 4
|
||||
switch i32 %13, label %switch.default [
|
||||
i32 0, label %switch.case15
|
||||
i32 1, label %switch.case15
|
||||
i32 2, label %switch.case15
|
||||
]
|
||||
|
||||
switch.case15: ; preds = %switch.entry14, %switch.entry14, %switch.entry14
|
||||
br label %switch.exit16
|
||||
|
||||
switch.default: ; preds = %switch.entry14
|
||||
br label %switch.exit16
|
||||
|
||||
switch.exit16: ; preds = %switch.default, %switch.case15
|
||||
%14 = load i32, i32* %h, align 4
|
||||
store i32 %14, i32* %switch17, align 4
|
||||
br label %switch.entry18
|
||||
|
||||
switch.entry18: ; preds = %switch.exit16
|
||||
%15 = load i32, i32* %switch17, align 4
|
||||
switch i32 %15, label %switch.exit23 [
|
||||
i32 0, label %switch.case19
|
||||
i32 1, label %switch.case20
|
||||
i32 2, label %switch.case22
|
||||
]
|
||||
|
||||
switch.case19: ; preds = %switch.entry18
|
||||
store i32 1, i32* %a, align 4
|
||||
%16 = call i32 @"std::io.println"(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.6, i32 0, i32 0)) #1
|
||||
br label %switch.case20
|
||||
|
||||
switch.case20: ; preds = %switch.entry18, %switch.case19
|
||||
store i32 2, i32* %a21, align 4
|
||||
%17 = call i32 @"std::io.println"(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.7, i32 0, i32 0)) #1
|
||||
br label %switch.case22
|
||||
|
||||
switch.case22: ; preds = %switch.entry18, %switch.case20
|
||||
%18 = call i32 @"std::io.println"(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.8, i32 0, i32 0)) #1
|
||||
br label %switch.exit23
|
||||
|
||||
switch.exit23: ; preds = %switch.case22, %switch.entry18
|
||||
ret void
|
||||
}
|
||||
37
test/test_suite/from_docs/examples_functionpointer.c3t
Normal file
37
test/test_suite/from_docs/examples_functionpointer.c3t
Normal file
@@ -0,0 +1,37 @@
|
||||
// #target: x64-darwin
|
||||
|
||||
module demo;
|
||||
define Callback = func int(char* text, int value);
|
||||
|
||||
func int my_callback(char* text, int value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Callback cb = &my_callback;
|
||||
|
||||
func void main()
|
||||
{
|
||||
int result = cb("demo", 123);
|
||||
// ..
|
||||
}
|
||||
|
||||
// #expect: demo.ll
|
||||
|
||||
define i32 @demo.my_callback(i8* %0, i32 %1) #0 {
|
||||
entry:
|
||||
%text = alloca i8*, align 8
|
||||
%value = alloca i32, align 4
|
||||
store i8* %0, i8** %text, align 8
|
||||
store i32 %1, i32* %value, align 4
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define void @main() #0 {
|
||||
entry:
|
||||
%result = alloca i32, align 4
|
||||
%0 = load i32 (i8*, i32)*, i32 (i8*, i32)** @demo.cb, align 8
|
||||
%1 = call i32 %0(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0), i32 123)
|
||||
store i32 %1, i32* %result, align 4
|
||||
ret void
|
||||
}
|
||||
176
test/test_suite/from_docs/examples_if_catch.c3t
Normal file
176
test/test_suite/from_docs/examples_if_catch.c3t
Normal file
@@ -0,0 +1,176 @@
|
||||
// #target: x64-darwin
|
||||
module demo;
|
||||
import std::io;
|
||||
|
||||
errtype MathError
|
||||
{
|
||||
DIVISION_BY_ZERO
|
||||
}
|
||||
|
||||
func int foo() { return 123; }
|
||||
func int bar() { return 0; }
|
||||
|
||||
func double! divide(int a, int b)
|
||||
{
|
||||
if (b == 0) return MathError.DIVISION_BY_ZERO!;
|
||||
return (double)(a) / (double)(b);
|
||||
|
||||
}
|
||||
|
||||
// Rethrowing an error uses "!!" suffix
|
||||
func void! testMayError()
|
||||
{
|
||||
divide(foo(), bar())!!;
|
||||
}
|
||||
|
||||
func void main()
|
||||
{
|
||||
// ratio has a failable type.
|
||||
double! ratio = divide(foo(), bar());
|
||||
|
||||
// Handle the error
|
||||
if (catch err = ratio)
|
||||
{
|
||||
case MathError.DIVISION_BY_ZERO:
|
||||
io::printf("Division by zero\n");
|
||||
return;
|
||||
default:
|
||||
io::printf("Unexpected error!");
|
||||
return;
|
||||
}
|
||||
// Flow typing makes "ratio"
|
||||
// have the type double here.
|
||||
io::printf("Ratio was %f\n", ratio);
|
||||
}
|
||||
|
||||
// #expect: demo.ll
|
||||
|
||||
define i64 @demo.divide(double* %0, i32 %1, i32 %2) #0 {
|
||||
entry:
|
||||
%a = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
%reterr = alloca i64, align 8
|
||||
%reterr1 = alloca i64, align 8
|
||||
store i32 %1, i32* %a, align 4
|
||||
store i32 %2, i32* %b, align 4
|
||||
%3 = load i32, i32* %b, align 4
|
||||
%eq = icmp eq i32 %3, 0
|
||||
br i1 %eq, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %entry
|
||||
store i64 ptrtoint ([1 x i8*]* @"demo.MathError$elements" to i64), i64* %reterr, align 8
|
||||
br label %err_retblock
|
||||
|
||||
postfailed: ; No predecessors!
|
||||
store double undef, double* %0, align 8
|
||||
ret i64 0
|
||||
|
||||
err_retblock: ; preds = %if.then
|
||||
%4 = load i64, i64* %reterr, align 8
|
||||
ret i64 %4
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
%5 = load i32, i32* %a, align 4
|
||||
%sifp = sitofp i32 %5 to double
|
||||
%6 = load i32, i32* %b, align 4
|
||||
%sifp2 = sitofp i32 %6 to double
|
||||
%fdiv = fdiv double %sifp, %sifp2
|
||||
store double %fdiv, double* %0, align 8
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
define i64 @demo.testMayError() #0 {
|
||||
entry:
|
||||
%error_var = alloca i64, align 8
|
||||
%retparam = alloca double, align 8
|
||||
%0 = call i32 @demo.foo()
|
||||
%1 = call i32 @demo.bar()
|
||||
%2 = call i64 @demo.divide(double* %retparam, i32 %0, i32 %1)
|
||||
%not_err = icmp eq i64 %2, 0
|
||||
br i1 %not_err, label %after.errcheck, label %error
|
||||
|
||||
error: ; preds = %entry
|
||||
store i64 %2, i64* %error_var, align 8
|
||||
br label %guard_block
|
||||
|
||||
after.errcheck: ; preds = %entry
|
||||
%3 = load double, double* %retparam, align 8
|
||||
br label %noerr_block
|
||||
|
||||
guard_block: ; preds = %error
|
||||
%4 = load i64, i64* %error_var, align 8
|
||||
ret i64 %4
|
||||
|
||||
noerr_block: ; preds = %after.errcheck
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
define void @main() #0 {
|
||||
entry:
|
||||
%ratio = alloca double, align 8
|
||||
%ratio.f = alloca i64, align 8
|
||||
%retparam = alloca double, align 8
|
||||
%err = alloca i64, align 8
|
||||
%switch = alloca i64, align 8
|
||||
%0 = call i32 @demo.foo()
|
||||
%1 = call i32 @demo.bar()
|
||||
%2 = call i64 @demo.divide(double* %retparam, i32 %0, i32 %1)
|
||||
%not_err = icmp eq i64 %2, 0
|
||||
br i1 %not_err, label %after.errcheck, label %error
|
||||
|
||||
error: ; preds = %entry
|
||||
store i64 %2, i64* %ratio.f, align 8
|
||||
br label %after_assign
|
||||
|
||||
after.errcheck: ; preds = %entry
|
||||
%3 = load double, double* %retparam, align 8
|
||||
store double %3, double* %ratio, align 8
|
||||
store i64 0, i64* %ratio.f, align 8
|
||||
br label %after_assign
|
||||
|
||||
after_assign: ; preds = %after.errcheck, %error
|
||||
br label %testblock
|
||||
|
||||
testblock: ; preds = %after_assign
|
||||
%4 = load i64, i64* %ratio.f, align 8
|
||||
%not_err1 = icmp eq i64 %4, 0
|
||||
br i1 %not_err1, label %after_check, label %error2
|
||||
|
||||
error2: ; preds = %testblock
|
||||
store i64 %4, i64* %err, align 8
|
||||
br label %end_block
|
||||
|
||||
after_check: ; preds = %testblock
|
||||
store i64 0, i64* %err, align 8
|
||||
br label %end_block
|
||||
|
||||
end_block: ; preds = %after_check, %error2
|
||||
%5 = load i64, i64* %err, align 8
|
||||
%neq = icmp ne i64 %5, 0
|
||||
br i1 %neq, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %end_block
|
||||
store i64 %5, i64* %switch, align 8
|
||||
br label %switch.entry
|
||||
|
||||
switch.entry: ; preds = %if.then
|
||||
%6 = load i64, i64* %switch, align 8
|
||||
%eq = icmp eq i64 ptrtoint ([1 x i8*]* @"demo.MathError$elements" to i64), %6
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
%7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str, i32 0, i32 0))
|
||||
ret void
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
br label %switch.default
|
||||
|
||||
switch.default: ; preds = %next_if
|
||||
%8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i32 0, i32 0))
|
||||
ret void
|
||||
|
||||
if.exit: ; preds = %end_block
|
||||
%9 = load double, double* %ratio, align 8
|
||||
%10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.2, i32 0, i32 0), double %9)
|
||||
ret void
|
||||
}
|
||||
46
test/test_suite/from_docs/examples_struct.c3
Normal file
46
test/test_suite/from_docs/examples_struct.c3
Normal file
@@ -0,0 +1,46 @@
|
||||
define Callback = func int(char c);
|
||||
struct Person {}
|
||||
struct Company {}
|
||||
enum Status : int
|
||||
{
|
||||
IDLE,
|
||||
BUSY,
|
||||
DONE,
|
||||
}
|
||||
|
||||
struct MyData
|
||||
{
|
||||
char* name;
|
||||
Callback open;
|
||||
Callback close;
|
||||
//Status status;
|
||||
|
||||
// named sub-structs (x.other.value)
|
||||
struct other
|
||||
{
|
||||
int value;
|
||||
int status; // ok, no name clash with other status
|
||||
}
|
||||
|
||||
// anonymous sub-structs (x.value)
|
||||
struct
|
||||
{
|
||||
int value;
|
||||
int status; // error, name clash with other status in MyData
|
||||
}
|
||||
|
||||
// anonymous union (x.person)
|
||||
union
|
||||
{
|
||||
Person* person;
|
||||
Company* company;
|
||||
}
|
||||
|
||||
// named sub-unions (x.either.this)
|
||||
union either
|
||||
{
|
||||
int this;
|
||||
bool or;
|
||||
char* that;
|
||||
}
|
||||
}
|
||||
@@ -33,12 +33,12 @@ 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 { i64, i8* }*
|
||||
%lo = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp, i32 0, i32 0
|
||||
%lo1 = load i64, i64* %lo, align 8
|
||||
%hi = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp, i32 0, i32 1
|
||||
%hi2 = load i8*, i8** %hi, align 8
|
||||
%6 = call i32 @sum_us(i64 %lo1, i8* %hi2)
|
||||
%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*
|
||||
@@ -50,25 +50,26 @@ func void test()
|
||||
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 { i64, i8* }*
|
||||
%lo5 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp4, i32 0, i32 0
|
||||
%lo6 = load i64, i64* %lo5, align 8
|
||||
%hi7 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp4, i32 0, i32 1
|
||||
%hi8 = load i8*, i8** %hi7, align 8
|
||||
%14 = call i32 @sum_us(i64 %lo6, i8* %hi8)
|
||||
%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 { i64, i8* }*
|
||||
%lo11 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp10, i32 0, i32 0
|
||||
%lo12 = load i64, i64* %lo11, align 8
|
||||
%hi13 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp10, i32 0, i32 1
|
||||
%hi14 = load i8*, i8** %hi13, align 8
|
||||
%17 = call i32 @sum_us(i64 %lo12, i8* %hi14)
|
||||
%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 { i64, i8* }*
|
||||
%lo17 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp16, i32 0, i32 0
|
||||
%lo18 = load i64, i64* %lo17, align 8
|
||||
%hi19 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp16, i32 0, i32 1
|
||||
%hi20 = load i8*, i8** %hi19, align 8
|
||||
%19 = call i32 @sum_us(i64 %lo18, i8* %hi20)
|
||||
%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)
|
||||
ret void
|
||||
|
||||
@@ -257,7 +257,7 @@ func Type getValue(Blob blob)
|
||||
%"int[]" = type { i32*, i64 }
|
||||
%Foo = type { i32, i32 }
|
||||
|
||||
define void @test.Foo2__printme(%Foo2* %0)
|
||||
define void @test.Foo2__printme(%Foo2* %0) #0 {
|
||||
entry:
|
||||
%foo = alloca %Foo2*, align 8
|
||||
store %Foo2* %0, %Foo2** %foo, align 8
|
||||
@@ -268,7 +268,7 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @test.Foo2__mutate(%Foo2* %0)
|
||||
define i32 @test.Foo2__mutate(%Foo2* %0) #0 {
|
||||
entry:
|
||||
%foo = alloca %Foo2*, align 8
|
||||
store %Foo2* %0, %Foo2** %foo, align 8
|
||||
@@ -281,15 +281,15 @@ entry:
|
||||
ret i32 %add
|
||||
}
|
||||
|
||||
declare i32 @printf(i8*, ...)
|
||||
declare i32 @printf(i8*, ...) #0
|
||||
|
||||
define void @test.helloWorld()
|
||||
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()
|
||||
define i32 @test.test_static() #0 {
|
||||
entry:
|
||||
%0 = load i32, i32* @test_static.x, align 4
|
||||
%add = add i32 %0, 1
|
||||
@@ -300,7 +300,8 @@ entry:
|
||||
ret i32 %3
|
||||
}
|
||||
|
||||
define i32 @test.helo(double %0, %Bobo* byval align 8 %1)
|
||||
define i32 @test.helo(double %0, %Bobo* byval align 8 %1) #0 {
|
||||
entry:
|
||||
%d = alloca double, align 8
|
||||
%b = alloca %Bobo, align 4
|
||||
%de = alloca [3 x i32], align 4
|
||||
@@ -322,7 +323,8 @@ define i32 @test.helo(double %0, %Bobo* byval align 8 %1)
|
||||
ret i32 1
|
||||
}
|
||||
|
||||
define i32 @test.test1(i32 %0, i32 %1)
|
||||
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,34 +338,39 @@ 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(i64, i8*)
|
||||
declare void @test_virtual3(i64, i8*) #0
|
||||
|
||||
declare void @test_virtual2(i8*, i8*)
|
||||
declare void @test_virtual2(i8*, i8*) #0
|
||||
|
||||
define i32 @test.sum_us(i64 %0, i8* %1)
|
||||
define i32 @test.sum_us(i8* %0, i64 %1) #0 {
|
||||
entry:
|
||||
%x = alloca %"int[]", align 8
|
||||
%sum = alloca i32, align 4
|
||||
%vararg = alloca %"int[]", align 8
|
||||
%tempaddr = alloca %"int[]", align 8
|
||||
%pair = bitcast %"int[]"* %x to { i64, i8* }*
|
||||
%lo = getelementptr inbounds { i64, i8* }, { i64, i8* }* %pair, i32 0, i32 0
|
||||
store i64 %0, i64* %lo, align 8
|
||||
%hi = getelementptr inbounds { i64, i8* }, { i64, i8* }* %pair, i32 0, i32 1
|
||||
store i8* %1, i8** %hi, 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
|
||||
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 %2, 0
|
||||
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
|
||||
@@ -381,12 +388,12 @@ define i32 @test.sum_us(i64 %0, i8* %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[]"* %tempaddr, align 8
|
||||
%casttemp = bitcast %"int[]"* %tempaddr to { i64, i8* }*
|
||||
%lo1 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp, i32 0, i32 0
|
||||
%lo2 = load i64, i64* %lo1, align 8
|
||||
%hi3 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp, i32 0, i32 1
|
||||
%hi4 = load i8*, i8** %hi3, align 8
|
||||
%13 = call i32 @test.sum_us(i64 %lo2, i8* %hi4)
|
||||
%casttemp = bitcast %"int[]"* %tempaddr 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
|
||||
@@ -394,19 +401,21 @@ define i32 @test.sum_us(i64 %0, i8* %1)
|
||||
ret i32 %14
|
||||
}
|
||||
|
||||
define i32 @test.sumd(i64 %0, i8* %1)
|
||||
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 { i64, i8* }*
|
||||
%lo = getelementptr inbounds { i64, i8* }, { i64, i8* }* %pair, i32 0, i32 0
|
||||
store i64 %0, i64* %lo, align 8
|
||||
%hi = getelementptr inbounds { i64, i8* }, { i64, i8* }* %pair, i32 0, i32 1
|
||||
store i8* %1, i8** %hi, 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
|
||||
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
|
||||
@@ -416,6 +425,7 @@ define i32 @test.sumd(i64 %0, i8* %1)
|
||||
%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
|
||||
@@ -427,15 +437,18 @@ define i32 @test.sumd(i64 %0, i8* %1)
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
define void @main()
|
||||
define void @main() #0 {
|
||||
entry:
|
||||
%list = alloca %LinkedList, align 8
|
||||
%i = alloca i32, align 4
|
||||
@@ -474,12 +487,14 @@ entry:
|
||||
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 = 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: ; preds = %for.cond
|
||||
%6 = load i32, i32* %i, align 4
|
||||
%7 = load i32, i32* %i, align 4
|
||||
%siuiext = zext i32 %7 to i64
|
||||
@@ -487,11 +502,13 @@ entry:
|
||||
%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: ; 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: ; 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
|
||||
@@ -503,17 +520,19 @@ entry:
|
||||
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: ; 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: ; preds = %for.cond2
|
||||
%16 = load i32, i32* %i1, align 4
|
||||
%17 = load i32, i32* %i1, align 4
|
||||
%siuiext6 = zext i32 %17 to i64
|
||||
@@ -521,11 +540,13 @@ entry:
|
||||
%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: ; 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: ; 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)
|
||||
@@ -558,12 +579,12 @@ entry:
|
||||
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 { i64, i8* }*
|
||||
%lo = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp, i32 0, i32 0
|
||||
%lo11 = load i64, i64* %lo, align 8
|
||||
%hi = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp, i32 0, i32 1
|
||||
%hi12 = load i8*, i8** %hi, align 8
|
||||
%41 = call i32 @test.sum_us(i64 %lo11, i8* %hi12)
|
||||
%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
|
||||
@@ -580,21 +601,21 @@ entry:
|
||||
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 { i64, i8* }*
|
||||
%lo16 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp15, i32 0, i32 0
|
||||
%lo17 = load i64, i64* %lo16, align 8
|
||||
%hi18 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp15, i32 0, i32 1
|
||||
%hi19 = load i8*, i8** %hi18, align 8
|
||||
%52 = call i32 @test.sum_us(i64 %lo17, i8* %hi19)
|
||||
%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 { i64, i8* }*
|
||||
%lo22 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp21, i32 0, i32 0
|
||||
%lo23 = load i64, i64* %lo22, align 8
|
||||
%hi24 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp21, i32 0, i32 1
|
||||
%hi25 = load i8*, i8** %hi24, align 8
|
||||
%56 = call i32 @test.sum_us(i64 %lo23, i8* %hi25)
|
||||
%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
|
||||
@@ -609,12 +630,12 @@ entry:
|
||||
%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 { i64, i8* }*
|
||||
%lo28 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp27, i32 0, i32 0
|
||||
%lo29 = load i64, i64* %lo28, align 8
|
||||
%hi30 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp27, i32 0, i32 1
|
||||
%hi31 = load i8*, i8** %hi30, align 8
|
||||
%65 = call i32 @test.sum_us(i64 %lo29, i8* %hi31)
|
||||
%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
|
||||
@@ -623,28 +644,27 @@ entry:
|
||||
%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 { i64, i8* }*
|
||||
%lo35 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp34, i32 0, i32 0
|
||||
%lo36 = load i64, i64* %lo35, align 8
|
||||
%hi37 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp34, i32 0, i32 1
|
||||
%hi38 = load i8*, i8** %hi37, align 8
|
||||
%71 = call i32 @test.sum_us(i64 %lo36, i8* %hi38)
|
||||
%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 { i64, i8* }*
|
||||
%lo41 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp40, i32 0, i32 0
|
||||
%lo42 = load i64, i64* %lo41, align 8
|
||||
%hi43 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %casttemp40, i32 0, i32 1
|
||||
%hi44 = load i8*, i8** %hi43, align 8
|
||||
%74 = call i32 @test.sum_us(i64 %lo42, i8* %hi44)
|
||||
%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)
|
||||
store i32 (double, %Bobo*)* null, i32 (double, %Bobo*)** %a1, align 8
|
||||
store i32 (double, %Bobo*)* null, i32 (double, %Bobo*)** %b2, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
// #expect: hello_world.ll
|
||||
|
||||
define void @hello_world.hello()
|
||||
|
||||
@@ -134,3 +134,27 @@ func void test_missing_no_cases(Baz x)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
errtype MathError
|
||||
{
|
||||
DIVISION_BY_ZERO
|
||||
}
|
||||
|
||||
// Rethrowing an error uses "!!" suffix
|
||||
func void! testMayError()
|
||||
{
|
||||
}
|
||||
|
||||
func void main()
|
||||
{
|
||||
// Handle the error
|
||||
switch (catch err = testMayError()) // #error: Catch unwrapping is only allowed
|
||||
{
|
||||
case MathError.DIVISION_BY_ZERO:
|
||||
io::printf("Division by zero\n");
|
||||
return;
|
||||
default:
|
||||
io::printf("Unexpected error!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user