Main arguments are now slices if desired.

This commit is contained in:
Christoffer Lerno
2021-12-16 23:31:27 +01:00
committed by Christoffer Lerno
parent 497eef5328
commit c52629d60f
66 changed files with 421 additions and 139 deletions

View File

@@ -223,6 +223,7 @@ bool expr_is_pure(Expr *expr)
case EXPR_NOP:
case EXPR_PTR:
return true;
case EXPR_ARGV_TO_SUBARRAY:
case EXPR_BITASSIGN:
return false;
case EXPR_VARIANTSWITCH:

View File

@@ -936,6 +936,12 @@ typedef struct
};
} ExprVariantSwitch;
typedef struct
{
Decl *argc;
Decl *argv;
} ExprArgv;
struct Expr_
{
ExprKind expr_kind : 8;
@@ -948,6 +954,7 @@ struct Expr_
ExprCast cast_expr;
TypeInfo *type_expr;
ExprConst const_expr;
ExprArgv argv_expr;
ExprGuard rethrow_expr;
Decl *decl_expr;
ExprOrError or_error_expr;
@@ -1381,6 +1388,7 @@ typedef struct Context_
Decl **types;
Decl **generic_defines;
Decl **functions;
Decl *main_function;
Decl **macros;
Decl **generics;
Decl **generic_methods;
@@ -1609,6 +1617,10 @@ extern const char *kw_builtin_exp;
extern const char *kw_builtin_fabs;
extern const char *kw_builtin_fma;
extern const char *kw_builtin_cmpxchg;
extern const char *kw_argc;
extern const char *kw_argv;
extern const char *kw_mainstub;
#define AST_NEW_TOKEN(_kind, _token) new_ast(_kind, source_span_from_token_id((_token).id))

View File

@@ -71,6 +71,7 @@ Expr *copy_expr(Expr *source_expr)
{
case EXPR_MACRO_BODY_EXPANSION:
case EXPR_VARIANTSWITCH:
case EXPR_ARGV_TO_SUBARRAY:
UNREACHABLE
case EXPR_FLATPATH:
case EXPR_UNDEF:

View File

@@ -211,6 +211,7 @@ typedef enum
EXPR_SLICE_ASSIGN,
EXPR_SUBSCRIPT,
EXPR_SUBSCRIPT_ADDR,
EXPR_ARGV_TO_SUBARRAY,
EXPR_TERNARY,
EXPR_TRY,
EXPR_TRY_UNWRAP,

View File

@@ -1014,6 +1014,7 @@ void *llvm_gen(Module *module)
{
llvm_emit_function_decl(gen_context, context->functions[i]);
}
if (context->main_function) llvm_emit_function_decl(gen_context, context->main_function);
}
VECEACH(module->contexts, j)
@@ -1035,6 +1036,8 @@ void *llvm_gen(Module *module)
Decl *decl = context->functions[i];
if (decl->func_decl.body) llvm_emit_function_body(gen_context, decl);
}
if (context->main_function) llvm_emit_function_body(gen_context, context->main_function);
VECEACH(context->methods, i)
{
Decl *decl = context->methods[i];

View File

@@ -5159,6 +5159,87 @@ void llvm_emit_try_unwrap_chain(GenContext *c, BEValue *value, Expr *expr)
}
static inline void llvm_emit_argv_to_subarray(GenContext *c, BEValue *value, Expr *expr)
{
BEValue argc_value;
BEValue argv_value;
llvm_value_set_decl_address(&argc_value, expr->argv_expr.argc);
llvm_value_set_decl_address(&argv_value, expr->argv_expr.argv);
llvm_value_rvalue(c, &argc_value);
llvm_value_rvalue(c, &argv_value);
LLVMValueRef argv_ptr = argv_value.value;
LLVMValueRef count = argc_value.value;
Type *arg_array_type = type_get_subarray(type_char);
AlignSize alignment = type_alloca_alignment(type_get_array(arg_array_type, 1));
LLVMTypeRef arg_array_elem_type = llvm_get_type(c, arg_array_type);
LLVMValueRef arg_array = LLVMBuildArrayAlloca(c->builder, arg_array_elem_type, count, "argarray");
LLVMSetAlignment(arg_array, alignment);
// Store the addresses.
LLVMTypeRef temp_type = llvm_get_type(c, expr->type);
LLVMTypeRef loop_type = llvm_get_type(c, type_usize);
LLVMTypeRef char_ptr_type = llvm_get_ptr_type(c, type_char);
LLVMValueRef size = llvm_zext_trunc(c, count, loop_type);
LLVMValueRef result = LLVMGetUndef(temp_type);
result = LLVMBuildInsertValue(c->builder, result, size, 1, "");
result = LLVMBuildInsertValue(c->builder, result, arg_array, 0, "");
llvm_value_set(value, result, expr->type);
// Check if zero:
BEValue cond;
llvm_value_set_bool(&cond, LLVMBuildICmp(c->builder, LLVMIntEQ, count, llvm_get_zero(c, argc_value.type), ""));
LLVMBasicBlockRef exit_block = llvm_basic_block_new(c, "exit_loop");
LLVMBasicBlockRef pre_loop_block = llvm_basic_block_new(c, "pre_loop");
// Jump to exit if zero
llvm_emit_cond_br(c, &cond, exit_block, pre_loop_block);
// Now we create the pre loop block
llvm_emit_block(c, pre_loop_block);
LLVMBasicBlockRef body_block = llvm_basic_block_new(c, "body_loop");
LLVMValueRef zero = LLVMConstNull(loop_type);
// Jump to the first entry
llvm_emit_br(c, body_block);
llvm_emit_block(c, body_block);
LLVMValueRef index_var = LLVMBuildPhi(c->builder, loop_type, "");
// Find the current substring
LLVMValueRef index = LLVMBuildInBoundsGEP2(c->builder, arg_array_elem_type, arg_array, &index_var, 1, "indexfe");
LLVMValueRef pointer_to_arg = LLVMBuildInBoundsGEP2(c->builder, char_ptr_type, argv_ptr, &index_var, 1, "");
// Get the char* to the argument
LLVMValueRef pointer_value = llvm_emit_load_aligned(c, llvm_get_ptr_type(c, type_char), pointer_to_arg,
type_abi_alignment(type_get_ptr(type_char)), "");
AlignSize index_align;
// Get strlen to calculate length
LLVMValueRef strlen = LLVMGetNamedFunction(c->module, "strlen");
LLVMTypeRef strlen_type = LLVMFunctionType(loop_type, &char_ptr_type, 1, false);
if (!strlen)
{
strlen = LLVMAddFunction(c->module, "strlen", strlen_type);
}
LLVMValueRef len = LLVMBuildCall2(c->builder, strlen_type, strlen, &pointer_value, 1, "");
// We first set the pointer
AlignSize align = type_abi_alignment(arg_array_type);
LLVMValueRef ptr_loc = llvm_emit_struct_gep_raw(c, index, arg_array_elem_type, 0, align, &index_align);
llvm_store_aligned(c, ptr_loc, pointer_value, index_align);
// Then the length
LLVMValueRef len_loc = llvm_emit_struct_gep_raw(c, index, arg_array_elem_type, 1, align, &index_align);
llvm_store_aligned(c, len_loc, len, index_align);
// Add index
LLVMValueRef index_plus = LLVMBuildNUWAdd(c->builder, index_var, llvm_const_int(c, type_usize, 1), "");
llvm_value_set_bool(&cond, LLVMBuildICmp(c->builder, LLVMIntULT, index_plus, size, ""));
llvm_emit_cond_br(c, &cond, body_block, exit_block);
LLVMValueRef values[2] = { index_plus, zero };
LLVMBasicBlockRef blocks[2] = { body_block, pre_loop_block };
LLVMAddIncoming(index_var, values, blocks, 2);
llvm_emit_block(c, exit_block);
}
void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
{
EMIT_LOC(c, expr);
@@ -5176,6 +5257,9 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
case EXPR_FLATPATH:
case EXPR_VARIANTSWITCH:
UNREACHABLE
case EXPR_ARGV_TO_SUBARRAY:
llvm_emit_argv_to_subarray(c, value, expr);
return;
case EXPR_TRY_UNWRAP_CHAIN:
llvm_emit_try_unwrap_chain(c, value, expr);
return;

View File

@@ -810,6 +810,7 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type)
case EXPR_TYPEOFANY:
case EXPR_PTR:
case EXPR_VARIANTSWITCH:
case EXPR_ARGV_TO_SUBARRAY:
UNREACHABLE
case EXPR_POST_UNARY:
return recursive_may_narrow_float(expr->unary_expr.expr, type);
@@ -963,6 +964,7 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type)
case EXPR_SUBSCRIPT_ADDR:
case EXPR_TYPEOFANY:
case EXPR_PTR:
case EXPR_ARGV_TO_SUBARRAY:
case EXPR_VARIANTSWITCH:
UNREACHABLE
case EXPR_POST_UNARY:

