diff --git a/lib/std/core/mem_allocator.c3 b/lib/std/core/mem_allocator.c3 index f1cf06600..1e74f5a3c 100644 --- a/lib/std/core/mem_allocator.c3 +++ b/lib/std/core/mem_allocator.c3 @@ -208,14 +208,14 @@ fn void DynamicArenaAllocator.destroy(DynamicArenaAllocator* this) while (page) { DynamicArenaPage* next_page = page.prev_arena; - this.backing_allocator.free(page); + this.backing_allocator.free(page)!!; page = next_page; } page = this.unused_page; while (page) { DynamicArenaPage* next_page = page.prev_arena; - this.backing_allocator.free(page); + this.backing_allocator.free(page)!!; page = next_page; } this.page = null; @@ -297,7 +297,7 @@ private fn void*! DynamicArenaAllocator.alloc_new(DynamicArenaAllocator* this, u DynamicArenaPage*! page = this.backing_allocator.alloc(DynamicArenaPage.sizeof); if (catch err = page) { - this.backing_allocator.free(mem); + this.backing_allocator.free(mem)?; return err!; } page.memory = mem; diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index dc84186c5..a29e45130 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -196,7 +196,7 @@ fn void String.destroy(String* str) if (!*str) return; StringData* data = str.data(); if (!data) return; - data.allocator.free(data); + data.allocator.free(data)!!; *str = (String)null; } diff --git a/lib/std/io_printf.c3 b/lib/std/io_printf.c3 index 918cb1e81..a3c20abae 100644 --- a/lib/std/io_printf.c3 +++ b/lib/std/io_printf.c3 @@ -542,7 +542,7 @@ private fn void! etoa(PrintParam* param, FloatType value) if (minwidth) { // output the exponential symbol - param.out(param.flags.uppercase ? 'E' : 'e'); + param.out(param.flags.uppercase ? 'E' : 'e')?; // output the exponent value param.flags = { .zeropad = true, .plus = true }; param.width = minwidth - 1; @@ -653,7 +653,7 @@ private fn NtoaType int_from_variant(variant arg, bool *is_neg) } -fn usize! printf(char[] format, args...) +fn usize! printf(char[] format, args...) @maydiscard { return vsnprintf(&out_putchar_fn, " ", format, args); } diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 758f087a8..e2e0e8252 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -458,6 +458,8 @@ typedef struct bool attr_noinline : 1; bool attr_extname : 1; bool attr_naked : 1; + bool attr_nodiscard : 1; + bool attr_maydiscard: 1; }; TypeInfoId type_parent; FunctionSignature function_signature; @@ -498,6 +500,8 @@ typedef struct struct { bool attr_noreturn : 1; + bool attr_nodiscard : 1; + bool attr_maydiscard : 1; }; TypeInfoId type_parent; // May be 0 TypeInfoId rtype; // May be 0 @@ -687,6 +691,7 @@ typedef struct bool is_builtin : 1; bool is_func_ref : 1; bool attr_pure : 1; + bool result_unused : 1; AstId body; union { @@ -808,16 +813,27 @@ typedef struct } ExprBodyExpansion; +typedef struct +{ + void *block_return_exit; + void *block_failable_exit; + void *block_error_var; + void *block_return_out; +} BlockExit; + typedef struct { AstId first_stmt; + BlockExit **block_exit_ref; } ExprFuncBlock; + typedef struct { AstId first_stmt; Expr **args; Decl **params; + BlockExit **block_exit; } ExprMacroBlock; @@ -982,6 +998,7 @@ typedef struct { Expr *expr; // May be NULL AstId cleanup; + BlockExit** block_exit_ref; // For block exits } AstReturnStmt; typedef struct @@ -1412,6 +1429,7 @@ typedef struct SemaContext_ uint32_t original_inline_line; Decl **yield_params; Ast *yield_body; + BlockExit** block_exit_ref; Type *expected_block_type; Ast **returns; // Reusable returns cache. diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 481818cf1..57363334d 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -701,6 +701,8 @@ typedef enum ATTRIBUTE_OPERATOR, ATTRIBUTE_PURE, ATTRIBUTE_REFLECT, + ATTRIBUTE_MAYDISCARD, + ATTRIBUTE_NODISCARD, ATTRIBUTE_NONE, NUMBER_OF_ATTRIBUTES = ATTRIBUTE_NONE, } AttributeType; diff --git a/src/compiler/linker.c b/src/compiler/linker.c index 09e50f2ff..b3525dc8d 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -65,6 +65,20 @@ static void linker_setup_windows(const char ***args_ref, LinkerType linker_type) { if (linker_type == LINKER_CC) return; //add_arg("/MACHINE:X64"); + switch (active_target.debug_info) + { + case DEBUG_INFO_NOT_SET: + break; + case DEBUG_INFO_NONE: + add_arg("/DEBUG:NONE"); + break; + case DEBUG_INFO_LINE_TABLES: + case DEBUG_INFO_FULL: + add_arg("/DEBUG:FULL"); + break; + default: + UNREACHABLE + } if (active_target.win.sdk) { add_arg(str_printf("/LIBPATH:%s", active_target.win.sdk)); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index cb11dab1e..e3664beb5 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -4943,7 +4943,7 @@ static inline void gencontext_emit_expression_list_expr(GenContext *context, BEV } } -static inline void llvm_emit_return_block(GenContext *context, BEValue *be_value, Type *type, AstId current) +static inline void llvm_emit_return_block(GenContext *context, BEValue *be_value, Type *type, AstId current, BlockExit **block_exit) { // First case - an empty block if (!current) @@ -4954,25 +4954,26 @@ static inline void llvm_emit_return_block(GenContext *context, BEValue *be_value Type *type_lowered = type_lowering(type); LLVMValueRef old_ret_out = context->return_out; - LLVMBasicBlockRef saved_block_return_exit = context->block_return_exit; - LLVMBasicBlockRef saved_block_failable_exit = context->block_failable_exit; - LLVMValueRef saved_block_error = context->block_error_var; context->in_block++; - LLVMBasicBlockRef expr_block = llvm_basic_block_new(context, "expr_block.exit"); - context->block_return_exit = expr_block; - - LLVMValueRef return_out = NULL; LLVMValueRef error_out = context->error_var; LLVMBasicBlockRef error_block = context->catch_block; + LLVMValueRef return_out = NULL; + LLVMBasicBlockRef expr_block = llvm_basic_block_new(context, "expr_block.exit"); + + BlockExit exit = { + .block_return_exit = expr_block, + .block_failable_exit = error_block, + .block_error_var = error_out, + .block_return_out = NULL, + }; + + *block_exit= &exit; if (type_no_fail(type_lowered) != type_void) { - return_out = llvm_emit_alloca_aligned(context, type_lowered, "blockret"); + exit.block_return_out = llvm_emit_alloca_aligned(context, type_lowered, "blockret"); } - context->block_error_var = error_out; - context->block_failable_exit = error_block; - context->return_out = return_out; context->error_var = NULL; context->catch_block = NULL; @@ -5013,7 +5014,7 @@ static inline void llvm_emit_return_block(GenContext *context, BEValue *be_value // Optimization, emit directly to value llvm_emit_expr(context, be_value, ret_expr); // And remove the alloca - LLVMInstructionEraseFromParent(context->return_out); + LLVMInstructionEraseFromParent(exit.block_return_out); goto DONE; } while (0); @@ -5034,9 +5035,9 @@ static inline void llvm_emit_return_block(GenContext *context, BEValue *be_value // Emit the exit block. llvm_emit_block(context, expr_block); - if (return_out) + if (exit.block_return_out) { - llvm_value_set_address_abi_aligned(be_value, return_out, type_lowered); + llvm_value_set_address_abi_aligned(be_value, exit.block_return_out, type_lowered); } else { @@ -5047,16 +5048,13 @@ DONE: context->return_out = old_ret_out; context->catch_block = error_block; context->error_var = error_out; - context->block_return_exit = saved_block_return_exit; - context->block_failable_exit = saved_block_failable_exit; - context->block_error_var = saved_block_error; context->in_block--; } static inline void llvm_emit_expr_block(GenContext *context, BEValue *be_value, Expr *expr) { - llvm_emit_return_block(context, be_value, expr->type, expr->expr_block.first_stmt); + llvm_emit_return_block(context, be_value, expr->type, expr->expr_block.first_stmt, expr->expr_block.block_exit_ref); } static inline void llvm_emit_macro_block(GenContext *context, BEValue *be_value, Expr *expr) @@ -5098,7 +5096,8 @@ static inline void llvm_emit_macro_block(GenContext *context, BEValue *be_value, llvm_emit_expr(context, &value, expr->macro_block.args[i]); llvm_store_decl_raw(context, decl, llvm_load_value_store(context, &value)); } - llvm_emit_return_block(context, be_value, expr->type, expr->macro_block.first_stmt); + + llvm_emit_return_block(context, be_value, expr->type, expr->macro_block.first_stmt, expr->macro_block.block_exit); } LLVMValueRef llvm_emit_call_intrinsic(GenContext *context, unsigned intrinsic, LLVMTypeRef *types, unsigned type_count, diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 94b717e55..0c10112a5 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -437,7 +437,6 @@ void llvm_emit_function_body(GenContext *c, Decl *decl) LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(c->context, c->function, "entry"); c->current_block = entry; c->current_block_is_target = true; - c->block_return_exit = NULL; c->in_block = 0; c->builder = LLVMCreateBuilderInContext(c->context); LLVMPositionBuilderAtEnd(c->builder, entry); diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 16748e011..0a9c30849 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -99,9 +99,6 @@ typedef struct Module *code_module; LLVMValueRef return_out; LLVMValueRef failable_out; - LLVMBasicBlockRef block_return_exit; - LLVMBasicBlockRef block_failable_exit; - LLVMValueRef block_error_var; BEValue retval; int in_block; bool current_block_is_target : 1; diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index 8ff8f3429..0e9a220ea 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -228,8 +228,9 @@ static inline void llvm_emit_block_exit_return(GenContext *c, Ast *ast) LLVMBasicBlockRef error_return_block = NULL; LLVMValueRef error_out = NULL; - c->error_var = c->block_error_var; - c->catch_block = c->block_failable_exit; + BlockExit *exit = *ast->return_stmt.block_exit_ref; + c->error_var = exit->block_error_var; + c->catch_block = exit->block_failable_exit; LLVMBasicBlockRef err_cleanup_block = NULL; Expr *ret_expr = ast->return_stmt.expr; @@ -250,21 +251,21 @@ static inline void llvm_emit_block_exit_return(GenContext *c, Ast *ast) POP_ERROR(); llvm_emit_statement_chain(c, ast->return_stmt.cleanup); - if (c->return_out && return_value.value) + if (exit->block_return_out && return_value.value) { - llvm_store_value_aligned(c, c->return_out, &return_value, type_alloca_alignment(return_value.type)); + llvm_store_value_aligned(c, exit->block_return_out, &return_value, type_alloca_alignment(return_value.type)); } if (err_cleanup_block) { - llvm_emit_br(c, c->block_return_exit); + llvm_emit_br(c, exit->block_return_exit); llvm_emit_block(c, err_cleanup_block); llvm_emit_statement_chain(c, ast->return_stmt.cleanup); - llvm_emit_jmp(c, c->block_failable_exit); + llvm_emit_jmp(c, exit->block_failable_exit); } else { - llvm_emit_jmp(c, c->block_return_exit); + llvm_emit_jmp(c, exit->block_return_exit); } } diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index bc358750a..5d4ae0054 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1163,6 +1163,8 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, ATTR_MEMBER, [ATTRIBUTE_INLINE] = ATTR_FUNC | ATTR_CALL, [ATTRIBUTE_NOINLINE] = ATTR_FUNC | ATTR_CALL, + [ATTRIBUTE_NODISCARD] = ATTR_FUNC | ATTR_MACRO, + [ATTRIBUTE_MAYDISCARD] = ATTR_FUNC | ATTR_MACRO, [ATTRIBUTE_BIGENDIAN] = ATTR_BITSTRUCT, [ATTRIBUTE_LITTLEENDIAN] = ATTR_BITSTRUCT, [ATTRIBUTE_USED] = (AttributeDomain)~ATTR_CALL, @@ -1340,6 +1342,22 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, decl->func_decl.attr_noinline = true; decl->func_decl.attr_inline = false; break; + case ATTRIBUTE_NODISCARD: + if (domain == ATTR_MACRO) + { + decl->macro_decl.attr_nodiscard = true; + break; + } + decl->func_decl.attr_nodiscard = true; + break; + case ATTRIBUTE_MAYDISCARD: + if (domain == ATTR_MACRO) + { + decl->macro_decl.attr_maydiscard = true; + break; + } + decl->func_decl.attr_maydiscard = true; + break; case ATTRIBUTE_INLINE: decl->func_decl.attr_inline = true; decl->func_decl.attr_noinline = false; @@ -1689,9 +1707,27 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl) if (!sema_analyse_attributes(context, decl, decl->attributes, ATTR_FUNC)) return decl_poison(decl); Type *func_type = sema_analyse_function_signature(context, decl->func_decl.function_signature.abi, &decl->func_decl.function_signature, true); - decl->type = func_type; if (!func_type) return decl_poison(decl); + TypeInfo *rtype_info = type_infoptr(decl->func_decl.function_signature.returntype); + assert(rtype_info); + Type *rtype = rtype_info->type->canonical; + if (decl->func_decl.attr_nodiscard) + { + if (rtype == type_void) + { + SEMA_ERROR(rtype_info, "@nodiscard cannot be used on functions returning 'void'."); + return decl_poison(decl); + } + } + if (decl->func_decl.attr_maydiscard) + { + if (!type_is_failable(rtype)) + { + SEMA_ERROR(rtype_info, "@maydiscard can only be used on functions returning optional values."); + return decl_poison(decl); + } + } if (decl->func_decl.type_parent) { if (!sema_analyse_method(context, decl)) return decl_poison(decl); @@ -1749,9 +1785,28 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) if (!sema_analyse_attributes(context, decl, decl->attributes, ATTR_MACRO)) return decl_poison(decl); - - TypeInfo *rtype = type_infoptr(decl->macro_decl.rtype); - if (decl->macro_decl.rtype && !sema_resolve_type_info(context, rtype)) return decl_poison(decl); + if (decl->macro_decl.rtype) + { + TypeInfo *rtype_info = type_infoptr(decl->macro_decl.rtype); + if (!sema_resolve_type_info(context, rtype_info)) return decl_poison(decl); + Type *rtype = rtype_info->type; + if (decl->macro_decl.attr_nodiscard) + { + if (rtype == type_void) + { + SEMA_ERROR(rtype_info, "@nodiscard cannot be used on macros returning 'void'."); + return decl_poison(decl); + } + } + if (decl->macro_decl.attr_maydiscard) + { + if (!type_is_failable(rtype)) + { + SEMA_ERROR(rtype_info, "@maydiscard can only be used on macros returning optional values."); + return decl_poison(decl); + } + } + } decl->macro_decl.unit = context->unit; Decl **parameters = decl->macro_decl.parameters; unsigned param_count = vec_size(parameters); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 20d0eaa0e..15116cff5 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1611,10 +1611,26 @@ static inline bool sema_expr_analyse_func_invocation(SemaContext *context, Funct SEMA_ERROR(expr, "Only '@pure' functions may be called, you can override this with an attribute."); return false; } + + bool is_unused = expr->call_expr.result_unused; if (!sema_expr_analyse_call_invocation(context, expr, callee, &failable)) return false; Type *rtype = prototype->rtype; + if (is_unused && rtype != type_void && decl && decl->decl_kind == DECL_FUNC) + { + if (decl->func_decl.attr_nodiscard) + { + SEMA_ERROR(expr, "The result of the function must be used."); + return false; + } + if (type_is_failable(rtype) && !decl->func_decl.attr_maydiscard) + { + SEMA_ERROR(expr, "The optional result of the macro must be used."); + return false; + } + } + expr->type = type_get_opt_fail(rtype, failable); return true; @@ -1882,6 +1898,9 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s macro_context.yield_context = context; macro_context.original_inline_line = context->original_inline_line ? context->original_inline_line : call_expr->span.row; + BlockExit** block_exit_ref = MALLOCS(BlockExit*); + macro_context.block_exit_ref = block_exit_ref; + VECEACH(params, i) { Decl *param = params[i]; @@ -1944,7 +1963,32 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s if (!sum_returns) return SCOPE_POP_ERROR(); call_expr->type = type_get_opt_fail(sum_returns, failable); } - if (vec_size(macro_context.returns) == 1) + + if (call_expr->call_expr.result_unused) + { + Type *type = call_expr->type; + if (type != type_void) + { + if (decl->macro_decl.attr_nodiscard) + { + SEMA_ERROR(call_expr, "The result of the macro must be used."); + return SCOPE_POP_ERROR(); + } + if (type_is_failable(type) && !decl->macro_decl.attr_maydiscard) + { + SEMA_ERROR(call_expr, "The optional result of the macro must be used."); + return SCOPE_POP_ERROR(); + } + } + } + unsigned returns_found = vec_size(macro_context.returns); + // We may have zero normal macro returns but the active scope still has a "jump end". + // In this case it is triggered by the @body() + if (!returns_found && macro_context.active_scope.jump_end) + { + is_no_return = true; + } + if (returns_found == 1) { Ast *ret = macro_context.returns[0]; Expr *result = ret ? ret->return_stmt.expr : NULL; @@ -1962,6 +2006,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s call_expr->macro_block.first_stmt = body->compound_stmt.first_stmt; call_expr->macro_block.params = params; call_expr->macro_block.args = args; + call_expr->macro_block.block_exit = block_exit_ref; EXIT: assert(context->active_scope.defer_last == context->active_scope.defer_start); context->active_scope = old_scope; @@ -2107,7 +2152,6 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call) SemaContext *context = macro_context->yield_context; Decl **params = macro_context->yield_params; - Expr *func_expr = exprptr(call_expr->function); assert(func_expr->expr_kind == EXPR_MACRO_BODY_EXPANSION); expr_replace(call, func_expr); @@ -2115,6 +2159,7 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call) call->body_expansion_expr.declarations = macro_context->yield_params; AstId last_defer = context->active_scope.defer_last; bool success; + bool ends_in_jump; SCOPE_START if (macro_defer) @@ -2133,15 +2178,20 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call) Decl *param = params[i]; if (!sema_add_local(context, param)) return SCOPE_POP_ERROR(); } - call->body_expansion_expr.ast = ast_macro_copy(macro_context->yield_body); - success = sema_analyse_statement(context, call->body_expansion_expr.ast); - + Ast *ast = call->body_expansion_expr.ast = ast_macro_copy(macro_context->yield_body); + success = sema_analyse_statement(context, ast); + assert(ast->ast_kind == AST_COMPOUND_STMT); + if (context->active_scope.jump_end) + { + macro_context->active_scope.jump_end = true; + } if (first_defer) { first_defer->defer_stmt.prev_defer = 0; context->active_scope.defer_last = last_defer; } SCOPE_END; + return success; } @@ -3473,6 +3523,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr) if (parent->expr_kind != EXPR_TYPEINFO) { SEMA_ERROR(expr, "'typeid' can only be used with types, not values"); + return false; } expr->type = type_typeid; @@ -6439,6 +6490,10 @@ static inline bool sema_expr_analyse_expr_block(SemaContext *context, Type *infe Ast **saved_returns = context_push_returns(context); Type *stored_block_type = context->expected_block_type; context->expected_block_type = infer_type; + BlockExit **ref = MALLOCS(BlockExit*); + BlockExit **stored_block_exit = context->block_exit_ref; + context->block_exit_ref = ref; + expr->expr_block.block_exit_ref = ref; SCOPE_START_WITH_FLAGS(SCOPE_EXPR_BLOCK) context->block_return_defer = context->active_scope.defer_last; @@ -6487,6 +6542,7 @@ static inline bool sema_expr_analyse_expr_block(SemaContext *context, Type *infe context_pop_defers(context, &stmt->next); SCOPE_END; context->expected_block_type = stored_block_type; + context->block_exit_ref = stored_block_exit; context_pop_returns(context, saved_returns); return success; diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 6bca77186..7fb1ae248 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -126,6 +126,7 @@ static inline bool sema_analyse_block_exit_stmt(SemaContext *context, Ast *state return false; } } + statement->return_stmt.block_exit_ref = context->block_exit_ref; statement->return_stmt.cleanup = context_get_defers(context, context->active_scope.defer_last, context->block_return_defer); vec_add(context->returns, statement); return true; @@ -706,10 +707,28 @@ static inline bool sema_analyse_declare_stmt(SemaContext *context, Ast *statemen return sema_analyse_var_decl(context, statement->declare_stmt, true); } +static inline bool expr_is_assign(Expr *expr) +{ + switch (expr->expr_kind) + { + case EXPR_DECL: + case EXPR_BITASSIGN: + case EXPR_SLICE_ASSIGN: + return true; + case EXPR_BINARY: + return expr->binary_expr.operator >= BINARYOP_ASSIGN; + default: + return false; + } +} static inline bool sema_analyse_expr_stmt(SemaContext *context, Ast *statement) { - if (!sema_analyse_expr(context, statement->expr_stmt)) return false; - return true; + Expr *expr = statement->expr_stmt; + if (expr->expr_kind == EXPR_CALL) + { + expr->call_expr.result_unused = true; + } + return sema_analyse_expr(context, expr); } bool sema_analyse_defer_stmt_body(SemaContext *context, Ast *statement, Ast *body) diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 42169523b..5ea6f222c 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -230,6 +230,8 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_PURE] = kw_at_pure; attribute_list[ATTRIBUTE_REFLECT] = KW_DEF("@reflect"); attribute_list[ATTRIBUTE_AUTOIMPORT] = KW_DEF("@autoimport"); + attribute_list[ATTRIBUTE_MAYDISCARD] = KW_DEF("@maydiscard"); + attribute_list[ATTRIBUTE_NODISCARD] = KW_DEF("@nodiscard"); for (unsigned i = 0; i < NUMBER_OF_ATTRIBUTES; i++) { diff --git a/src/compiler/types.c b/src/compiler/types.c index 8a569d694..40d267c98 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -1501,6 +1501,14 @@ Type *type_find_max_type(Type *type, Type *other) { return other; } + if (other->type_kind == TYPE_POINTER) + { + Type *other_pointer = other->pointer; + if (other_pointer->type_kind == TYPE_ARRAY && other_pointer->array.base->canonical == array_base) + { + return type_get_subarray(array_base); + } + } } if (type->pointer->type_kind == TYPE_VECTOR) { diff --git a/test/test_suite/errors/error_regression_2.c3t b/test/test_suite/errors/error_regression_2.c3t index 519ff784b..2a92d18af 100644 --- a/test/test_suite/errors/error_regression_2.c3t +++ b/test/test_suite/errors/error_regression_2.c3t @@ -17,7 +17,7 @@ fn void Summary.print(Summary *s, CFile out) // We don't have a native printf in C3 yet, so use libc, // which is not all that nice for the strings but... char[] title = s.title ? *s.title : "missing"; - libc::fprintf(out, "Summary({ .title = %.*s, .ok = %s})", (int)title.len, title.ptr, s.ok ? "true" : "false"); + libc::fprintf(out, "Summary({ .title = %.*s, .ok = %s})", (int)title.len, title.ptr, s.ok ? (char*)"true" : (char*)"false"); } fn bool contains(char[] haystack, char[] needle) @@ -144,7 +144,7 @@ fn void main() bool! has_title = readWhetherTitleNonEmpty(url); // This looks a bit less than elegant, but as you see it's mostly due to having to // use printf here. - libc::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? nameFromError(catch(has_title)), (has_title ?? false) ? "true" : "false"); + libc::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? nameFromError(catch(has_title)), (has_title ?? false) ? (char*)"true" : (char*)"false"); } } @@ -757,8 +757,9 @@ err_retblock: ; preds = %error3, %error define i8* @test.bool_to_string(i8 zeroext %0) #0 { entry: %1 = trunc i8 %0 to i1 - %ternary = select i1 %1, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.7, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.8, i32 0, i32 0) - ret i8* %ternary + %ternary = select i1 %1, %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.7, i32 0, i32 0), i64 4 }, %"char[]" { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.8, i32 0, i32 0), i64 5 } + %2 = extractvalue %"char[]" %ternary, 0 + ret i8* %2 } ; Function Attrs: nounwind diff --git a/test/test_suite/errors/failable_inits.c3t b/test/test_suite/errors/failable_inits.c3t index c531dd197..5007d1e99 100644 --- a/test/test_suite/errors/failable_inits.c3t +++ b/test/test_suite/errors/failable_inits.c3t @@ -13,13 +13,13 @@ struct Bar int x; } -fn void! test1() +fn void! test1() @maydiscard { Bar! x = Foo.MY_VAL1!; Bar y = x?; } -fn void! test2() +fn void! test2() @maydiscard { Bar! x = {}; Bar y = x?; diff --git a/test/test_suite/macros/macro_body_defer.c3t b/test/test_suite/macros/macro_body_defer.c3t index 8d0d26311..0da402404 100644 --- a/test/test_suite/macros/macro_body_defer.c3t +++ b/test/test_suite/macros/macro_body_defer.c3t @@ -87,17 +87,17 @@ loop.exit: ; preds = %loop.body br label %loop.body2 loop.body2: ; preds = %loop.exit - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.13, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.10, i32 0, i32 0)) store i32 3, i32* %i3, align 4 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.14, i32 0, i32 0)) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.15, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.11, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.12, i32 0, i32 0)) %3 = load i32, i32* %i3, align 4 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.16, i32 0, i32 0), i32 %3) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.17, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.13, i32 0, i32 0), i32 %3) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.14, i32 0, i32 0)) ret i64 0 loop.exit4: ; No predecessors! - call void (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.21, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.15, i32 0, i32 0)) ret i64 0 } diff --git a/test/test_suite2/errors/error_regression_2.c3t b/test/test_suite2/errors/error_regression_2.c3t index e32f9245a..c237df358 100644 --- a/test/test_suite2/errors/error_regression_2.c3t +++ b/test/test_suite2/errors/error_regression_2.c3t @@ -17,7 +17,7 @@ fn void Summary.print(Summary *s, CFile out) // We don't have a native printf in C3 yet, so use libc, // which is not all that nice for the strings but... char[] title = s.title ? *s.title : "missing"; - libc::fprintf(out, "Summary({ .title = %.*s, .ok = %s})", (int)title.len, title.ptr, s.ok ? "true" : "false"); + libc::fprintf(out, "Summary({ .title = %.*s, .ok = %s})", (int)title.len, title.ptr, s.ok ? (char*)"true" : (char*)"false"); } fn bool contains(char[] haystack, char[] needle) @@ -144,757 +144,761 @@ fn void main() bool! has_title = readWhetherTitleNonEmpty(url); // This looks a bit less than elegant, but as you see it's mostly due to having to // use printf here. - libc::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? nameFromError(catch(has_title)), (has_title ?? false) ? "true" : "false"); + libc::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? nameFromError(catch(has_title)), (has_title ?? false) ? (char*)"true" : (char*)"false"); } } /* #expect: test.ll +; Function Attrs: nounwind define void @test.Summary__print(ptr %0, ptr %1) #0 { entry: - %title = alloca %"char[]", align 8 - %2 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 0 - %3 = load ptr, ptr %2, align 8 - %ptrbool = icmp ne ptr %3, null - br i1 %ptrbool, label %cond.lhs, label %cond.rhs + %title = alloca %"char[]", align 8 + %2 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 0 + %3 = load ptr, ptr %2, align 8 + %ptrbool = icmp ne ptr %3, null + br i1 %ptrbool, label %cond.lhs, label %cond.rhs cond.lhs: ; preds = %entry - %4 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 0 - %5 = load ptr, ptr %4, align 8 - %6 = load %"char[]", ptr %5, align 8 - br label %cond.phi + %4 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 0 + %5 = load ptr, ptr %4, align 8 + %6 = load %"char[]", ptr %5, align 8 + br label %cond.phi cond.rhs: ; preds = %entry - br label %cond.phi + br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi %"char[]" [ %6, %cond.lhs ], [ { ptr @.str.26, i64 7 }, %cond.rhs ] - store %"char[]" %val, ptr %title, align 8 - %7 = getelementptr inbounds %"char[]", ptr %title, i32 0, i32 1 - %8 = load i64, ptr %7, align 8 - %uisitrunc = trunc i64 %8 to i32 - %9 = getelementptr inbounds %"char[]", ptr %title, i32 0, i32 0 - %10 = load ptr, ptr %9, align 8 - %11 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 1 - %12 = load i8, ptr %11, align 8 - %13 = trunc i8 %12 to i1 - %ternary = select i1 %13, ptr @.str.28, ptr @.str.29 - %14 = call i32 (ptr, ptr, ...) @fprintf(ptr %1, ptr @.str.27, i32 %uisitrunc, ptr %10, ptr %ternary) - ret void + %val = phi %"char[]" [ %6, %cond.lhs ], [ { ptr @.str.26, i64 7 }, %cond.rhs ] + store %"char[]" %val, ptr %title, align 8 + %7 = getelementptr inbounds %"char[]", ptr %title, i32 0, i32 1 + %8 = load i64, ptr %7, align 8 + %uisitrunc = trunc i64 %8 to i32 + %9 = getelementptr inbounds %"char[]", ptr %title, i32 0, i32 0 + %10 = load ptr, ptr %9, align 8 + %11 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 1 + %12 = load i8, ptr %11, align 8 + %13 = trunc i8 %12 to i1 + %ternary = select i1 %13, ptr @.str.28, ptr @.str.29 + %14 = call i32 (ptr, ptr, ...) @fprintf(ptr %1, ptr @.str.27, i32 %uisitrunc, ptr %10, ptr %ternary) + ret void } +; Function Attrs: nounwind define zeroext i8 @test.contains(ptr %0, i64 %1, ptr %2, i64 %3) #0 { entry: - %haystack = alloca %"char[]", align 8 - %needle = alloca %"char[]", align 8 - %len = alloca i64, align 8 - %needle_len = alloca i64, align 8 - %i = alloca i64, align 8 - %4 = getelementptr inbounds { ptr, i64 }, ptr %haystack, i32 0, i32 0 - store ptr %0, ptr %4, align 8 - %5 = getelementptr inbounds { ptr, i64 }, ptr %haystack, i32 0, i32 1 - store i64 %1, ptr %5, align 8 - %6 = getelementptr inbounds { ptr, i64 }, ptr %needle, i32 0, i32 0 - store ptr %2, ptr %6, align 8 - %7 = getelementptr inbounds { ptr, i64 }, ptr %needle, i32 0, i32 1 - store i64 %3, ptr %7, align 8 - %8 = getelementptr inbounds %"char[]", ptr %haystack, i32 0, i32 1 - %9 = load i64, ptr %8, align 8 - store i64 %9, ptr %len, align 8 - %10 = getelementptr inbounds %"char[]", ptr %needle, i32 0, i32 1 - %11 = load i64, ptr %10, align 8 - store i64 %11, ptr %needle_len, align 8 - %12 = load i64, ptr %len, align 8 - %13 = load i64, ptr %needle_len, align 8 - %lt = icmp ult i64 %12, %13 - br i1 %lt, label %if.then, label %if.exit + %haystack = alloca %"char[]", align 8 + %needle = alloca %"char[]", align 8 + %len = alloca i64, align 8 + %needle_len = alloca i64, align 8 + %i = alloca i64, align 8 + %4 = getelementptr inbounds { ptr, i64 }, ptr %haystack, i32 0, i32 0 + store ptr %0, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %haystack, i32 0, i32 1 + store i64 %1, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %needle, i32 0, i32 0 + store ptr %2, ptr %6, align 8 + %7 = getelementptr inbounds { ptr, i64 }, ptr %needle, i32 0, i32 1 + store i64 %3, ptr %7, align 8 + %8 = getelementptr inbounds %"char[]", ptr %haystack, i32 0, i32 1 + %9 = load i64, ptr %8, align 8 + store i64 %9, ptr %len, align 8 + %10 = getelementptr inbounds %"char[]", ptr %needle, i32 0, i32 1 + %11 = load i64, ptr %10, align 8 + store i64 %11, ptr %needle_len, align 8 + %12 = load i64, ptr %len, align 8 + %13 = load i64, ptr %needle_len, align 8 + %lt = icmp ult i64 %12, %13 + br i1 %lt, label %if.then, label %if.exit if.then: ; preds = %entry - ret i8 0 + ret i8 0 if.exit: ; preds = %entry - %14 = load i64, ptr %needle_len, align 8 - %not = icmp eq i64 %14, 0 - br i1 %not, label %if.then1, label %if.exit2 + %14 = load i64, ptr %needle_len, align 8 + %not = icmp eq i64 %14, 0 + br i1 %not, label %if.then1, label %if.exit2 if.then1: ; preds = %if.exit - ret i8 1 + ret i8 1 if.exit2: ; preds = %if.exit - %15 = load i64, ptr %len, align 8 - %16 = load i64, ptr %needle_len, align 8 - %sub = sub i64 %16, 1 - %sub3 = sub i64 %15, %sub - store i64 %sub3, ptr %len, align 8 - store i64 0, ptr %i, align 8 - br label %loop.cond + %15 = load i64, ptr %len, align 8 + %16 = load i64, ptr %needle_len, align 8 + %sub = sub i64 %16, 1 + %sub3 = sub i64 %15, %sub + store i64 %sub3, ptr %len, align 8 + store i64 0, ptr %i, align 8 + br label %loop.cond loop.cond: ; preds = %if.exit6, %if.exit2 - %17 = load i64, ptr %i, align 8 - %18 = load i64, ptr %len, align 8 - %lt4 = icmp ult i64 %17, %18 - br i1 %lt4, label %loop.body, label %loop.exit + %17 = load i64, ptr %i, align 8 + %18 = load i64, ptr %len, align 8 + %lt4 = icmp ult i64 %17, %18 + br i1 %lt4, label %loop.body, label %loop.exit loop.body: ; preds = %loop.cond - %19 = getelementptr inbounds %"char[]", ptr %haystack, i32 0, i32 0 - %20 = load ptr, ptr %19, align 8 - %21 = load i64, ptr %i, align 8 - %ptroffset = getelementptr inbounds i8, ptr %20, i64 %21 - %22 = getelementptr inbounds %"char[]", ptr %needle, i32 0, i32 0 - %23 = load ptr, ptr %22, align 8 - %24 = load i64, ptr %needle_len, align 8 - %25 = call i32 @memcmp(ptr %ptroffset, ptr %23, i64 %24) - %eq = icmp eq i32 %25, 0 - br i1 %eq, label %if.then5, label %if.exit6 + %19 = getelementptr inbounds %"char[]", ptr %haystack, i32 0, i32 0 + %20 = load ptr, ptr %19, align 8 + %21 = load i64, ptr %i, align 8 + %ptroffset = getelementptr inbounds i8, ptr %20, i64 %21 + %22 = getelementptr inbounds %"char[]", ptr %needle, i32 0, i32 0 + %23 = load ptr, ptr %22, align 8 + %24 = load i64, ptr %needle_len, align 8 + %25 = call i32 @memcmp(ptr %ptroffset, ptr %23, i64 %24) + %eq = icmp eq i32 %25, 0 + br i1 %eq, label %if.then5, label %if.exit6 if.then5: ; preds = %loop.body - ret i8 1 + ret i8 1 if.exit6: ; preds = %loop.body - %26 = load i64, ptr %i, align 8 - %add = add i64 %26, 1 - store i64 %add, ptr %i, align 8 - br label %loop.cond + %26 = load i64, ptr %i, align 8 + %add = add i64 %26, 1 + store i64 %add, ptr %i, align 8 + br label %loop.cond loop.exit: ; preds = %loop.cond - ret i8 0 + ret i8 0 } +; Function Attrs: nounwind define i64 @test.readDoc(ptr %0, ptr %1, i64 %2) #0 { entry: - %url = alloca %"char[]", align 8 - %taddr = alloca %"char[]", align 8 - %taddr5 = alloca %"char[]", align 8 - %reterr = alloca i64, align 8 - %literal = alloca %Doc, align 8 - %taddr12 = alloca %"char[]", align 8 - %reterr16 = alloca i64, align 8 - %literal17 = alloca %Doc, align 8 - %error_var = alloca i64, align 8 - %value = alloca %Head, align 8 - %literal18 = alloca %Head, align 8 - %temp = alloca ptr, align 8 - %taddr24 = alloca %"char[]", align 8 - %reterr28 = alloca i64, align 8 - %literal29 = alloca %Doc, align 8 - %error_var30 = alloca i64, align 8 - %value31 = alloca %Head, align 8 - %literal32 = alloca %Head, align 8 - %error_var33 = alloca i64, align 8 - %value34 = alloca %"char[]", align 8 - %temp35 = alloca ptr, align 8 - %temp41 = alloca ptr, align 8 - %len = alloca i32, align 4 - %str = alloca ptr, align 8 - %reterr54 = alloca i64, align 8 - %literal55 = alloca %Doc, align 8 - %error_var56 = alloca i64, align 8 - %value57 = alloca %Head, align 8 - %literal58 = alloca %Head, align 8 - %error_var59 = alloca i64, align 8 - %value60 = alloca %"char[]", align 8 - %temp61 = alloca ptr, align 8 - %temp67 = alloca ptr, align 8 - %3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - store ptr %1, ptr %3, align 8 - %4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - store i64 %2, ptr %4, align 8 - %5 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - %lo = load ptr, ptr %5, align 8 - %6 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - %hi = load i64, ptr %6, align 8 - store %"char[]" { ptr @.str, i64 4 }, ptr %taddr, align 8 - %7 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 0 - %lo1 = load ptr, ptr %7, align 8 - %8 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 1 - %hi2 = load i64, ptr %8, align 8 - %9 = call i8 @test.contains(ptr %lo, i64 %hi, ptr %lo1, i64 %hi2) - %10 = trunc i8 %9 to i1 - br i1 %10, label %if.then, label %if.exit + %url = alloca %"char[]", align 8 + %taddr = alloca %"char[]", align 8 + %taddr5 = alloca %"char[]", align 8 + %reterr = alloca i64, align 8 + %literal = alloca %Doc, align 8 + %taddr12 = alloca %"char[]", align 8 + %reterr16 = alloca i64, align 8 + %literal17 = alloca %Doc, align 8 + %error_var = alloca i64, align 8 + %value = alloca %Head, align 8 + %literal18 = alloca %Head, align 8 + %temp = alloca ptr, align 8 + %taddr24 = alloca %"char[]", align 8 + %reterr28 = alloca i64, align 8 + %literal29 = alloca %Doc, align 8 + %error_var30 = alloca i64, align 8 + %value31 = alloca %Head, align 8 + %literal32 = alloca %Head, align 8 + %error_var33 = alloca i64, align 8 + %value34 = alloca %"char[]", align 8 + %temp35 = alloca ptr, align 8 + %temp41 = alloca ptr, align 8 + %len = alloca i32, align 4 + %str = alloca ptr, align 8 + %reterr54 = alloca i64, align 8 + %literal55 = alloca %Doc, align 8 + %error_var56 = alloca i64, align 8 + %value57 = alloca %Head, align 8 + %literal58 = alloca %Head, align 8 + %error_var59 = alloca i64, align 8 + %value60 = alloca %"char[]", align 8 + %temp61 = alloca ptr, align 8 + %temp67 = alloca ptr, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + store ptr %1, ptr %3, align 8 + %4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + store i64 %2, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo = load ptr, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi = load i64, ptr %6, align 8 + store %"char[]" { ptr @.str, i64 4 }, ptr %taddr, align 8 + %7 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 0 + %lo1 = load ptr, ptr %7, align 8 + %8 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 1 + %hi2 = load i64, ptr %8, align 8 + %9 = call i8 @test.contains(ptr %lo, i64 %hi, ptr %lo1, i64 %hi2) + %10 = trunc i8 %9 to i1 + br i1 %10, label %if.then, label %if.exit if.then: ; preds = %entry - ret i64 ptrtoint (ptr @test.ReadError.BAD_READ to i64) + ret i64 ptrtoint (ptr @test.ReadError.BAD_READ to i64) if.exit: ; preds = %entry - %11 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - %lo3 = load ptr, ptr %11, align 8 - %12 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - %hi4 = load i64, ptr %12, align 8 - store %"char[]" { ptr @.str.1, i64 12 }, ptr %taddr5, align 8 - %13 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 0 - %lo6 = load ptr, ptr %13, align 8 - %14 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 1 - %hi7 = load i64, ptr %14, align 8 - %15 = call i8 @test.contains(ptr %lo3, i64 %hi4, ptr %lo6, i64 %hi7) - %16 = trunc i8 %15 to i1 - br i1 %16, label %if.then8, label %if.exit9 + %11 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo3 = load ptr, ptr %11, align 8 + %12 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi4 = load i64, ptr %12, align 8 + store %"char[]" { ptr @.str.1, i64 12 }, ptr %taddr5, align 8 + %13 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 0 + %lo6 = load ptr, ptr %13, align 8 + %14 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 1 + %hi7 = load i64, ptr %14, align 8 + %15 = call i8 @test.contains(ptr %lo3, i64 %hi4, ptr %lo6, i64 %hi7) + %16 = trunc i8 %15 to i1 + br i1 %16, label %if.then8, label %if.exit9 if.then8: ; preds = %if.exit - %17 = getelementptr inbounds %Doc, ptr %literal, i32 0, i32 0 - store ptr null, ptr %17, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 8, i1 false) - ret i64 0 + %17 = getelementptr inbounds %Doc, ptr %literal, i32 0, i32 0 + store ptr null, ptr %17, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 8, i1 false) + ret i64 0 if.exit9: ; preds = %if.exit - %18 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - %lo10 = load ptr, ptr %18, align 8 - %19 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - %hi11 = load i64, ptr %19, align 8 - store %"char[]" { ptr @.str.2, i64 13 }, ptr %taddr12, align 8 - %20 = getelementptr inbounds { ptr, i64 }, ptr %taddr12, i32 0, i32 0 - %lo13 = load ptr, ptr %20, align 8 - %21 = getelementptr inbounds { ptr, i64 }, ptr %taddr12, i32 0, i32 1 - %hi14 = load i64, ptr %21, align 8 - %22 = call i8 @test.contains(ptr %lo10, i64 %hi11, ptr %lo13, i64 %hi14) - %23 = trunc i8 %22 to i1 - br i1 %23, label %if.then15, label %if.exit21 + %18 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo10 = load ptr, ptr %18, align 8 + %19 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi11 = load i64, ptr %19, align 8 + store %"char[]" { ptr @.str.2, i64 13 }, ptr %taddr12, align 8 + %20 = getelementptr inbounds { ptr, i64 }, ptr %taddr12, i32 0, i32 0 + %lo13 = load ptr, ptr %20, align 8 + %21 = getelementptr inbounds { ptr, i64 }, ptr %taddr12, i32 0, i32 1 + %hi14 = load i64, ptr %21, align 8 + %22 = call i8 @test.contains(ptr %lo10, i64 %hi11, ptr %lo13, i64 %hi14) + %23 = trunc i8 %22 to i1 + br i1 %23, label %if.then15, label %if.exit21 if.then15: ; preds = %if.exit9 - %24 = getelementptr inbounds %Doc, ptr %literal17, i32 0, i32 0 - %25 = getelementptr inbounds %Head, ptr %literal18, i32 0, i32 0 - store ptr null, ptr %25, align 8 - %26 = load %Head, ptr %literal18, align 8 - store %Head %26, ptr %value, align 8 - %27 = call ptr @"std::core::mem.alloc"(i64 8, i64 0) - store ptr %27, ptr %temp, align 8 - %28 = load ptr, ptr %temp, align 8 - %not = icmp eq ptr %28, null - br i1 %not, label %if.then19, label %if.exit20 + %24 = getelementptr inbounds %Doc, ptr %literal17, i32 0, i32 0 + %25 = getelementptr inbounds %Head, ptr %literal18, i32 0, i32 0 + store ptr null, ptr %25, align 8 + %26 = load %Head, ptr %literal18, align 8 + store %Head %26, ptr %value, align 8 + %27 = call ptr @"std::core::mem.alloc"(i64 8, i64 0) + store ptr %27, ptr %temp, align 8 + %28 = load ptr, ptr %temp, align 8 + %not = icmp eq ptr %28, null + br i1 %not, label %if.then19, label %if.exit20 if.then19: ; preds = %if.then15 - store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var, align 8 - br label %guard_block + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var, align 8 + br label %guard_block if.exit20: ; preds = %if.then15 - %29 = load ptr, ptr %temp, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %29, ptr align 8 %value, i32 8, i1 false) - br label %noerr_block + %29 = load ptr, ptr %temp, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %29, ptr align 8 %value, i32 8, i1 false) + br label %noerr_block guard_block: ; preds = %if.then19 - %30 = load i64, ptr %error_var, align 8 - ret i64 %30 + %30 = load i64, ptr %error_var, align 8 + ret i64 %30 noerr_block: ; preds = %if.exit20 - %31 = load ptr, ptr %temp, align 8 - store ptr %31, ptr %24, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal17, i32 8, i1 false) - ret i64 0 + %31 = load ptr, ptr %temp, align 8 + store ptr %31, ptr %24, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal17, i32 8, i1 false) + ret i64 0 if.exit21: ; preds = %if.exit9 - %32 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - %lo22 = load ptr, ptr %32, align 8 - %33 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - %hi23 = load i64, ptr %33, align 8 - store %"char[]" { ptr @.str.3, i64 11 }, ptr %taddr24, align 8 - %34 = getelementptr inbounds { ptr, i64 }, ptr %taddr24, i32 0, i32 0 - %lo25 = load ptr, ptr %34, align 8 - %35 = getelementptr inbounds { ptr, i64 }, ptr %taddr24, i32 0, i32 1 - %hi26 = load i64, ptr %35, align 8 - %36 = call i8 @test.contains(ptr %lo22, i64 %hi23, ptr %lo25, i64 %hi26) - %37 = trunc i8 %36 to i1 - br i1 %37, label %if.then27, label %if.exit47 + %32 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo22 = load ptr, ptr %32, align 8 + %33 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi23 = load i64, ptr %33, align 8 + store %"char[]" { ptr @.str.3, i64 11 }, ptr %taddr24, align 8 + %34 = getelementptr inbounds { ptr, i64 }, ptr %taddr24, i32 0, i32 0 + %lo25 = load ptr, ptr %34, align 8 + %35 = getelementptr inbounds { ptr, i64 }, ptr %taddr24, i32 0, i32 1 + %hi26 = load i64, ptr %35, align 8 + %36 = call i8 @test.contains(ptr %lo22, i64 %hi23, ptr %lo25, i64 %hi26) + %37 = trunc i8 %36 to i1 + br i1 %37, label %if.then27, label %if.exit47 if.then27: ; preds = %if.exit21 - %38 = getelementptr inbounds %Doc, ptr %literal29, i32 0, i32 0 - store ptr null, ptr %literal32, align 8 - %39 = getelementptr inbounds %Head, ptr %literal32, i32 0, i32 0 - store %"char[]" { ptr @.str.4, i64 0 }, ptr %value34, align 8 - %40 = call ptr @"std::core::mem.alloc"(i64 16, i64 0) - store ptr %40, ptr %temp35, align 8 - %41 = load ptr, ptr %temp35, align 8 - %not36 = icmp eq ptr %41, null - br i1 %not36, label %if.then37, label %if.exit38 + %38 = getelementptr inbounds %Doc, ptr %literal29, i32 0, i32 0 + store ptr null, ptr %literal32, align 8 + %39 = getelementptr inbounds %Head, ptr %literal32, i32 0, i32 0 + store %"char[]" { ptr @.str.4, i64 0 }, ptr %value34, align 8 + %40 = call ptr @"std::core::mem.alloc"(i64 16, i64 0) + store ptr %40, ptr %temp35, align 8 + %41 = load ptr, ptr %temp35, align 8 + %not36 = icmp eq ptr %41, null + br i1 %not36, label %if.then37, label %if.exit38 if.then37: ; preds = %if.then27 - store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var33, align 8 - br label %guard_block39 + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var33, align 8 + br label %guard_block39 if.exit38: ; preds = %if.then27 - %42 = load ptr, ptr %temp35, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %42, ptr align 8 %value34, i32 16, i1 false) - br label %noerr_block40 + %42 = load ptr, ptr %temp35, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %42, ptr align 8 %value34, i32 16, i1 false) + br label %noerr_block40 guard_block39: ; preds = %if.then37 - %43 = load i64, ptr %error_var33, align 8 - ret i64 %43 + %43 = load i64, ptr %error_var33, align 8 + ret i64 %43 noerr_block40: ; preds = %if.exit38 - %44 = load ptr, ptr %temp35, align 8 - store ptr %44, ptr %39, align 8 - %45 = load %Head, ptr %literal32, align 8 - store %Head %45, ptr %value31, align 8 - %46 = call ptr @"std::core::mem.alloc"(i64 8, i64 0) - store ptr %46, ptr %temp41, align 8 - %47 = load ptr, ptr %temp41, align 8 - %not42 = icmp eq ptr %47, null - br i1 %not42, label %if.then43, label %if.exit44 + %44 = load ptr, ptr %temp35, align 8 + store ptr %44, ptr %39, align 8 + %45 = load %Head, ptr %literal32, align 8 + store %Head %45, ptr %value31, align 8 + %46 = call ptr @"std::core::mem.alloc"(i64 8, i64 0) + store ptr %46, ptr %temp41, align 8 + %47 = load ptr, ptr %temp41, align 8 + %not42 = icmp eq ptr %47, null + br i1 %not42, label %if.then43, label %if.exit44 if.then43: ; preds = %noerr_block40 - store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var30, align 8 - br label %guard_block45 + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var30, align 8 + br label %guard_block45 if.exit44: ; preds = %noerr_block40 - %48 = load ptr, ptr %temp41, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %48, ptr align 8 %value31, i32 8, i1 false) - br label %noerr_block46 + %48 = load ptr, ptr %temp41, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %48, ptr align 8 %value31, i32 8, i1 false) + br label %noerr_block46 guard_block45: ; preds = %if.then43 - %49 = load i64, ptr %error_var30, align 8 - ret i64 %49 + %49 = load i64, ptr %error_var30, align 8 + ret i64 %49 noerr_block46: ; preds = %if.exit44 - %50 = load ptr, ptr %temp41, align 8 - store ptr %50, ptr %38, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal29, i32 8, i1 false) - ret i64 0 + %50 = load ptr, ptr %temp41, align 8 + store ptr %50, ptr %38, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal29, i32 8, i1 false) + ret i64 0 if.exit47: ; preds = %if.exit21 - %51 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1 - %52 = load i64, ptr %51, align 8 - %uisitrunc = trunc i64 %52 to i32 - %53 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 - %54 = load ptr, ptr %53, align 8 - %55 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.5, i32 %uisitrunc, ptr %54) - store i32 %55, ptr %len, align 4 - %56 = load i32, ptr %len, align 4 - %siuiext = sext i32 %56 to i64 - %add = add i64 %siuiext, 1 - %57 = call ptr @"std::core::mem.alloc"(i64 %add, i64 0) - store ptr %57, ptr %str, align 8 - %58 = load ptr, ptr %str, align 8 - %not48 = icmp eq ptr %58, null - br i1 %not48, label %if.then49, label %if.exit50 + %51 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1 + %52 = load i64, ptr %51, align 8 + %uisitrunc = trunc i64 %52 to i32 + %53 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 + %54 = load ptr, ptr %53, align 8 + %55 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.5, i32 %uisitrunc, ptr %54) + store i32 %55, ptr %len, align 4 + %56 = load i32, ptr %len, align 4 + %siuiext = sext i32 %56 to i64 + %add = add i64 %siuiext, 1 + %57 = call ptr @"std::core::mem.alloc"(i64 %add, i64 0) + store ptr %57, ptr %str, align 8 + %58 = load ptr, ptr %str, align 8 + %not48 = icmp eq ptr %58, null + br i1 %not48, label %if.then49, label %if.exit50 if.then49: ; preds = %if.exit47 - ret i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64) + ret i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64) if.exit50: ; preds = %if.exit47 - %59 = load ptr, ptr %str, align 8 - %60 = load i32, ptr %len, align 4 - %siuiext51 = sext i32 %60 to i64 - %add52 = add i64 %siuiext51, 1 - %61 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1 - %62 = load i64, ptr %61, align 8 - %uisitrunc53 = trunc i64 %62 to i32 - %63 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 - %64 = load ptr, ptr %63, align 8 - %65 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %59, i64 %add52, ptr @.str.6, i32 %uisitrunc53, ptr %64) - %66 = getelementptr inbounds %Doc, ptr %literal55, i32 0, i32 0 - store ptr null, ptr %literal58, align 8 - %67 = getelementptr inbounds %Head, ptr %literal58, i32 0, i32 0 - %68 = load ptr, ptr %str, align 8 - %69 = load i32, ptr %len, align 4 - %sub = sub i32 %69, 1 - %sisiext = sext i32 %sub to i64 - %70 = add i64 %sisiext, 1 - %size = sub i64 %70, 0 - %ptroffset = getelementptr inbounds i8, ptr %68, i64 0 - %71 = insertvalue %"char[]" undef, ptr %ptroffset, 0 - %72 = insertvalue %"char[]" %71, i64 %size, 1 - store %"char[]" %72, ptr %value60, align 8 - %73 = call ptr @"std::core::mem.alloc"(i64 16, i64 0) - store ptr %73, ptr %temp61, align 8 - %74 = load ptr, ptr %temp61, align 8 - %not62 = icmp eq ptr %74, null - br i1 %not62, label %if.then63, label %if.exit64 + %59 = load ptr, ptr %str, align 8 + %60 = load i32, ptr %len, align 4 + %siuiext51 = sext i32 %60 to i64 + %add52 = add i64 %siuiext51, 1 + %61 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1 + %62 = load i64, ptr %61, align 8 + %uisitrunc53 = trunc i64 %62 to i32 + %63 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 + %64 = load ptr, ptr %63, align 8 + %65 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %59, i64 %add52, ptr @.str.6, i32 %uisitrunc53, ptr %64) + %66 = getelementptr inbounds %Doc, ptr %literal55, i32 0, i32 0 + store ptr null, ptr %literal58, align 8 + %67 = getelementptr inbounds %Head, ptr %literal58, i32 0, i32 0 + %68 = load ptr, ptr %str, align 8 + %69 = load i32, ptr %len, align 4 + %sub = sub i32 %69, 1 + %sisiext = sext i32 %sub to i64 + %70 = add i64 %sisiext, 1 + %size = sub i64 %70, 0 + %ptroffset = getelementptr inbounds i8, ptr %68, i64 0 + %71 = insertvalue %"char[]" undef, ptr %ptroffset, 0 + %72 = insertvalue %"char[]" %71, i64 %size, 1 + store %"char[]" %72, ptr %value60, align 8 + %73 = call ptr @"std::core::mem.alloc"(i64 16, i64 0) + store ptr %73, ptr %temp61, align 8 + %74 = load ptr, ptr %temp61, align 8 + %not62 = icmp eq ptr %74, null + br i1 %not62, label %if.then63, label %if.exit64 if.then63: ; preds = %if.exit50 - store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var59, align 8 - br label %guard_block65 + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var59, align 8 + br label %guard_block65 if.exit64: ; preds = %if.exit50 - %75 = load ptr, ptr %temp61, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %75, ptr align 8 %value60, i32 16, i1 false) - br label %noerr_block66 + %75 = load ptr, ptr %temp61, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %75, ptr align 8 %value60, i32 16, i1 false) + br label %noerr_block66 guard_block65: ; preds = %if.then63 - %76 = load i64, ptr %error_var59, align 8 - ret i64 %76 + %76 = load i64, ptr %error_var59, align 8 + ret i64 %76 noerr_block66: ; preds = %if.exit64 - %77 = load ptr, ptr %temp61, align 8 - store ptr %77, ptr %67, align 8 - %78 = load %Head, ptr %literal58, align 8 - store %Head %78, ptr %value57, align 8 - %79 = call ptr @"std::core::mem.alloc"(i64 8, i64 0) - store ptr %79, ptr %temp67, align 8 - %80 = load ptr, ptr %temp67, align 8 - %not68 = icmp eq ptr %80, null - br i1 %not68, label %if.then69, label %if.exit70 + %77 = load ptr, ptr %temp61, align 8 + store ptr %77, ptr %67, align 8 + %78 = load %Head, ptr %literal58, align 8 + store %Head %78, ptr %value57, align 8 + %79 = call ptr @"std::core::mem.alloc"(i64 8, i64 0) + store ptr %79, ptr %temp67, align 8 + %80 = load ptr, ptr %temp67, align 8 + %not68 = icmp eq ptr %80, null + br i1 %not68, label %if.then69, label %if.exit70 if.then69: ; preds = %noerr_block66 - store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var56, align 8 - br label %guard_block71 + store i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), ptr %error_var56, align 8 + br label %guard_block71 if.exit70: ; preds = %noerr_block66 - %81 = load ptr, ptr %temp67, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %81, ptr align 8 %value57, i32 8, i1 false) - br label %noerr_block72 + %81 = load ptr, ptr %temp67, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %81, ptr align 8 %value57, i32 8, i1 false) + br label %noerr_block72 guard_block71: ; preds = %if.then69 - %82 = load i64, ptr %error_var56, align 8 - ret i64 %82 + %82 = load i64, ptr %error_var56, align 8 + ret i64 %82 noerr_block72: ; preds = %if.exit70 - %83 = load ptr, ptr %temp67, align 8 - store ptr %83, ptr %66, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal55, i32 8, i1 false) - ret i64 0 + %83 = load ptr, ptr %temp67, align 8 + store ptr %83, ptr %66, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal55, i32 8, i1 false) + ret i64 0 } ; Function Attrs: nounwind define { ptr, i8 } @test.buildSummary(ptr %0) #0 { entry: - %doc = alloca %Doc, align 8 - %literal = alloca %Summary, align 8 - %tempcoerce = alloca { ptr, i8 }, align 8 - %1 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 - store ptr %0, ptr %1, align 8 - %2 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0 - store ptr null, ptr %2, align 8 - %3 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1 - store i8 0, ptr %3, align 8 - %4 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0 - %5 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 - %6 = load ptr, ptr %5, align 8 - %ptrbool = icmp ne ptr %6, null - br i1 %ptrbool, label %cond.lhs, label %cond.rhs + %doc = alloca %Doc, align 8 + %literal = alloca %Summary, align 8 + %tempcoerce = alloca { ptr, i8 }, align 8 + %1 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + store ptr %0, ptr %1, align 8 + %2 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0 + store ptr null, ptr %2, align 8 + %3 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1 + store i8 0, ptr %3, align 8 + %4 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0 + %5 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + %6 = load ptr, ptr %5, align 8 + %ptrbool = icmp ne ptr %6, null + br i1 %ptrbool, label %cond.lhs, label %cond.rhs cond.lhs: ; preds = %entry - %7 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 - %8 = load ptr, ptr %7, align 8 - %9 = getelementptr inbounds %Head, ptr %8, i32 0, i32 0 - %10 = load ptr, ptr %9, align 8 - br label %cond.phi + %7 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + %9 = getelementptr inbounds %Head, ptr %8, i32 0, i32 0 + %10 = load ptr, ptr %9, align 8 + br label %cond.phi cond.rhs: ; preds = %entry - br label %cond.phi + br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi ptr [ %10, %cond.lhs ], [ null, %cond.rhs ] - store ptr %val, ptr %4, align 8 - %11 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1 - store i8 1, ptr %11, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %literal, i32 16, i1 false) - %12 = load { ptr, i8 }, ptr %tempcoerce, align 8 - ret { ptr, i8 } %12 + %val = phi ptr [ %10, %cond.lhs ], [ null, %cond.rhs ] + store ptr %val, ptr %4, align 8 + %11 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1 + store i8 1, ptr %11, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %literal, i32 16, i1 false) + %12 = load { ptr, i8 }, ptr %tempcoerce, align 8 + ret { ptr, i8 } %12 } ; Function Attrs: nounwind define { ptr, i8 } @test.readAndBuildSummary(ptr %0, i64 %1) #0 { entry: - %url = alloca %"char[]", align 8 - %retparam = alloca %Doc, align 8 - %result = alloca %Summary, align 8 - %literal = alloca %Summary, align 8 - %taddr = alloca %Summary, align 8 - %tempcoerce = alloca { ptr, i8 }, align 8 - %2 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - store ptr %0, ptr %2, align 8 - %3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - store i64 %1, ptr %3, align 8 - %4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - %lo = load ptr, ptr %4, align 8 - %5 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - %hi = load i64, ptr %5, align 8 - %6 = call i64 @test.readDoc(ptr %retparam, ptr %lo, i64 %hi) - %not_err = icmp eq i64 %6, 0 - br i1 %not_err, label %after.errcheck, label %else_block + %url = alloca %"char[]", align 8 + %retparam = alloca %Doc, align 8 + %result = alloca %Summary, align 8 + %literal = alloca %Summary, align 8 + %taddr = alloca %Summary, align 8 + %tempcoerce = alloca { ptr, i8 }, align 8 + %2 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + store ptr %0, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + store i64 %1, ptr %3, align 8 + %4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo = load ptr, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi = load i64, ptr %5, align 8 + %6 = call i64 @test.readDoc(ptr %retparam, ptr %lo, i64 %hi) + %not_err = icmp eq i64 %6, 0 + br i1 %not_err, label %after.errcheck, label %else_block after.errcheck: ; preds = %entry - %7 = getelementptr inbounds %Doc, ptr %retparam, i32 0, i32 0 - %8 = load ptr, ptr %7, align 8 - %9 = call { ptr, i8 } @test.buildSummary(ptr %8) - store { ptr, i8 } %9, ptr %result, align 8 - %10 = load %Summary, ptr %result, align 8 - br label %phi_block + %7 = getelementptr inbounds %Doc, ptr %retparam, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + %9 = call { ptr, i8 } @test.buildSummary(ptr %8) + store { ptr, i8 } %9, ptr %result, align 8 + %10 = load %Summary, ptr %result, align 8 + br label %phi_block else_block: ; preds = %entry - %11 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0 - store ptr null, ptr %11, align 8 - %12 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1 - store i8 0, ptr %12, align 8 - %13 = load %Summary, ptr %literal, align 8 - br label %phi_block + %11 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0 + store ptr null, ptr %11, align 8 + %12 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1 + store i8 0, ptr %12, align 8 + %13 = load %Summary, ptr %literal, align 8 + br label %phi_block phi_block: ; preds = %else_block, %after.errcheck - %val = phi %Summary [ %10, %after.errcheck ], [ %13, %else_block ] - store %Summary %val, ptr %taddr, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %taddr, i32 16, i1 false) - %14 = load { ptr, i8 }, ptr %tempcoerce, align 8 - ret { ptr, i8 } %14 + %val = phi %Summary [ %10, %after.errcheck ], [ %13, %else_block ] + store %Summary %val, ptr %taddr, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %taddr, i32 16, i1 false) + %14 = load { ptr, i8 }, ptr %tempcoerce, align 8 + ret { ptr, i8 } %14 } ; Function Attrs: nounwind define i64 @test.isTitleNonEmpty(ptr %0, ptr %1) #0 { entry: - %doc = alloca %Doc, align 8 - %head = alloca ptr, align 8 - %reterr = alloca i64, align 8 - %2 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 - store ptr %1, ptr %2, align 8 - %3 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 - %4 = load ptr, ptr %3, align 8 - %not = icmp eq ptr %4, null - br i1 %not, label %if.then, label %if.exit + %doc = alloca %Doc, align 8 + %head = alloca ptr, align 8 + %reterr = alloca i64, align 8 + %2 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + store ptr %1, ptr %2, align 8 + %3 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + %4 = load ptr, ptr %3, align 8 + %not = icmp eq ptr %4, null + br i1 %not, label %if.then, label %if.exit if.then: ; preds = %entry - ret i64 ptrtoint (ptr @test.TitleResult.TITLE_MISSING to i64) + ret i64 ptrtoint (ptr @test.TitleResult.TITLE_MISSING to i64) if.exit: ; preds = %entry - %5 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 - %6 = load ptr, ptr %5, align 8 - %7 = getelementptr inbounds %Head, ptr %6, i32 0, i32 0 - %8 = load ptr, ptr %7, align 8 - store ptr %8, ptr %head, align 8 - %9 = load ptr, ptr %head, align 8 - %not1 = icmp eq ptr %9, null - br i1 %not1, label %if.then2, label %if.exit3 + %5 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0 + %6 = load ptr, ptr %5, align 8 + %7 = getelementptr inbounds %Head, ptr %6, i32 0, i32 0 + %8 = load ptr, ptr %7, align 8 + store ptr %8, ptr %head, align 8 + %9 = load ptr, ptr %head, align 8 + %not1 = icmp eq ptr %9, null + br i1 %not1, label %if.then2, label %if.exit3 if.then2: ; preds = %if.exit - ret i64 ptrtoint (ptr @test.TitleResult.TITLE_MISSING to i64) + ret i64 ptrtoint (ptr @test.TitleResult.TITLE_MISSING to i64) if.exit3: ; preds = %if.exit - %10 = load ptr, ptr %head, align 8 - %11 = getelementptr inbounds %"char[]", ptr %10, i32 0, i32 1 - %12 = load i64, ptr %11, align 8 - %lt = icmp ult i64 0, %12 - %13 = zext i1 %lt to i8 - store i8 %13, ptr %0, align 1 - ret i64 0 + %10 = load ptr, ptr %head, align 8 + %11 = getelementptr inbounds %"char[]", ptr %10, i32 0, i32 1 + %12 = load i64, ptr %11, align 8 + %lt = icmp ult i64 0, %12 + %13 = zext i1 %lt to i8 + store i8 %13, ptr %0, align 1 + ret i64 0 } ; Function Attrs: nounwind define i64 @test.readWhetherTitleNonEmpty(ptr %0, ptr %1, i64 %2) #0 { entry: - %url = alloca %"char[]", align 8 - %reterr = alloca i64, align 8 - %retparam = alloca i8, align 1 - %retparam1 = alloca %Doc, align 8 - %3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - store ptr %1, ptr %3, align 8 - %4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - store i64 %2, ptr %4, align 8 - %5 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - %lo = load ptr, ptr %5, align 8 - %6 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - %hi = load i64, ptr %6, align 8 - %7 = call i64 @test.readDoc(ptr %retparam1, ptr %lo, i64 %hi) - %not_err = icmp eq i64 %7, 0 - br i1 %not_err, label %after.errcheck, label %error + %url = alloca %"char[]", align 8 + %reterr = alloca i64, align 8 + %retparam = alloca i8, align 1 + %retparam1 = alloca %Doc, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + store ptr %1, ptr %3, align 8 + %4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + store i64 %2, ptr %4, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo = load ptr, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi = load i64, ptr %6, align 8 + %7 = call i64 @test.readDoc(ptr %retparam1, ptr %lo, i64 %hi) + %not_err = icmp eq i64 %7, 0 + br i1 %not_err, label %after.errcheck, label %error error: ; preds = %entry - store i64 %7, ptr %reterr, align 8 - br label %err_retblock + store i64 %7, ptr %reterr, align 8 + br label %err_retblock after.errcheck: ; preds = %entry - %8 = getelementptr inbounds %Doc, ptr %retparam1, i32 0, i32 0 - %9 = load ptr, ptr %8, align 8 - %10 = call i64 @test.isTitleNonEmpty(ptr %retparam, ptr %9) - %not_err2 = icmp eq i64 %10, 0 - br i1 %not_err2, label %after.errcheck4, label %error3 + %8 = getelementptr inbounds %Doc, ptr %retparam1, i32 0, i32 0 + %9 = load ptr, ptr %8, align 8 + %10 = call i64 @test.isTitleNonEmpty(ptr %retparam, ptr %9) + %not_err2 = icmp eq i64 %10, 0 + br i1 %not_err2, label %after.errcheck4, label %error3 error3: ; preds = %after.errcheck - store i64 %10, ptr %reterr, align 8 - br label %err_retblock + store i64 %10, ptr %reterr, align 8 + br label %err_retblock after.errcheck4: ; preds = %after.errcheck - %11 = load i8, ptr %retparam, align 1 - store i8 %11, ptr %0, align 1 - ret i64 0 + %11 = load i8, ptr %retparam, align 1 + store i8 %11, ptr %0, align 1 + ret i64 0 err_retblock: ; preds = %error3, %error - %12 = load i64, ptr %reterr, align 8 - ret i64 %12 + %12 = load i64, ptr %reterr, align 8 + ret i64 %12 } ; Function Attrs: nounwind define ptr @test.bool_to_string(i8 zeroext %0) #0 { entry: - %1 = trunc i8 %0 to i1 - %ternary = select i1 %1, ptr @.str.7, ptr @.str.8 - ret ptr %ternary + %1 = trunc i8 %0 to i1 + %ternary = select i1 %1, %"char[]" { ptr @.str.7, i64 4 }, %"char[]" { ptr @.str.8, i64 5 } + %2 = extractvalue %"char[]" %ternary, 0 + ret ptr %2 } ; Function Attrs: nounwind define ptr @test.nameFromError(i64 %0) #0 { entry: - %switch = alloca i64, align 8 - store i64 %0, ptr %switch, align 8 - br label %switch.entry + %switch = alloca i64, align 8 + store i64 %0, ptr %switch, align 8 + br label %switch.entry switch.entry: ; preds = %entry - %1 = load i64, ptr %switch, align 8 - %eq = icmp eq i64 ptrtoint (ptr @test.TitleResult.TITLE_MISSING to i64), %1 - br i1 %eq, label %switch.case, label %next_if + %1 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @test.TitleResult.TITLE_MISSING to i64), %1 + br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry - ret ptr @.str.9 + ret ptr @.str.9 next_if: ; preds = %switch.entry - %eq1 = icmp eq i64 ptrtoint (ptr @test.ReadError.BAD_READ to i64), %1 - br i1 %eq1, label %switch.case2, label %next_if3 + %eq1 = icmp eq i64 ptrtoint (ptr @test.ReadError.BAD_READ to i64), %1 + br i1 %eq1, label %switch.case2, label %next_if3 switch.case2: ; preds = %next_if - ret ptr @.str.10 + ret ptr @.str.10 next_if3: ; preds = %next_if - %eq4 = icmp eq i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), %1 - br i1 %eq4, label %switch.case5, label %next_if6 + %eq4 = icmp eq i64 ptrtoint (ptr @test.ReadError.OUT_OF_MEMORY to i64), %1 + br i1 %eq4, label %switch.case5, label %next_if6 switch.case5: ; preds = %next_if3 - ret ptr @.str.11 + ret ptr @.str.11 next_if6: ; preds = %next_if3 - br label %switch.default + br label %switch.default switch.default: ; preds = %next_if6 - ret ptr @.str.12 + ret ptr @.str.12 } ; Function Attrs: nounwind define void @test.main() #0 { entry: - %URLS = alloca %"char[][]", align 8 - %literal = alloca [5 x %"char[]"], align 16 - %anon = alloca i64, align 8 - %anon1 = alloca %"char[][]", align 8 - %anon2 = alloca i64, align 8 - %url = alloca %"char[]", align 8 - %summary = alloca %Summary, align 8 - %result = alloca %Summary, align 8 - %title_sure = alloca %"char[]", align 8 - %has_title = alloca i8, align 1 - %has_title.f = alloca i64, align 8 - %retparam = alloca i8, align 1 - %0 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 0 - store %"char[]" { ptr @.str.13, i64 4 }, ptr %0, align 8 - %1 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 1 - store %"char[]" { ptr @.str.14, i64 11 }, ptr %1, align 8 - %2 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 2 - store %"char[]" { ptr @.str.15, i64 13 }, ptr %2, align 8 - %3 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 3 - store %"char[]" { ptr @.str.16, i64 12 }, ptr %3, align 8 - %4 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 4 - store %"char[]" { ptr @.str.17, i64 4 }, ptr %4, align 8 - %5 = insertvalue %"char[][]" undef, ptr %literal, 0 - %6 = insertvalue %"char[][]" %5, i64 5, 1 - store %"char[][]" %6, ptr %URLS, align 8 - store i64 0, ptr %anon, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %anon1, ptr align 8 %URLS, i32 16, i1 false) - %7 = getelementptr inbounds %"char[][]", ptr %anon1, i32 0, i32 1 - %8 = load i64, ptr %7, align 8 - store i64 %8, ptr %anon2, align 8 - br label %loop.cond + %URLS = alloca %"char[][]", align 8 + %literal = alloca [5 x %"char[]"], align 16 + %anon = alloca i64, align 8 + %anon1 = alloca %"char[][]", align 8 + %anon2 = alloca i64, align 8 + %url = alloca %"char[]", align 8 + %summary = alloca %Summary, align 8 + %result = alloca %Summary, align 8 + %title_sure = alloca %"char[]", align 8 + %has_title = alloca i8, align 1 + %has_title.f = alloca i64, align 8 + %retparam = alloca i8, align 1 + %0 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 0 + store %"char[]" { ptr @.str.13, i64 4 }, ptr %0, align 8 + %1 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 1 + store %"char[]" { ptr @.str.14, i64 11 }, ptr %1, align 8 + %2 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 2 + store %"char[]" { ptr @.str.15, i64 13 }, ptr %2, align 8 + %3 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 3 + store %"char[]" { ptr @.str.16, i64 12 }, ptr %3, align 8 + %4 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 4 + store %"char[]" { ptr @.str.17, i64 4 }, ptr %4, align 8 + %5 = insertvalue %"char[][]" undef, ptr %literal, 0 + %6 = insertvalue %"char[][]" %5, i64 5, 1 + store %"char[][]" %6, ptr %URLS, align 8 + store i64 0, ptr %anon, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %anon1, ptr align 8 %URLS, i32 16, i1 false) + %7 = getelementptr inbounds %"char[][]", ptr %anon1, i32 0, i32 1 + %8 = load i64, ptr %7, align 8 + store i64 %8, ptr %anon2, align 8 + br label %loop.cond loop.cond: ; preds = %phi_block11, %entry - %9 = load i64, ptr %anon, align 8 - %10 = load i64, ptr %anon2, align 8 - %lt = icmp ult i64 %9, %10 - br i1 %lt, label %loop.body, label %loop.exit + %9 = load i64, ptr %anon, align 8 + %10 = load i64, ptr %anon2, align 8 + %lt = icmp ult i64 %9, %10 + br i1 %lt, label %loop.body, label %loop.exit loop.body: ; preds = %loop.cond - %11 = getelementptr inbounds %"char[][]", ptr %anon1, i32 0, i32 0 - %12 = load ptr, ptr %11, align 8 - %13 = load i64, ptr %anon, align 8 - %ptroffset = getelementptr inbounds %"char[]", ptr %12, i64 %13 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %url, ptr align 8 %ptroffset, i32 16, i1 false) - %14 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1 - %15 = load i64, ptr %14, align 8 - %uisitrunc = trunc i64 %15 to i32 - %16 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 - %17 = load ptr, ptr %16, align 8 - %18 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %uisitrunc, ptr %17) - %19 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - %lo = load ptr, ptr %19, align 8 - %20 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - %hi = load i64, ptr %20, align 8 - %21 = call { ptr, i8 } @test.readAndBuildSummary(ptr %lo, i64 %hi) - store { ptr, i8 } %21, ptr %result, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %summary, ptr align 8 %result, i32 16, i1 false) - %22 = call i32 (ptr, ...) @printf(ptr @.str.19) - %23 = load ptr, ptr @__stdoutp, align 8 - call void @test.Summary__print(ptr %summary, ptr %23) - %24 = call i32 (ptr, ...) @printf(ptr @.str.20) - %25 = getelementptr inbounds %Summary, ptr %summary, i32 0, i32 0 - %26 = load ptr, ptr %25, align 8 - %ptrbool = icmp ne ptr %26, null - br i1 %ptrbool, label %cond.lhs, label %cond.rhs + %11 = getelementptr inbounds %"char[][]", ptr %anon1, i32 0, i32 0 + %12 = load ptr, ptr %11, align 8 + %13 = load i64, ptr %anon, align 8 + %ptroffset = getelementptr inbounds %"char[]", ptr %12, i64 %13 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %url, ptr align 8 %ptroffset, i32 16, i1 false) + %14 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1 + %15 = load i64, ptr %14, align 8 + %uisitrunc = trunc i64 %15 to i32 + %16 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 + %17 = load ptr, ptr %16, align 8 + %18 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %uisitrunc, ptr %17) + %19 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo = load ptr, ptr %19, align 8 + %20 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi = load i64, ptr %20, align 8 + %21 = call { ptr, i8 } @test.readAndBuildSummary(ptr %lo, i64 %hi) + store { ptr, i8 } %21, ptr %result, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %summary, ptr align 8 %result, i32 16, i1 false) + %22 = call i32 (ptr, ...) @printf(ptr @.str.19) + %23 = load ptr, ptr @__stdoutp, align 8 + call void @test.Summary__print(ptr %summary, ptr %23) + %24 = call i32 (ptr, ...) @printf(ptr @.str.20) + %25 = getelementptr inbounds %Summary, ptr %summary, i32 0, i32 0 + %26 = load ptr, ptr %25, align 8 + %ptrbool = icmp ne ptr %26, null + br i1 %ptrbool, label %cond.lhs, label %cond.rhs cond.lhs: ; preds = %loop.body - %27 = getelementptr inbounds %Summary, ptr %summary, i32 0, i32 0 - %28 = load ptr, ptr %27, align 8 - %29 = load %"char[]", ptr %28, align 8 - br label %cond.phi + %27 = getelementptr inbounds %Summary, ptr %summary, i32 0, i32 0 + %28 = load ptr, ptr %27, align 8 + %29 = load %"char[]", ptr %28, align 8 + br label %cond.phi cond.rhs: ; preds = %loop.body - br label %cond.phi + br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi %"char[]" [ %29, %cond.lhs ], [ { ptr @.str.21, i64 0 }, %cond.rhs ] - store %"char[]" %val, ptr %title_sure, align 8 - %30 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 1 - %31 = load i64, ptr %30, align 8 - %uisitrunc3 = trunc i64 %31 to i32 - %32 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 0 - %33 = load ptr, ptr %32, align 8 - %34 = call i32 (ptr, ...) @printf(ptr @.str.22, i32 %uisitrunc3, ptr %33) - %35 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 - %lo4 = load ptr, ptr %35, align 8 - %36 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 - %hi5 = load i64, ptr %36, align 8 - %37 = call i64 @test.readWhetherTitleNonEmpty(ptr %retparam, ptr %lo4, i64 %hi5) - %not_err = icmp eq i64 %37, 0 - br i1 %not_err, label %after.errcheck, label %error + %val = phi %"char[]" [ %29, %cond.lhs ], [ { ptr @.str.21, i64 0 }, %cond.rhs ] + store %"char[]" %val, ptr %title_sure, align 8 + %30 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 1 + %31 = load i64, ptr %30, align 8 + %uisitrunc3 = trunc i64 %31 to i32 + %32 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 0 + %33 = load ptr, ptr %32, align 8 + %34 = call i32 (ptr, ...) @printf(ptr @.str.22, i32 %uisitrunc3, ptr %33) + %35 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 + %lo4 = load ptr, ptr %35, align 8 + %36 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 + %hi5 = load i64, ptr %36, align 8 + %37 = call i64 @test.readWhetherTitleNonEmpty(ptr %retparam, ptr %lo4, i64 %hi5) + %not_err = icmp eq i64 %37, 0 + br i1 %not_err, label %after.errcheck, label %error error: ; preds = %cond.phi - store i64 %37, ptr %has_title.f, align 8 - br label %after_assign + store i64 %37, ptr %has_title.f, align 8 + br label %after_assign after.errcheck: ; preds = %cond.phi - %38 = load i8, ptr %retparam, align 1 - store i8 %38, ptr %has_title, align 1 - store i64 0, ptr %has_title.f, align 8 - br label %after_assign + %38 = load i8, ptr %retparam, align 1 + store i8 %38, ptr %has_title, align 1 + store i64 0, ptr %has_title.f, align 8 + br label %after_assign after_assign: ; preds = %after.errcheck, %error - %39 = load i64, ptr %has_title.f, align 8 - %not_err6 = icmp eq i64 %39, 0 - br i1 %not_err6, label %after_check, label %else_block + %39 = load i64, ptr %has_title.f, align 8 + %not_err6 = icmp eq i64 %39, 0 + br i1 %not_err6, label %after_check, label %else_block after_check: ; preds = %after_assign - %40 = load i8, ptr %has_title, align 1 - %41 = call ptr @test.bool_to_string(i8 %40) - br label %phi_block + %40 = load i8, ptr %has_title, align 1 + %41 = call ptr @test.bool_to_string(i8 %40) + br label %phi_block else_block: ; preds = %after_assign - %42 = load i64, ptr %has_title.f, align 8 - %43 = call ptr @test.nameFromError(i64 %42) - br label %phi_block + %42 = load i64, ptr %has_title.f, align 8 + %43 = call ptr @test.nameFromError(i64 %42) + br label %phi_block phi_block: ; preds = %else_block, %after_check - %val7 = phi ptr [ %41, %after_check ], [ %43, %else_block ] - %44 = load i64, ptr %has_title.f, align 8 - %not_err8 = icmp eq i64 %44, 0 - br i1 %not_err8, label %after_check9, label %else_block10 + %val7 = phi ptr [ %41, %after_check ], [ %43, %else_block ] + %44 = load i64, ptr %has_title.f, align 8 + %not_err8 = icmp eq i64 %44, 0 + br i1 %not_err8, label %after_check9, label %else_block10 after_check9: ; preds = %phi_block - %45 = load i8, ptr %has_title, align 1 - %46 = trunc i8 %45 to i1 - br label %phi_block11 + %45 = load i8, ptr %has_title, align 1 + %46 = trunc i8 %45 to i1 + br label %phi_block11 else_block10: ; preds = %phi_block - br label %phi_block11 + br label %phi_block11 phi_block11: ; preds = %else_block10, %after_check9 - %val12 = phi i1 [ %46, %after_check9 ], [ false, %else_block10 ] - %ternary = select i1 %val12, ptr @.str.24, ptr @.str.25 - %47 = call i32 (ptr, ...) @printf(ptr @.str.23, ptr %val7, ptr %ternary) - %48 = load i64, ptr %anon, align 8 - %add = add i64 %48, 1 - store i64 %add, ptr %anon, align 8 - br label %loop.cond + %val12 = phi i1 [ %46, %after_check9 ], [ false, %else_block10 ] + %ternary = select i1 %val12, ptr @.str.24, ptr @.str.25 + %47 = call i32 (ptr, ...) @printf(ptr @.str.23, ptr %val7, ptr %ternary) + %48 = load i64, ptr %anon, align 8 + %add = add i64 %48, 1 + store i64 %add, ptr %anon, align 8 + br label %loop.cond loop.exit: ; preds = %loop.cond - ret void + ret void } diff --git a/test/test_suite2/errors/failable_inits.c3t b/test/test_suite2/errors/failable_inits.c3t index e3cb4d26d..0ef3b14df 100644 --- a/test/test_suite2/errors/failable_inits.c3t +++ b/test/test_suite2/errors/failable_inits.c3t @@ -13,13 +13,13 @@ struct Bar int x; } -fn void! test1() +fn void! test1() @maydiscard { Bar! x = Foo.MY_VAL1!; Bar y = x?; } -fn void! test2() +fn void! test2() @maydiscard { Bar! x = {}; Bar y = x?; diff --git a/test/test_suite2/macros/macro_body_defer.c3t b/test/test_suite2/macros/macro_body_defer.c3t index 5b5c69883..443295bab 100644 --- a/test/test_suite2/macros/macro_body_defer.c3t +++ b/test/test_suite2/macros/macro_body_defer.c3t @@ -87,17 +87,17 @@ loop.exit: ; preds = %loop.body br label %loop.body2 loop.body2: ; preds = %loop.exit - call void (ptr, ...) @printf(ptr @.str.13) + call void (ptr, ...) @printf(ptr @.str.10) store i32 3, ptr %i3, align 4 - call void (ptr, ...) @printf(ptr @.str.14) - call void (ptr, ...) @printf(ptr @.str.15) + call void (ptr, ...) @printf(ptr @.str.11) + call void (ptr, ...) @printf(ptr @.str.12) %3 = load i32, ptr %i3, align 4 - call void (ptr, ...) @printf(ptr @.str.16, i32 %3) - call void (ptr, ...) @printf(ptr @.str.17) + call void (ptr, ...) @printf(ptr @.str.13, i32 %3) + call void (ptr, ...) @printf(ptr @.str.14) ret i64 0 loop.exit4: ; No predecessors! - call void (ptr, ...) @printf(ptr @.str.21) + call void (ptr, ...) @printf(ptr @.str.15) ret i64 0 }