Rollback expression / macro unification.

This commit is contained in:
Christoffer Lerno
2024-05-23 23:02:57 +02:00
parent c1b57f9391
commit e90254da03
9 changed files with 177 additions and 122 deletions

View File

@@ -1016,6 +1016,13 @@ typedef struct
void *block_return_out;
} BlockExit;
typedef struct
{
AstId first_stmt;
BlockExit **block_exit_ref;
} ExprFuncBlock;
typedef struct
{
AstId first_stmt;
@@ -1023,9 +1030,12 @@ typedef struct
bool is_must_use : 1;
bool is_optional_return : 1;
bool had_optional_arg : 1;
DeclId macro_id;
Decl **params;
Decl *macro;
BlockExit **block_exit;
} ExprBlock;
} ExprMacroBlock;
typedef struct
{
@@ -1166,6 +1176,7 @@ struct Expr_
ExprEmbedExpr embed_expr; // 16
Expr** exec_expr; // 8
ExprAsmArg expr_asm_arg; // 24
ExprFuncBlock expr_block; // 4
ExprCompoundLiteral expr_compound_literal; // 16
Expr** expression_list; // 8
ExprGenericIdent generic_ident_expr;
@@ -1174,7 +1185,7 @@ struct Expr_
Expr** initializer_list; // 8
Expr *inner_expr; // 8
Decl *lambda_expr; // 8
ExprBlock expr_block; // 24
ExprMacroBlock macro_block; // 24
ExprMacroBody macro_body_expr; // 16;
OperatorOverload overload_expr; // 4
ExprPointerOffset pointer_offset_expr;

View File

@@ -449,13 +449,18 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
case EXPR_COND:
MACRO_COPY_EXPR_LIST(expr->cond_expr);
return expr;
case EXPR_EXPR_BLOCK:
MACRO_COPY_ASTID(expr->expr_block.first_stmt);
case EXPR_MACRO_BLOCK:
MACRO_COPY_DECL_LIST(expr->macro_block.params);
MACRO_COPY_ASTID(expr->macro_block.first_stmt);
fixup_decl(c, &expr->macro_block.macro);
return expr;
case EXPR_COMPOUND_LITERAL:
MACRO_COPY_EXPR(expr->expr_compound_literal.initializer);
MACRO_COPY_TYPE(expr->expr_compound_literal.type_info);
return expr;
case EXPR_EXPR_BLOCK:
MACRO_COPY_ASTID(expr->expr_block.first_stmt);
return expr;
case EXPR_POISONED:
return source_expr;
case EXPR_RETHROW:

View File

@@ -251,6 +251,7 @@ typedef enum
EXPR_INITIALIZER_LIST,
EXPR_LAMBDA,
EXPR_LAST_FAULT,
EXPR_MACRO_BLOCK,
EXPR_MACRO_BODY_EXPANSION,
EXPR_NOP,
EXPR_OPERATOR_CHARS,

View File

@@ -104,6 +104,7 @@ bool expr_may_addr(Expr *expr)
case EXPR_EXPR_BLOCK:
case EXPR_OPTIONAL:
case EXPR_FORCE_UNWRAP:
case EXPR_MACRO_BLOCK:
case EXPR_MACRO_BODY_EXPANSION:
case EXPR_NOP:
case EXPR_OPERATOR_CHARS:
@@ -218,6 +219,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
case EXPR_POST_UNARY:
case EXPR_SLICE_ASSIGN:
case EXPR_SLICE_COPY:
case EXPR_MACRO_BLOCK:
case EXPR_RETHROW:
return false;
case EXPR_IDENTIFIER:
@@ -508,9 +510,9 @@ bool expr_is_compile_time(Expr *expr)
{
case EXPR_CONST:
return true;
case EXPR_EXPR_BLOCK:
case EXPR_MACRO_BLOCK:
{
AstId current = expr->expr_block.first_stmt;
AstId current = expr->macro_block.first_stmt;
while (current)
{
if (!ast_is_compile_time(ast_next(&current))) return false;
@@ -740,6 +742,7 @@ bool expr_is_pure(Expr *expr)
case EXPR_OPTIONAL:
case EXPR_RETHROW:
case EXPR_HASH_IDENT:
case EXPR_MACRO_BLOCK:
case EXPR_INITIALIZER_LIST:
case EXPR_DESIGNATED_INITIALIZER_LIST:
case EXPR_POST_UNARY:

View File

@@ -24,6 +24,7 @@ static inline void llvm_emit_initialize_reference_bitstruct(GenContext *c, BEVal
static inline void llvm_emit_initialize_reference_list(GenContext *c, BEValue *ref, Expr *expr);
static inline void llvm_emit_initialize_reference_vector(GenContext *c, BEValue *ref, Type *real_type, Expr **elements);
static inline void llvm_emit_initializer_list_expr(GenContext *c, BEValue *value, Expr *expr);
static inline void llvm_emit_macro_block(GenContext *c, BEValue *be_value, Expr *expr);
static inline void llvm_emit_post_inc_dec(GenContext *c, BEValue *value, Expr *expr, int diff, bool allow_wrap);
static inline void llvm_emit_pre_inc_dec(GenContext *c, BEValue *value, Expr *expr, int diff, bool allow_wrap);
static inline void llvm_emit_return_block(GenContext *c, BEValue *be_value, Type *type, AstId current, BlockExit **block_exit);
@@ -6172,30 +6173,77 @@ DONE:
}
static inline void llvm_emit_expr_block(GenContext *c, BEValue *be_value, Expr *expr)
{
DEBUG_PUSH_LEXICAL_SCOPE(c, astptr(expr->expr_block.first_stmt)->span);
llvm_emit_return_block(c, be_value, expr->type, expr->expr_block.first_stmt, expr->expr_block.block_exit_ref);
DEBUG_POP_LEXICAL_SCOPE(c);
}
static inline void llvm_emit_macro_block(GenContext *c, BEValue *be_value, Expr *expr)
{
DebugScope *old_inline_location = c->debug.block_stack;
DebugScope updated;
if (expr->expr_block.macro_id && llvm_use_debug(c))
if (llvm_use_debug(c))
{
SourceSpan span = expr->span;
Decl *macro = declptr(expr->expr_block.macro_id);
Decl *macro = expr->macro_block.macro;
LLVMMetadataRef macro_def = llvm_debug_create_macro(c, macro);
LLVMMetadataRef loc = llvm_create_debug_location(c, span);
updated = (DebugScope) { .lexical_block = macro_def, .inline_loc = loc, .outline_loc = old_inline_location };
c->debug.block_stack = &updated;
}
DEBUG_PUSH_LEXICAL_SCOPE(c, astptr(expr->expr_block.first_stmt)->span);
llvm_emit_return_block(c, be_value, expr->type, expr->expr_block.first_stmt, expr->expr_block.block_exit);
bool is_unreachable = expr->expr_block.is_noreturn && c->current_block;
FOREACH_BEGIN(Decl *val, expr->macro_block.params)
// Skip vararg
if (!val) continue;
// In case we have a constant, we never do an emit. The value is already folded.
switch (val->var.kind)
{
case VARDECL_CONST:
case VARDECL_GLOBAL:
case VARDECL_LOCAL:
case VARDECL_MEMBER:
case VARDECL_LOCAL_CT:
case VARDECL_LOCAL_CT_TYPE:
case VARDECL_UNWRAPPED:
case VARDECL_REWRAPPED:
case VARDECL_ERASE:
case VARDECL_BITMEMBER:
UNREACHABLE
case VARDECL_PARAM_CT:
case VARDECL_PARAM_CT_TYPE:
case VARDECL_PARAM_EXPR:
continue;
case VARDECL_PARAM_REF:
case VARDECL_PARAM:
break;
}
Expr *init_expr = val->var.init_expr;
BEValue value;
c->debug.block_stack = old_inline_location;
llvm_emit_expr(c, &value, init_expr);
if (llvm_value_is_addr(&value) || val->var.is_written || val->var.is_addr || llvm_use_accurate_debug_info(c))
{
c->debug.block_stack = &updated;
llvm_emit_and_set_decl_alloca(c, val);
llvm_store_decl(c, val, &value);
continue;
}
val->is_value = true;
val->backend_value = value.value;
FOREACH_END();
c->debug.block_stack = &updated;
llvm_emit_return_block(c, be_value, expr->type, expr->macro_block.first_stmt, expr->macro_block.block_exit);
bool is_unreachable = expr->macro_block.is_noreturn && c->current_block;
if (is_unreachable)
{
llvm_emit_unreachable(c);
}
DEBUG_POP_LEXICAL_SCOPE(c);
c->debug.block_stack = old_inline_location;
}
LLVMValueRef llvm_emit_call_intrinsic(GenContext *context, unsigned intrinsic, LLVMTypeRef *types, unsigned type_count,
LLVMValueRef *values, unsigned arg_count)
{
@@ -6859,6 +6907,9 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
case EXPR_TRY_UNWRAP_CHAIN:
llvm_emit_try_unwrap_chain(c, value, expr);
return;
case EXPR_MACRO_BLOCK:
llvm_emit_macro_block(c, value, expr);
return;
case EXPR_TRY_UNWRAP:
llvm_emit_try_unwrap(c, value, expr);
return;

View File

@@ -540,6 +540,7 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
case EXPR_DESIGNATED_INITIALIZER_LIST:
case EXPR_DESIGNATOR:
case EXPR_EXPR_BLOCK:
case EXPR_MACRO_BLOCK:
case EXPR_OPTIONAL:
case EXPR_FORCE_UNWRAP:
case EXPR_INITIALIZER_LIST:
@@ -659,6 +660,7 @@ static bool expr_may_ref(Expr *expr)
case EXPR_OPTIONAL:
case EXPR_FORCE_UNWRAP:
case EXPR_INITIALIZER_LIST:
case EXPR_MACRO_BLOCK:
case EXPR_MACRO_BODY_EXPANSION:
case EXPR_NOP:
case EXPR_OPERATOR_CHARS:
@@ -2162,40 +2164,16 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
goto EXIT;
}
}
NOT_CT:;
Expr **list = NULL;
FOREACH_BEGIN(Decl *param, params)
if (!param) continue;
VarDeclKind kind = param->var.kind;
if (kind != VARDECL_PARAM_REF && kind != VARDECL_PARAM) continue;
Expr *decl_expr = expr_new(EXPR_DECL, param->span);
decl_expr->decl_expr = param;
decl_expr->type = param->type;
decl_expr->resolve_status = RESOLVE_DONE;
vec_add(list, decl_expr);
FOREACH_END();
Expr *new_block;
if (list)
{
call_expr->expr_kind = EXPR_EXPRESSION_LIST;
new_block = expr_new(EXPR_EXPR_BLOCK, call_expr->span);
new_block->type = call_expr->type;
vec_add(list, new_block);
call_expr->expression_list = list;
}
else
{
new_block = call_expr;
call_expr->expr_kind = EXPR_EXPR_BLOCK;
}
new_block->resolve_status = RESOLVE_DONE;
new_block->expr_block.macro_id = declid(decl);
new_block->expr_block.had_optional_arg = has_optional_arg;
new_block->expr_block.is_must_use = must_use;
new_block->expr_block.is_optional_return = optional_return;
new_block->expr_block.first_stmt = body->compound_stmt.first_stmt;
new_block->expr_block.block_exit = block_exit_ref;
new_block->expr_block.is_noreturn = is_no_return;
NOT_CT:
call_expr->expr_kind = EXPR_MACRO_BLOCK;
call_expr->macro_block.had_optional_arg = has_optional_arg;
call_expr->macro_block.is_must_use = must_use;
call_expr->macro_block.is_optional_return = optional_return;
call_expr->macro_block.first_stmt = body->compound_stmt.first_stmt;
call_expr->macro_block.macro = decl;
call_expr->macro_block.params = params;
call_expr->macro_block.block_exit = block_exit_ref;
call_expr->macro_block.is_noreturn = is_no_return;
EXIT:
assert(context->active_scope.defer_last == context->active_scope.defer_start);
context->active_scope = old_scope;
@@ -6823,7 +6801,7 @@ static inline bool sema_expr_analyse_expr_block(SemaContext *context, Type *infe
BlockExit **ref = CALLOCS(BlockExit*);
BlockExit **stored_block_exit = context->block_exit_ref;
context->block_exit_ref = ref;
expr->expr_block.block_exit = ref;
expr->expr_block.block_exit_ref = ref;
SCOPE_START_WITH_FLAGS(SCOPE_EXPR_BLOCK)
context->block_return_defer = context->active_scope.defer_last;
@@ -6871,7 +6849,6 @@ static inline bool sema_expr_analyse_expr_block(SemaContext *context, Type *infe
POP_NEXT();
context_pop_defers(context, &stmt->next);
SCOPE_END;
expr->expr_block.macro_id = 0;
context->expected_block_type = stored_block_type;
context->block_exit_ref = stored_block_exit;
context_pop_returns(context, saved_returns);
@@ -7982,6 +7959,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
case EXPR_ASM:
case EXPR_CONST:
case EXPR_NOP:
case EXPR_MACRO_BLOCK:
case EXPR_LAMBDA:
case EXPR_EXPR_BLOCK:
case EXPR_CT_IS_CONST:
@@ -8408,6 +8386,8 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr)
case EXPR_BITASSIGN:
// Created during semantic analysis
UNREACHABLE
case EXPR_MACRO_BLOCK:
UNREACHABLE
case EXPR_TYPEINFO:
expr->type = type_typeinfo;
return sema_resolve_type_info(context, expr->type_expr, RESOLVE_TYPE_DEFAULT);
@@ -8759,15 +8739,15 @@ bool sema_expr_check_discard(SemaContext *context, Expr *expr)
if (expr->expr_kind == EXPR_BINARY && expr->binary_expr.operator >= BINARYOP_ASSIGN) return true;
if (expr->expr_kind == EXPR_EXPR_BLOCK)
{
if (!expr->expr_block.macro_id)
if (type_is_void(expr->type)) return true;
RETURN_SEMA_ERROR(expr, "The block returns a value of type %s, which must be handled did you forget to assign it to something?",
type_quoted_error_string(expr->type));
}
if (expr->expr_kind == EXPR_MACRO_BLOCK)
{
if (expr->macro_block.is_must_use)
{
if (type_is_void(expr->type)) return true;
RETURN_SEMA_ERROR(expr, "The block returns a value of type %s, which must be handled did you forget to assign it to something?",
type_quoted_error_string(expr->type));
}
if (expr->expr_block.is_must_use)
{
if (expr->expr_block.is_optional_return)
if (expr->macro_block.is_optional_return)
{
RETURN_SEMA_ERROR(expr, "The macro returns %s, which is an optional and must be handled. "
"You can either assign it to a variable, rethrow it using '!', "
@@ -8776,7 +8756,7 @@ bool sema_expr_check_discard(SemaContext *context, Expr *expr)
}
RETURN_SEMA_ERROR(expr, "The called macro is marked `@nodiscard` meaning the result should be kept. You can still discard it using a void cast (e.g. '(void)the_call()') if you want.");
}
if (expr->expr_block.had_optional_arg) goto ERROR_ARGS;
if (expr->macro_block.had_optional_arg) goto ERROR_ARGS;
return true;
}
if (expr->expr_kind == EXPR_CALL)

View File

@@ -401,6 +401,14 @@ RETRY:
case EXPR_LAMBDA:
sema_trace_decl_liveness(expr->lambda_expr);
return;
case EXPR_MACRO_BLOCK:
{
FOREACH_BEGIN(Decl *val, expr->macro_block.params)
sema_trace_decl_liveness(val);
FOREACH_END();
sema_trace_stmt_chain_liveness(expr->macro_block.first_stmt);
return;
}
case EXPR_EXPR_BLOCK:
sema_trace_stmt_chain_liveness(expr->expr_block.first_stmt);
return;

View File

@@ -647,6 +647,7 @@ static inline bool sema_expr_valid_try_expression(Expr *expr)
case EXPR_EMBED:
case EXPR_EXPRESSION_LIST:
case EXPR_EXPR_BLOCK:
case EXPR_MACRO_BLOCK:
case EXPR_OPTIONAL:
case EXPR_FORCE_UNWRAP:
case EXPR_GENERIC_IDENT:
@@ -1227,8 +1228,8 @@ static inline bool sema_analyse_expr_stmt(SemaContext *context, Ast *statement)
case EXPR_CALL:
if (expr->call_expr.no_return) context->active_scope.jump_end = true;
break;
case EXPR_EXPR_BLOCK:
if (expr->expr_block.is_noreturn) context->active_scope.jump_end = true;
case EXPR_MACRO_BLOCK:
if (expr->macro_block.is_noreturn) context->active_scope.jump_end = true;
break;
case EXPR_CONST:
// Remove all const statements.

View File

@@ -47,48 +47,48 @@ entry:
%0 = load ptr, ptr %x1, align 8, !dbg !16
%1 = load atomic i32, ptr %0 seq_cst, align 4, !dbg !16
store i32 %1, ptr %x, align 4, !dbg !16
call void @llvm.dbg.declare(metadata ptr %y, metadata !21, metadata !DIExpression()), !dbg !22
call void @llvm.dbg.declare(metadata ptr %y, metadata !20, metadata !DIExpression()), !dbg !21
store ptr %a, ptr %x2, align 8
%2 = load ptr, ptr %x2, align 8, !dbg !23
%3 = load atomic volatile i32, ptr %2 monotonic, align 4, !dbg !23
store i32 %3, ptr %y, align 4, !dbg !23
%2 = load ptr, ptr %x2, align 8, !dbg !22
%3 = load atomic volatile i32, ptr %2 monotonic, align 4, !dbg !22
store i32 %3, ptr %y, align 4, !dbg !22
store ptr %a, ptr %x3, align 8
%4 = load i32, ptr %x, align 4, !dbg !27
%add = add i32 123, %4, !dbg !28
%4 = load i32, ptr %x, align 4, !dbg !25
%add = add i32 123, %4, !dbg !26
store i32 %add, ptr %value, align 4
%5 = load ptr, ptr %x3, align 8, !dbg !29
%6 = load i32, ptr %value, align 4, !dbg !29
store atomic i32 %6, ptr %5 seq_cst, align 4, !dbg !29
%5 = load ptr, ptr %x3, align 8, !dbg !27
%6 = load i32, ptr %value, align 4, !dbg !27
store atomic i32 %6, ptr %5 seq_cst, align 4, !dbg !27
store ptr %a, ptr %x4, align 8
%7 = load i32, ptr %y, align 4, !dbg !33
%add5 = add i32 33, %7, !dbg !34
%7 = load i32, ptr %y, align 4, !dbg !30
%add5 = add i32 33, %7, !dbg !31
store i32 %add5, ptr %value6, align 4
%8 = load ptr, ptr %x4, align 8, !dbg !35
%9 = load i32, ptr %value6, align 4, !dbg !35
store atomic volatile i32 %9, ptr %8 monotonic, align 4, !dbg !35
%10 = insertvalue %any undef, ptr %a, 0, !dbg !39
%11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.int" to i64), 1, !dbg !39
store %any %11, ptr %varargslots, align 16, !dbg !39
%12 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1), !dbg !40
ret void, !dbg !40
%8 = load ptr, ptr %x4, align 8, !dbg !32
%9 = load i32, ptr %value6, align 4, !dbg !32
store atomic volatile i32 %9, ptr %8 monotonic, align 4, !dbg !32
%10 = insertvalue %any undef, ptr %a, 0, !dbg !35
%11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.int" to i64), 1, !dbg !35
store %any %11, ptr %varargslots, align 16, !dbg !35
%12 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1), !dbg !36
ret void, !dbg !36
}
; Function Attrs: nounwind uwtable
define i32 @main(i32 %0, ptr %1) #0 !dbg !41 {
define i32 @main(i32 %0, ptr %1) #0 !dbg !37 {
entry:
%.anon = alloca i32, align 4
%.anon1 = alloca ptr, align 8
%.anon2 = alloca i32, align 4
%.anon3 = alloca ptr, align 8
store i32 %0, ptr %.anon, align 4
call void @llvm.dbg.declare(metadata ptr %.anon, metadata !47, metadata !DIExpression()), !dbg !48
call void @llvm.dbg.declare(metadata ptr %.anon, metadata !43, metadata !DIExpression()), !dbg !44
store ptr %1, ptr %.anon1, align 8
call void @llvm.dbg.declare(metadata ptr %.anon1, metadata !49, metadata !DIExpression()), !dbg !48
call void @llvm.dbg.declare(metadata ptr %.anon1, metadata !45, metadata !DIExpression()), !dbg !44
%2 = load i32, ptr %.anon, align 4
store i32 %2, ptr %.anon2, align 4
%3 = load ptr, ptr %.anon1, align 8
store ptr %3, ptr %.anon3, align 8
call void @test.main(), !dbg !50
ret i32 0, !dbg !54
call void @test.main(), !dbg !46
ret i32 0, !dbg !49
}
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
@@ -117,41 +117,36 @@ declare i1 @llvm.expect.i1(i1, i1) #2
!14 = !DILocalVariable(name: "x", scope: !6, file: !5, line: 13, type: !11, align: 4)
!15 = !DILocation(line: 13, column: 6, scope: !6)
!16 = !DILocation(line:
!17 = distinct !DILexicalBlock(scope: !19, file: !18,
!17 = distinct !DISubprogram(name: "@atomic_load", linkageName: "@atomic_load", scope: !18, file: !18,
!18 = !DIFile(filename: "mem.c3",
!19 = distinct !DISubprogram(name: "@atomic_load", linkageName: "@atomic_load", scope: !18
!20 = !DILocation(line: 13, column: 10, scope: !6)
!21 = !DILocalVariable(name: "y", scope: !6, file: !5, line: 14, type: !11, align: 4)
!22 = !DILocation(line: 14, column: 6, scope: !6)
!23 = !DILocation(line:
!24 = distinct !DILexicalBlock(scope: !25, file: !18
!25 = distinct !DISubprogram(name: "@atomic_load", linkageName: "@atomic_load", scope: !18
!26 = !DILocation(line: 14, column: 10, scope: !6)
!27 = !DILocation(line: 15, column: 25, scope: !6)
!28 = !DILocation(line: 15, column: 19, scope: !6)
!29 = !DILocation(line: 212, column: 20, scope: !30, inlinedAt: !32)
!30 = distinct !DILexicalBlock(scope: !31, file: !18, line:
!31 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !18
!32 = !DILocation(line: 15, column: 2, scope: !6)
!33 = !DILocation(line: 16, column: 24, scope: !6)
!34 = !DILocation(line: 16, column: 19, scope: !6)
!35 = !DILocation(line: 212, column: 20, scope: !36, inlinedAt: !38)
!36 = distinct !DILexicalBlock(scope: !37, file: !18, line: 212, column: 2)
!37 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !18, file: !18, line: 210, scopeLine: 210, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4
!38 = !DILocation(line: 16, column: 2, scope: !6)
!39 = !DILocation(line: 17, column: 20, scope: !6)
!40 = !DILocation(line: 17, column: 6, scope: !6)
!41 = distinct !DISubprogram(name: "_$main", linkageName: "main", scope: !5, file: !5, line: 10, type: !42, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !4, retainedNodes: !9)
!42 = !DISubroutineType(types: !43)
!43 = !{!11, !11, !44}
!44 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char**", baseType: !45, size: 64, align: 64, dwarfAddressSpace: 0)
!45 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char*", baseType: !46, size: 64, align: 64, dwarfAddressSpace: 0)
!46 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char)
!47 = !DILocalVariable(name: ".anon", arg: 1, scope: !41, file: !5, line: 10, type: !11)
!48 = !DILocation(line: 10, column: 9, scope: !41)
!49 = !DILocalVariable(name: ".anon", arg: 2, scope: !41, file: !5, line: 10, type: !44)
!50 = !DILocation(line: 18, column: 2, scope: !51, inlinedAt: !48)
!51 = distinct !DILexicalBlock(scope: !53, file: !52, line: 18, column: 2)
!52 = !DIFile(filename: "main_stub.c3"
!53 = distinct !DISubprogram(name: "@main_to_void_main", linkageName: "@main_to_void_main", scope: !52, file: !52, line: 16, scopeLine: 16, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition,
!54 = !DILocation(line: 19, column: 9, scope: !51, inlinedAt: !48)
!19 = !DILocation(line: 13, column: 10, scope: !6)
!20 = !DILocalVariable(name: "y", scope: !6, file: !5, line: 14, type: !11, align: 4)
!21 = !DILocation(line: 14, column: 6, scope: !6)
!22 = !DILocation(line:
!23 = distinct !DISubprogram(name: "@atomic_load", linkageName: "@atomic_load", scope: !18
!24 = !DILocation(line: 14, column: 10, scope: !6)
!25 = !DILocation(line: 15, column: 25, scope: !6)
!26 = !DILocation(line: 15, column: 19, scope: !6)
!27 = !DILocation(line: 212, column: 20, scope: !28, inlinedAt: !29)
!28 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !18
!29 = !DILocation(line: 15, column: 2, scope: !6)
!30 = !DILocation(line: 16, column: 24, scope: !6)
!31 = !DILocation(line: 16, column: 19, scope: !6)
!32 = !DILocation(line: 212, column: 20, scope: !33, inlinedAt: !34)
!33 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !18, file: !18, line: 210, scopeLine: 210, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4
!34 = !DILocation(line: 16, column: 2, scope: !6)
!35 = !DILocation(line: 17, column: 20, scope: !6)
!36 = !DILocation(line: 17, column: 6, scope: !6)
!37 = distinct !DISubprogram(name: "_$main", linkageName: "main", scope: !5, file: !5, line: 10, type: !38, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !4, retainedNodes: !9)
!38 = !DISubroutineType(types: !39)
!39 = !{!11, !11, !40}
!40 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char**", baseType: !41, size: 64, align: 64, dwarfAddressSpace: 0)
!41 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char*", baseType: !42, size: 64, align: 64, dwarfAddressSpace: 0)
!42 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char)
!43 = !DILocalVariable(name: ".anon", arg: 1, scope: !37, file: !5, line: 10, type: !11)
!44 = !DILocation(line: 10, column: 9, scope: !37)
!45 = !DILocalVariable(name: ".anon", arg: 2, scope: !37, file: !5, line: 10, type: !40)
!46 = !DILocation(line: 18, column: 2, scope: !47, inlinedAt: !44)
!47 = distinct !DISubprogram(name: "@main_to_void_main", linkageName: "@main_to_void_main", scope: !48, file: !48, line: 16, scopeLine: 16, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition
!48 = !DIFile(filename: "main_stub.c3", directory:
!49 = !DILocation(line: 19, column: 9, scope: !47, inlinedAt: !44)