View File

@@ -1270,6 +1270,139 @@ static inline bool sema_update_call_convention(Decl *decl, CallABI abi)
return had;
}
static inline bool sema_analyse_main_function(Context *context, Decl *decl)
{
if (decl == context->main_function) return true;
if (decl->visibility == VISIBLE_LOCAL)
{
SEMA_ERROR(decl, "A main function may not have local visibility.");
return false;
}
FunctionSignature *signature = &decl->func_decl.function_signature;
Type *rtype = type_flatten_distinct(signature->rtype->type);
bool is_int_return = true;
bool is_err_return = false;
if (rtype->type_kind == TYPE_FAILABLE_ANY) is_err_return = true;
if (!is_err_return && type_is_failable(rtype))
{
if (rtype->failable->type_kind != TYPE_VOID)
{
SEMA_ERROR(signature->rtype, "The return type of 'main' cannot be a failable, unless it is 'void!'.");
return false;
}
is_int_return = false;
is_err_return = true;
}
if (rtype->type_kind == TYPE_VOID) is_int_return = false;
if (type_is_integer(rtype) && rtype != type_cint())
{
SEMA_ERROR(signature->rtype, "Expected a return type of 'void' or %s.", type_quoted_error_string(type_cint()));
return false;
}
// At this point the style is either MAIN_INT_VOID, MAIN_VOID_VOID or MAIN_ERR_VOID
Decl **params = signature->params;
unsigned param_count = vec_size(params);
bool subarray_param = false;
bool cparam = false;
switch (param_count)
{
case 0:
// This is the default style already set
break;
case 1:
if (type_flatten_distinct(params[0]->type) != type_get_subarray(type_get_subarray(type_char)))
{
SEMA_ERROR(params[0], "Expected a parameter of type 'char[][]'");
return false;
}
subarray_param = true;
break;
case 2:
if (type_flatten_distinct(params[0]->type) != type_cint())
{
SEMA_ERROR(params[0], "Expected a parameter of type %s for a C-style main.", type_quoted_error_string(type_cint()));
return false;
}
if (type_flatten_distinct(params[1]->type) != type_get_ptr(type_get_ptr(type_char)))
{
SEMA_ERROR(params[1], "Expected a parameter of type 'char**' for a C-style main.");
return false;
}
cparam = true;
break;
default:
SEMA_ERROR(params[0], "Expected zero, 1 or 2 parameters for main.");
return false;
}
if (!subarray_param && is_int_return)
{
// Int return is pass-through at the moment.
decl->visibility = VISIBLE_EXTERN;
return true;
}
Decl *function = decl_new(DECL_FUNC, decl->name_token, VISIBLE_EXTERN);
function->name = kw_mainstub;
function->extname = kw_main;
function->func_decl.function_signature.rtype = type_info_new_base(type_cint(), decl->span);
Decl *param1 = decl_new_generated_var(kw_argv, type_cint(), VARDECL_PARAM, decl->span);
Decl *param2 = decl_new_generated_var(kw_argc, type_get_ptr(type_get_ptr(type_char)), VARDECL_PARAM, decl->span);
Decl **main_params = NULL;
vec_add(main_params, param1);
vec_add(main_params, param2);
function->func_decl.function_signature.params = main_params;
Ast *body = new_ast(AST_COMPOUND_STMT, decl->span);
Ast *ret_stmt = new_ast(AST_RETURN_STMT, decl->span);
Expr *call = expr_new(EXPR_CALL, decl->span);
call->call_expr.function = expr_variable(decl);
if (subarray_param)
{
Expr *subarray = expr_new(EXPR_ARGV_TO_SUBARRAY, decl->span);
subarray->argv_expr.argc = param1;
subarray->argv_expr.argv = param2;
vec_add(call->call_expr.arguments, subarray);
}
else if (cparam)
{
vec_add(call->call_expr.arguments, expr_variable(param1));
vec_add(call->call_expr.arguments, expr_variable(param2));
}
// Unresolve them or the params cannot be resolved later.
param1->resolve_status = RESOLVE_NOT_DONE;
param2->resolve_status = RESOLVE_NOT_DONE;
if (is_int_return)
{
ret_stmt->return_stmt.expr = call;
}
else if (is_err_return)
{
Expr *try_expr = expr_new(EXPR_TRY, decl->span);
try_expr->inner_expr = call;
Expr *not_expr = expr_new(EXPR_UNARY, decl->span);
not_expr->unary_expr.expr = try_expr;
not_expr->unary_expr.operator = UNARYOP_NOT;
Expr *cast_expr = expr_new(EXPR_CAST, decl->span);
cast_expr->cast_expr.expr = not_expr;
cast_expr->cast_expr.type_info = type_info_new_base(type_cint(), decl->span);
ret_stmt->return_stmt.expr = cast_expr;
}
else
{
Ast *stmt = new_ast(AST_EXPR_STMT, decl->span);
stmt->expr_stmt = call;
vec_add(body->compound_stmt.stmts, stmt);
Expr *c = expr_new(EXPR_CONST, decl->span);
c->type = type_cint();
expr_const_set_int(&c->const_expr, 0, c->type->type_kind);
c->resolve_status = RESOLVE_DONE;
ret_stmt->expr_stmt = c;
}
vec_add(body->compound_stmt.stmts, ret_stmt);
function->func_decl.body = body;
context->main_function = function;
return true;
}
static inline bool sema_analyse_func(Context *context, Decl *decl)
{
DEBUG_LOG("----Analysing function %s", decl->name);
@@ -1375,12 +1508,7 @@ static inline bool sema_analyse_func(Context *context, Decl *decl)
{
if (decl->name == kw_main)
{
if (decl->visibility == VISIBLE_LOCAL)
{
SEMA_ERROR(decl, "'main' cannot have local visibility.");
return false;
}
decl->visibility = VISIBLE_EXTERN;
if (!sema_analyse_main_function(context, decl)) return decl_poison(decl);
}
decl_set_external_name(decl);
}

View File

@@ -452,6 +452,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
case EXPR_MACRO_EXPANSION:
case EXPR_PLACEHOLDER:
case EXPR_POISONED:
case EXPR_ARGV_TO_SUBARRAY:
UNREACHABLE
case EXPR_NOP:
return true;
@@ -6730,6 +6731,9 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Expr *expr)
case EXPR_PTR:
case EXPR_VARIANTSWITCH:
UNREACHABLE
case EXPR_ARGV_TO_SUBARRAY:
expr->type = type_get_subarray(type_get_subarray(type_char));
return true;
case EXPR_DECL:
if (!sema_analyse_var_decl(context, expr->decl_expr, true)) return false;
expr->type = expr->decl_expr->type;

View File

@@ -224,6 +224,10 @@ void sema_analysis_pass_decls(Module *module)
{
sema_analyse_decl(context, context->functions[i]);
}
if (context->main_function)
{
sema_analyse_decl(context, context->main_function);
}
VECEACH(context->generic_defines, i)
{
sema_analyse_decl(context, context->generic_defines[i]);
@@ -247,6 +251,7 @@ void sema_analysis_pass_functions(Module *module)
{
analyse_func_body(context, context->functions[i]);
}
if (context->main_function) analyse_func_body(context, context->main_function);
}

View File

@@ -88,6 +88,9 @@ const char *kw_builtin_exp;
const char *kw_builtin_fabs;
const char *kw_builtin_fma;
const char *kw_builtin_cmpxchg;
const char *kw_argc;
const char *kw_argv;
const char *kw_mainstub;;
void symtab_init(uint32_t capacity)
{
@@ -153,6 +156,10 @@ void symtab_init(uint32_t capacity)
kw_default_iterator = KW_DEF("default_iterator");
kw_check_assign = KW_DEF("check_assign");
kw_argc = KW_DEF("_$argc");
kw_argv = KW_DEF("_$argv");
kw_mainstub = KW_DEF("_$mainstub");
builtin_list[BUILTIN_CEIL] = KW_DEF("ceil");
builtin_list[BUILTIN_TRUNC] = KW_DEF("trunc");
builtin_list[BUILTIN_SIN] = KW_DEF("sin");

View File

@@ -11,9 +11,10 @@ fn void test(Foo x) @regcall
{
}
fn void main()
fn int main()
{
test(Foo { });
return 0;
}
/* #expect: test.ll
@@ -38,7 +39,7 @@ entry:
}
; Function Attrs: nounwind
define void @main() #0 {
define i32 @main() #0 {
entry:
%literal = alloca %Foo, align 4
%0 = getelementptr inbounds %Foo, %Foo* %literal, i32 0, i32 0
@@ -52,5 +53,5 @@ entry:
%5 = getelementptr inbounds [2 x float], [2 x float]* %3, i64 0, i64 1
%loadexpanded1 = load float, float* %5, align 4
call x86_regcallcc void @test.test(float %loadexpanded, float %loadexpanded1)
ret void
ret i32 0
}

View File

@@ -23,7 +23,7 @@ fn void main()
/* #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
%xx = alloca [3 x i8], align 1
%xy = alloca [3 x i8], align 1

View File

@@ -93,7 +93,7 @@ fn void main()
/* #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
%b = alloca i8, align 1
%c1 = alloca i16, align 2

View File

@@ -30,7 +30,7 @@ fn void main()
/* #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
%xx = alloca [3 x i8], align 1
%xxu = alloca [3 x i8], align 1

View File

@@ -122,7 +122,7 @@ fn void test3()
/* #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
call void @foo.test1()
call void @foo.test2()

View File

@@ -107,11 +107,3 @@ entry:
store [4 x i8]* %12, [4 x i8]** %y2, align 8
ret void
}
; Function Attrs: nounwind
define void @main() #0 {
entry:
call void @foo.test()
call void @foo.test2()
ret void
}

View File

@@ -46,7 +46,7 @@ fn void main()
/* #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
%b = alloca %Bar, align 4
%f = alloca %Foo, align 4

View File

@@ -52,7 +52,7 @@ fn void main()
; Function Attrs: nounwind
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @main() #0 {
define void @test.main() #0 {
entry:
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), [5 x i8]* bitcast ([6 x i8]* @.str.1 to [5 x i8]*))
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), [9 x i8]* bitcast ([10 x i8]* @.str.3 to [9 x i8]*))

View File

@@ -35,7 +35,7 @@ fn void main()
; Function Attrs: nounwind
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @main() #0 {
define void @test.main() #0 {
entry:
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), [3 x i8]* bitcast ([4 x i8]* @.str.1 to [3 x i8]*))
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), [6 x i8]* bitcast ([7 x i8]* @.str.3 to [6 x i8]*))

View File

@@ -61,7 +61,7 @@ fn void main()
// #expect: mymodule.ll
define void @main() #0 {
define void @mymodule.main() #0 {
entry:
%x = alloca i32, align 4
%y = alloca i32, align 4

View File

@@ -40,7 +40,7 @@ fn void main()
@.str.16 = private constant [15 x i8] c"Blob**[3]: %s\0A\00", align 1
@.str.17 = private constant [10 x i8] c"Blob**[3]\00", align 1
define void @main()
define void @qnametest.main()
%help = alloca i32, align 4
store i32 0, i32* %help, align 4
%0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), [6 x i8]* bitcast ([7 x i8]* @.str.1 to [6 x i8]*))

View File

@@ -52,7 +52,7 @@ entry:
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @main() #0 {
define void @anyerr_void.main() #0 {
entry:
%z = alloca i64, align 8
%error_var = alloca i64, align 8

View File

@@ -94,7 +94,7 @@ noerr_block: ; preds = %after_check
}
; Function Attrs: nounwind
define void @main() #0 {
define void @test.main() #0 {
entry:
%0 = call i64 @test.test1()
%not_err = icmp eq i64 %0, 0

View File

@@ -37,7 +37,7 @@ fn void main()
declare i32 @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @main() #0 {
define void @test.main() #0 {
entry:
%z = alloca i32, align 4
%z.f = alloca i64, align 8

View File

@@ -95,7 +95,7 @@ entry:
ret void
}
define void @main() #0 {
define void @foo.main() #0 {
entry:
%f = alloca i64, align 8
%ef = alloca i64, align 8

View File

@@ -15,7 +15,7 @@ fn void main()
// #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
%i = alloca i32, align 4
%i.f = alloca i64, align 8

View File

@@ -27,7 +27,7 @@ fn void main()
// #expect: try_assign.ll
define void @main() #0 {
define void @try_assign.main() #0 {
entry:
%x = alloca i32, align 4
%z = alloca i32, align 4

View File

@@ -18,7 +18,7 @@ fn void main()
// #expect: try_with_chained_unwrap.ll
define void @main() #0 {
define void @try_with_chained_unwrap.main() #0 {
entry:
%val = alloca i32, align 4
%retparam = alloca i32, align 4

View File

@@ -21,7 +21,7 @@ fn void main()
// #expect: try_with_unwrap.ll
define void @main() #0 {
define void @try_with_unwrap.main() #0 {
entry:
%line = alloca i8*, align 8
%line.f = alloca i64, align 8

View File

@@ -49,7 +49,7 @@ fn void test3()
/* #expect: test.ll
define void @main() #0 {
define void @test.main() #0 {
entry:
call void @test.test()
call void @test.test2()

View File

@@ -15,7 +15,7 @@ fn void main()
// #expect: ternary_bool.ll
define void @main() #0 {
define void @ternary_bool.main() #0 {
entry:
%b = alloca i8, align 1
%c = alloca i8*, align 8

View File

@@ -13,7 +13,7 @@ macro foo(int x)
extern fn void printf(char*, ...);
fn void main()
fn int main()
{
int! a = @foo(1);
@@ -25,11 +25,12 @@ fn void main()
if (catch(c)) printf("c had error\n");
c = 3;
printf("c = %d\n", c);
return 0;
}
// #expect: failable_catch.ll
define void @main() #0 {
define i32 @main() #0 {
entry:
%a = alloca i32, align 4
%a.f = alloca i64, align 8
@@ -171,5 +172,5 @@ entry:
br label %voiderr27
voiderr27: ; preds = %after_check26, %if.exit24
ret void
ret i32 0
}

View File

@@ -80,10 +80,10 @@ exit10: ; preds = %exit9
}
; Function Attrs: nounwind
define void @main() #0 {
define void @defer1.main() #0 {
entry:
call void @defer1.test(i32 1)
call void @defer1.test(i32 0)
call void @defer1.test(i32 10)
ret void
}
}

View File

@@ -27,7 +27,7 @@ entry:
ret i32 0
}
define void @main() #0 {
define void @demo.main() #0 {
entry:
%result = alloca i32, align 4
%0 = load i32 (i8*, i32)*, i32 (i8*, i32)** @demo.cb, align 8

View File

@@ -105,7 +105,7 @@ noerr_block: ; preds = %after.errcheck
ret i64 0
}
define void @main() #0 {
define void @demo.main() #0 {
entry:
%ratio = alloca double, align 8
%ratio.f = alloca i64, align 8

View File

@@ -439,7 +439,7 @@ loop.exit: ; preds = %loop.cond
}
; Function Attrs: nounwind
define void @main() #0 {
define void @test.main() #0 {
entry:
%list = alloca %LinkedList, align 8
%i = alloca i32, align 4

View File

@@ -495,7 +495,7 @@ loop.exit: ; preds = %loop.cond
}
; Function Attrs: nounwind
define void @main() #0 {
define void @test.main() #0 {
entry:
%list = alloca %LinkedList, align 8
%i = alloca i32, align 4

View File

@@ -338,7 +338,7 @@ if.exit15: ; preds = %if.then14, %loop.ex
}
; Function Attrs: nounwind
define void @main(i32 %0, i8** %1) #0 {
define void @fasta.main(i32 %0, i8** %1) #0 {
entry:
%argc = alloca i32, align 4
%argv = alloca i8**, align 8
@@ -383,3 +383,15 @@ if.exit: ; preds = %if.then, %entry
call void @fasta.random_fasta(i8* %lo6, i64 %hi7, i8* %lo8, i64 %hi9, i32 %mul10)
ret void
}
define i32 @main(i32 %0, i8** %1) #0 {
entry:
%"_$argv" = alloca i32, align 4
%"_$argc" = alloca i8**, align 8
store i32 %0, i32* %"_$argv", align 4
store i8** %1, i8*** %"_$argc", align 8
%2 = load i32, i32* %"_$argv", align 4
%3 = load i8**, i8*** %"_$argc", align 8
call void @fasta.main(i32 %2, i8** %3)
ret i32 0
}

View File

@@ -28,7 +28,7 @@ fn void main()
/* #expect: test.ll
define void @main() #0 {
define void @test.main() #0 {
entry:
%ab = alloca i32, align 4
%x = alloca i32, align 4

View File

@@ -60,7 +60,7 @@ entry:
ret i32 %mul
}
define void @main() #0 {
define void @withbody.main() #0 {
entry:
%f = alloca %Foo, align 4
%y = alloca i32, align 4

View File

@@ -186,7 +186,7 @@ loop.exit: ; preds = %loop.cond
}
; Function Attrs: nounwind
define void @main() #0 {
define void @userland_bitcast.main() #0 {
entry:
%f = alloca float, align 4
%i = alloca i32, align 4

View File

@@ -30,7 +30,7 @@ fn void MyEnum.hello(MyEnum *myenum)
{
io::println("Hello from MyEnum");
}
fn void main()
fn int main()
{
Foo f;
Bar b;
@@ -38,6 +38,7 @@ fn void main()
f.hello();
b.hello();
a.hello();
return 0;
}
// #expect: foo.ll
@@ -60,7 +61,7 @@ define void @foo.MyEnum__hello(i32* %0)
%1 = call i32 @"std::io.println"(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.2, i32 0, i32 0))
ret void
define void @main()
define i32 @main()
entry:
%f = alloca i64, align 8
%b = alloca i32, align 4
@@ -71,4 +72,4 @@ entry:
call void @foo.Foo__hello(i64* %f)
call void @foo.Bar__hello(i32* %b)
call void @foo.MyEnum__hello(i32* %a)
ret void
ret i32 0

View File

@@ -18,20 +18,21 @@ module abc;
import foo;
import baz;
fn void main()
fn int main()
{
Bar bar;
bar.test();
return 0;
}
// #expect: abc.ll
declare void @foo.Bar__test(%Bar*)
define void @main()
define i32 @main()
entry:
%bar = alloca %Bar, align 4
%0 = bitcast %Bar* %bar to i32*
store i32 0, i32* %0, align 4
call void @foo.Bar__test(%Bar* %bar)
ret void
ret i32 0

View File

@@ -20,7 +20,7 @@ fn void main()
/* #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
%x = alloca [3 x i32], align 4
%y = alloca [3 x i32]*, align 8

View File

@@ -63,7 +63,7 @@ entry:
ret void
}
define void @main() #0 {
define void @foo.main() #0 {
entry:
%x = alloca i32, align 4
%y = alloca i32, align 4

View File

@@ -39,7 +39,7 @@ fn void main()
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @main() #0 {
define void @test.main() #0 {
entry:
%y = alloca i32, align 4
%x = alloca i32, align 4

View File

@@ -19,10 +19,10 @@ fn void main()
/* #expect: test.ll
@.str = private constant [4 x i8] c"%d\0A\00", align 1
; Function Attrs: nounwind
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define void @main() #0 {
define void @test.main() #0 {
entry:
%x = alloca [8 x i32], align 16
%"__idx$" = alloca i64, align 8
@@ -50,6 +50,7 @@ loop.cond: ; preds = %loop.body, %entry
%8 = load i64, i64* %"__idx$", align 8
%gt = icmp ugt i64 8, %8
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%9 = load i64, i64* %"__idx$", align 8
%10 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 %9
@@ -61,17 +62,31 @@ loop.body: ; preds = %loop.cond
%add = add i64 %13, 1
store i64 %add, i64* %"__idx$", align 8
br label %loop.cond
loop.exit: ; preds = %loop.cond
br label %cond
cond: ; preds = %assign, %loop.exit
%14 = phi i64 [ 0, %loop.exit ], [ %add1, %assign ]
%le = icmp sle i64 %14, 7
br i1 %le, label %assign, label %exit
assign: ; preds = %cond
%15 = getelementptr inbounds [8 x i32], [8 x i32]* %x, i64 0, i64 %14
store i32 123, i32* %15, align 4
%add1 = add i64 %14, 1
br label %cond
exit: ; preds = %cond
ret void
}
define i32 @main(i32 %0, i8** %1) #0 {
entry:
%"_$argv" = alloca i32, align 4
%"_$argc" = alloca i8**, align 8
store i32 %0, i32* %"_$argv", align 4
store i8** %1, i8*** %"_$argc", align 8
call void @test.main()
ret i32 0
}

View File

@@ -133,7 +133,7 @@ entry:
ret %Foo* %1
}
; Function Attrs: nounwind
define void @main() #0 {
define void @foo.main() #0 {
entry:
%x = alloca %Foo, align 4
%a = alloca i32, align 4

View File

@@ -14,7 +14,7 @@ fn void defer9() {}
fn void defer10() {}
fn void defer11() {}
fn int main(int argc)
fn int main(int argc, char** argv)
{
int a = 0;
{
@@ -48,75 +48,98 @@ fn int main(int argc)
/* #expect: foo.ll
define i32 @main(i32 %0) #0 {
define i32 @main(i32 %0, i8** %1) #0 {
entry:
%argc = alloca i32, align 4
%argv = alloca i8**, align 8
%a = alloca i32, align 4
store i32 %0, i32* %argc, align 4
store i8** %1, i8*** %argv, align 8
store i32 0, i32* %a, align 4
call void @foo.defer2()
%1 = load i32, i32* %a, align 4
%eq = icmp eq i32 %1, 1
%2 = load i32, i32* %a, align 4
%eq = icmp eq i32 %2, 1
br i1 %eq, label %if.then, label %if.exit
if.then: ; preds = %entry
br label %exit
if.exit: ; preds = %entry
call void @foo.defer1()
br label %exit
exit: ; preds = %if.exit, %if.then
br label %loop.cond
loop.cond: ; preds = %exit6, %exit
%2 = load i32, i32* %a, align 4
%intbool = icmp ne i32 %2, 0
%3 = load i32, i32* %a, align 4
%intbool = icmp ne i32 %3, 0
br i1 %intbool, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%3 = load i32, i32* %argc, align 4
%eq1 = icmp eq i32 %3, 1
%4 = load i32, i32* %argc, align 4
%eq1 = icmp eq i32 %4, 1
br i1 %eq1, label %if.then2, label %if.exit4
if.then2: ; preds = %loop.body
call void @foo.defer4()
br label %exit3
exit3: ; preds = %if.then2
br label %loop.exit
if.exit4: ; preds = %loop.body
call void @foo.defer6()
call void @foo.defer5()
br label %exit5
exit5: ; preds = %if.exit4
call void @foo.defer4()
br label %exit6
exit6: ; preds = %exit5
br label %loop.cond
loop.exit: ; preds = %exit3, %loop.cond
br label %loop.cond7
loop.cond7: ; preds = %loop.exit
%4 = load i32, i32* %a, align 4
%intbool8 = icmp ne i32 %4, 0
%5 = load i32, i32* %a, align 4
%intbool8 = icmp ne i32 %5, 0
br i1 %intbool8, label %loop.body9, label %loop.exit18
loop.body9: ; preds = %loop.cond7
%5 = load i32, i32* %argc, align 4
%eq10 = icmp eq i32 %5, 1
%6 = load i32, i32* %argc, align 4
%eq10 = icmp eq i32 %6, 1
br i1 %eq10, label %if.then11, label %if.exit13
if.then11: ; preds = %loop.body9
call void @foo.defer8()
br label %exit12
exit12: ; preds = %if.then11
br label %loop.exit18
if.exit13: ; preds = %loop.body9
call void @foo.defer10()
call void @foo.defer9()
br label %exit14
exit14: ; preds = %if.exit13
call void @foo.defer8()
br label %exit15
exit15: ; preds = %exit14
br label %loop.exit18
loop.exit18: ; preds = %exit15, %exit12, %loop.cond7
call void @foo.defer7()
br label %exit19
exit19: ; preds = %loop.exit18
call void @foo.defer3()
br label %exit20
exit20: ; preds = %exit19
ret i32 0
}

View File

@@ -6,7 +6,7 @@ fn void testA() {}
fn void testB() {}
fn void test3() {}
fn int main(int argc)
fn int main(int argc, char** argv)
{
int a = 0;
while (a)
@@ -26,49 +26,42 @@ fn int main(int argc)
// #expect: test.ll
define i32 @main(i32 %0) #0 {
define i32 @main(i32 %0, i8** %1) #0 {
entry:
%argc = alloca i32, align 4
%argv = alloca i8**, align 8
%a = alloca i32, align 4
store i32 %0, i32* %argc, align 4
store i8** %1, i8*** %argv, align 8
store i32 0, i32* %a, align 4
br label %loop.cond
loop.cond: ; preds = %exit3, %entry
%1 = load i32, i32* %a, align 4
%intbool = icmp ne i32 %1, 0
%2 = load i32, i32* %a, align 4
%intbool = icmp ne i32 %2, 0
br i1 %intbool, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%2 = load i32, i32* %argc, align 4
%eq = icmp eq i32 %2, 1
%3 = load i32, i32* %argc, align 4
%eq = icmp eq i32 %3, 1
br i1 %eq, label %if.then, label %if.exit
if.then: ; preds = %loop.body
call void @test.testA()
call void @test.testB()
br label %exit
exit: ; preds = %if.then
call void @test.test2()
br label %exit1
exit1: ; preds = %exit
br label %loop.exit
if.exit: ; preds = %loop.body
call void @test.test3()
call void @test.testA()
call void @test.testB()
br label %exit2
exit2: ; preds = %if.exit
call void @test.test2()
br label %exit3
exit3: ; preds = %exit2
br label %loop.cond
loop.exit: ; preds = %exit1, %loop.cond
ret i32 0
}

View File

@@ -10,7 +10,7 @@ fn void test7() {}
fn void test8() {}
fn void test9() {}
fn int main(int argc)
fn int main(int argc, char **argv)
{
defer test1();
int a = 0;
@@ -36,29 +36,30 @@ fn int main(int argc)
/* #expect: test.ll
define i32 @main(i32 %0) #0 {
define i32 @main(i32 %0, i8** %1) #0 {
entry:
%argc = alloca i32, align 4
%argv = alloca i8**, align 8
%a = alloca i32, align 4
store i32 %0, i32* %argc, align 4
store i8** %1, i8*** %argv, align 8
store i32 0, i32* %a, align 4
br label %loop.cond
loop.cond: ; preds = %exit3, %entry
%1 = load i32, i32* %a, align 4
%intbool = icmp ne i32 %1, 0
%2 = load i32, i32* %a, align 4
%intbool = icmp ne i32 %2, 0
br i1 %intbool, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%2 = load i32, i32* %argc, align 4
%eq = icmp eq i32 %2, 1
%3 = load i32, i32* %argc, align 4
%eq = icmp eq i32 %3, 1
br i1 %eq, label %if.then, label %if.exit
if.then: ; preds = %loop.body
%3 = load i32, i32* %a, align 4
%4 = load i32, i32* %argc, align 4
%add = add i32 %3, %4
%4 = load i32, i32* %a, align 4
%5 = load i32, i32* %argc, align 4
%add = add i32 %4, %5
call void @test.test2()
br label %exit
@@ -85,18 +86,18 @@ loop.exit: ; preds = %loop.cond
br label %loop.cond4
loop.cond4: ; preds = %loop.exit
%5 = load i32, i32* %a, align 4
%intbool5 = icmp ne i32 %5, 0
%6 = load i32, i32* %a, align 4
%intbool5 = icmp ne i32 %6, 0
br i1 %intbool5, label %loop.body6, label %loop.exit21
loop.body6: ; preds = %loop.cond4
%6 = load i32, i32* %argc, align 4
%eq7 = icmp eq i32 %6, 1
%7 = load i32, i32* %argc, align 4
%eq7 = icmp eq i32 %7, 1
br i1 %eq7, label %if.then8, label %if.exit13
if.then8: ; preds = %loop.body6
%7 = load i32, i32* %a, align 4
%add9 = add i32 %7, 2
%8 = load i32, i32* %a, align 4
%add9 = add i32 %8, 2
call void @test.test6()
br label %exit10
@@ -132,8 +133,8 @@ exit17: ; preds = %exit16
ret i32 4
loop.exit21: ; preds = %loop.cond4
%8 = load i32, i32* %argc, align 4
%add22 = add i32 0, %8
%9 = load i32, i32* %argc, align 4
%add22 = add i32 0, %9
call void @test.test5()
br label %exit23

View File

@@ -40,7 +40,7 @@ fn void main()
@.str = private constant [4 x i8] c"%d\0A\00", align 1
@.str.1 = private constant [8 x i8] c"%d, %d\0A\00", align 1
define void @main() #0 {
define void @foo.main() #0 {
entry:
%i = alloca i32, align 4
store i32 10, i32* %i, align 4

View File

@@ -34,7 +34,7 @@ extern fn int printf(char *fmt, ...);
// #expect: foo.ll
; Function Attrs: nounwind
define void @main() #0 {
define void @foo.main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8

View File

@@ -32,7 +32,7 @@ extern fn int printf(char *fmt, ...);
// #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
%i = alloca [3 x i32], align 4
%x = alloca %Foo, align 8

View File

@@ -48,7 +48,7 @@ fn void main()
/* #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
%i = alloca i32, align 4
%switch = alloca i32, align 4

View File

@@ -27,7 +27,7 @@ fn void main()
// #expect: foo.ll
define void @main() #0 {
define void @foo.main() #0 {
entry:
%i = alloca i32, align 4
store i32 10, i32* %i, align 4

View File

@@ -200,7 +200,7 @@ switch.exit26: ; preds = %switch.default25, %
}
; Function Attrs: nounwind
define void @main() #0 {
define void @mymodule.main() #0 {
entry:
call void @mymodule.test()
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.8, i32 0, i32 0))

View File

@@ -7,8 +7,19 @@ fn void main()
@.str = private constant [18 x i8] c"Hello\00 world! now\00", align 1
define void @main()
define void @string_escape.main() #0 {
entry:
%s = alloca i8*, align 8
store i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str, i32 0, i32 0), i8** %s, align 8
ret void
}
define i32 @main(i32 %0, i8** %1) #0 {
entry:
%"_$argv" = alloca i32, align 4
%"_$argc" = alloca i8**, align 8
store i32 %0, i32* %"_$argv", align 4
store i8** %1, i8*** %"_$argc", align 8
call void @string_escape.main()
ret i32 0
}

View File

@@ -1,10 +1,11 @@
// #target: x64-darwin
module foo;
fn void main()
fn int main()
{
char[2] x = "ab";
char[*] y = "abc";
return 0;
}
/* #expect: foo.ll
@@ -12,7 +13,7 @@ fn void main()
@.str = private constant [3 x i8] c"ab\00", align 1
@.str.1 = private constant [4 x i8] c"abc\00", align 1
define void @main() #0 {
define i32 @main() #0 {
entry:
%x = alloca [2 x i8], align 1
%y = alloca [3 x i8], align 1
@@ -20,5 +21,5 @@ entry:
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %0, i8* align 8 getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i32 2, i1 false)
%1 = bitcast [3 x i8]* %y to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %1, i8* align 8 getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i32 0, i32 0), i32 3, i1 false)
ret void
ret i32 0
}

View File

@@ -33,7 +33,7 @@ fn void main()
// #expect: mymodule.ll
define void @main() #0 {
define void @mymodule.main() #0 {
entry:
%y = alloca %"char[]", align 8
%z = alloca %"char[]", align 8

View File

@@ -175,7 +175,7 @@ loop.exit: ; preds = %loop.cond
}
; Function Attrs: nounwind
define void @main() #0 {
define void @foo.main() #0 {
entry:
%x = alloca %variant, align 8
%taddr = alloca i32, align 4

View File

@@ -153,11 +153,3 @@ entry:
%66 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.6, i32 0, i32 0), i32 %59, i32 %61, i32 %63, i32 %65)
ret void
}
; Function Attrs: nounwind
define void @main() #0 {
entry:
call void @vector_bit.testf()
call void @vector_bit.testi()
ret void
}

View File

@@ -182,8 +182,7 @@ entry:
ret void
}
; Function Attrs: nounwind
define void @main() #0 {
define void @vector_incdec.main() #0 {
entry:
call void @vector_incdec.testf()
call void @vector_incdec.testi()

View File

@@ -17,7 +17,7 @@ fn void main()
@vector_init.baz = global <4 x i32> <i32 1, i32 4, i32 5, i32 7>, align 16
; Function Attrs: nounwind
define void @main() #0 {
define void @vector_init.main() #0 {
entry:
%foo = alloca <4 x i32>, align 16
%z = alloca i32, align 4

View File

@@ -278,12 +278,3 @@ entry:
%91 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.12, i32 0, i32 0), i32 %84, i32 %86, i32 %88, i32 %90)
ret void
}
; Function Attrs: nounwind
define void @main() #0 {
entry:
call void @vector_ops.testf()
call void @vector_ops.testi()
call void @vector_ops.testb()
ret void
}