mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
- $member.get supports bitstructs.
- $member.set for setting members without the *& trick. - io::struct_to_format now supports bitstructs.
This commit is contained in:
@@ -19,7 +19,7 @@ alias FloatType = double;
|
||||
|
||||
macro bool is_struct_with_default_print($Type)
|
||||
{
|
||||
return $Type.kindof == STRUCT
|
||||
return ($Type.kindof == STRUCT ||| $Type.kindof == BITSTRUCT)
|
||||
&&& !$defined($Type.to_format)
|
||||
&&& !$defined($Type.to_constant_string);
|
||||
}
|
||||
@@ -27,7 +27,7 @@ macro bool is_struct_with_default_print($Type)
|
||||
<*
|
||||
Introspect a struct and print it to a formatter
|
||||
|
||||
@require @typekind(value) == STRUCT : `This macro is only valid on macros`
|
||||
@require @typekind(value) == STRUCT || @typekind(value) == BITSTRUCT : `This macro is only valid on macros`
|
||||
*>
|
||||
macro usz? struct_to_format(value, Formatter* f, bool $force_dump)
|
||||
{
|
||||
@@ -40,7 +40,7 @@ macro usz? struct_to_format(value, Formatter* f, bool $force_dump)
|
||||
$if $member.nameof != "":
|
||||
total += f.printf("%s: ", $member.nameof)!;
|
||||
$endif
|
||||
$if ($force_dump &&& $member.typeid.kindof == STRUCT) |||
|
||||
$if ($force_dump &&& ($member.typeid.kindof == STRUCT || $member.typeid.kindof == BITSTRUCT)) |||
|
||||
is_struct_with_default_print($member.typeid):
|
||||
total += struct_to_format($member.get(value), f, $force_dump)!;
|
||||
$else
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
- Add `@allow_deprecated` attribute to functions to selectively allow deprecated declarations #2223.
|
||||
- Improve error message on pointer diff #2239.
|
||||
- Compile-time comparison of constant vectors. #1575.
|
||||
- $member.get supports bitstructs.
|
||||
- $member.set for setting members without the *& trick.
|
||||
|
||||
### Fixes
|
||||
- `-2147483648`, MIN literals work correctly.
|
||||
@@ -76,6 +78,7 @@
|
||||
- Add comparison with `==` for ZString types.
|
||||
- `is_array_or_slice_of_char` and `is_arrayptr_or_slice_of_char` are replaced by constant `@` variants.
|
||||
- `@pool` now has an optional `reserve` parameter, some minor changes to the temp_allocator API
|
||||
- io::struct_to_format now supports bitstructs.
|
||||
|
||||
## 0.7.2 Change list
|
||||
|
||||
|
||||
@@ -467,6 +467,7 @@ static void c_emit_expr(GenContext *c, CValue *value, Expr *expr)
|
||||
case EXPR_MACRO_BODY_EXPANSION:
|
||||
break;
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
break;
|
||||
case EXPR_NAMED_ARGUMENT:
|
||||
break;
|
||||
|
||||
@@ -3548,6 +3548,7 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc)
|
||||
case EXPR_DEFAULT_ARG:
|
||||
case EXPR_TYPECALL:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_RVALUE:
|
||||
case EXPR_CT_SUBSCRIPT:
|
||||
break;
|
||||
|
||||
@@ -335,6 +335,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
|
||||
}
|
||||
return expr;
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
fixup_decl(c, &expr->member_get_expr);
|
||||
break;
|
||||
case EXPR_SWIZZLE:
|
||||
|
||||
@@ -780,6 +780,7 @@ typedef enum
|
||||
EXPR_MAKE_ANY,
|
||||
EXPR_MAKE_SLICE,
|
||||
EXPR_MEMBER_GET,
|
||||
EXPR_MEMBER_SET,
|
||||
EXPR_NAMED_ARGUMENT,
|
||||
EXPR_NOP,
|
||||
EXPR_OPERATOR_CHARS,
|
||||
@@ -1421,6 +1422,7 @@ typedef enum
|
||||
TYPE_PROPERTY_QNAMEOF,
|
||||
TYPE_PROPERTY_RETURNS,
|
||||
TYPE_PROPERTY_SIZEOF,
|
||||
TYPE_PROPERTY_SET,
|
||||
TYPE_PROPERTY_TAGOF,
|
||||
TYPE_PROPERTY_HAS_TAGOF,
|
||||
TYPE_PROPERTY_VALUES,
|
||||
|
||||
@@ -65,6 +65,7 @@ const char *expr_kind_to_string(ExprKind kind)
|
||||
case EXPR_MAKE_ANY: return "make_any";
|
||||
case EXPR_MAKE_SLICE: return "make_slice";
|
||||
case EXPR_MEMBER_GET: return "member_get";
|
||||
case EXPR_MEMBER_SET: return "member_set";
|
||||
case EXPR_NAMED_ARGUMENT: return "named_argument";
|
||||
case EXPR_NOP: return "nop";
|
||||
case EXPR_OPERATOR_CHARS: return "operator_chars";
|
||||
@@ -223,6 +224,7 @@ bool expr_may_addr(Expr *expr)
|
||||
case EXPR_SUBSCRIPT:
|
||||
case EXPR_MEMBER_GET:
|
||||
return true;
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_SLICE:
|
||||
case EXPR_BENCHMARK_HOOK:
|
||||
case EXPR_TEST_HOOK:
|
||||
@@ -328,6 +330,7 @@ bool expr_is_runtime_const(Expr *expr)
|
||||
case EXPR_MACRO_BLOCK:
|
||||
case EXPR_RETHROW:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_BITACCESS:
|
||||
case EXPR_COND:
|
||||
case EXPR_PTR_ACCESS:
|
||||
@@ -828,6 +831,7 @@ bool expr_is_pure(Expr *expr)
|
||||
case EXPR_TYPEINFO:
|
||||
case EXPR_LAST_FAULT:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
return true;
|
||||
case EXPR_TWO:
|
||||
return expr_is_pure(expr->two_expr.first) && expr_is_pure(expr->two_expr.last);
|
||||
|
||||
@@ -6983,6 +6983,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
case EXPR_ASM:
|
||||
case EXPR_DESIGNATOR:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_NAMED_ARGUMENT:
|
||||
case EXPR_BUILTIN:
|
||||
case EXPR_OPERATOR_CHARS:
|
||||
|
||||
@@ -631,6 +631,7 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
|
||||
case EXPR_MAKE_ANY:
|
||||
case EXPR_MAKE_SLICE:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_NAMED_ARGUMENT:
|
||||
case EXPR_NOP:
|
||||
case EXPR_OPERATOR_CHARS:
|
||||
@@ -694,6 +695,7 @@ static bool expr_may_ref(Expr *expr)
|
||||
case EXPR_DEFAULT_ARG:
|
||||
case EXPR_TYPECALL:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_EXT_TRUNC:
|
||||
case EXPR_PTR_ACCESS:
|
||||
case EXPR_VECTOR_TO_ARRAY:
|
||||
@@ -3188,21 +3190,14 @@ INLINE bool sema_call_may_not_have_attributes(SemaContext *context, Expr *expr)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_call_analyse_member_get(SemaContext *context, Expr *expr)
|
||||
INLINE bool sema_analyse_member_get_set_common(SemaContext *context, Decl *decl, Expr *inner, bool *is_bitrstruct)
|
||||
{
|
||||
if (vec_size(expr->call_expr.arguments) != 1)
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "Expected a single argument to '.get'.");
|
||||
}
|
||||
if (!sema_call_may_not_have_attributes(context, expr)) return false;
|
||||
Expr *get = exprptr(expr->call_expr.function);
|
||||
Expr *inner = expr->call_expr.arguments[0];
|
||||
if (!sema_analyse_expr(context, inner)) return false;
|
||||
Decl *decl = get->member_get_expr;
|
||||
Type *type = type_flatten(inner->type);
|
||||
if (type->type_kind != TYPE_STRUCT && type->type_kind != TYPE_UNION)
|
||||
bool type_is_bitstruct = type->type_kind == TYPE_BITSTRUCT;
|
||||
if (!type_is_bitstruct && type->type_kind != TYPE_STRUCT && type->type_kind != TYPE_UNION)
|
||||
{
|
||||
RETURN_SEMA_ERROR(inner, "This value does not match the member.");
|
||||
RETURN_SEMA_ERROR(inner, "The member does not belong to the type %s.", type_quoted_error_string(inner->type));
|
||||
}
|
||||
Decl **members = type->decl->strukt.members;
|
||||
ArrayIndex index = -1;
|
||||
@@ -3216,9 +3211,47 @@ static inline bool sema_call_analyse_member_get(SemaContext *context, Expr *expr
|
||||
}
|
||||
if (index == -1)
|
||||
{
|
||||
RETURN_SEMA_ERROR(inner, "This value does not match the member.");
|
||||
RETURN_SEMA_ERROR(inner, "The member does not belong to the type %s.", type_quoted_error_string(inner->type));
|
||||
}
|
||||
expr->expr_kind = EXPR_ACCESS_RESOLVED;
|
||||
*is_bitrstruct = type_is_bitstruct;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_call_analyse_member_set(SemaContext *context, Expr *expr)
|
||||
{
|
||||
if (vec_size(expr->call_expr.arguments) != 2)
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "Expected two arguments to '.set'.");
|
||||
}
|
||||
if (!sema_call_may_not_have_attributes(context, expr)) return false;
|
||||
Expr *get = exprptr(expr->call_expr.function);
|
||||
Decl *decl = get->member_get_expr;
|
||||
Expr *inner = expr->call_expr.arguments[0];
|
||||
bool is_bitstruct;
|
||||
if (!sema_analyse_member_get_set_common(context, decl, inner, &is_bitstruct)) return false;
|
||||
Expr *arg = expr->call_expr.arguments[1];
|
||||
Expr *access = expr_new_expr(is_bitstruct ? EXPR_BITACCESS : EXPR_ACCESS_RESOLVED, expr);
|
||||
access->access_resolved_expr = (ExprResolvedAccess) { .parent = inner, .ref = decl };
|
||||
access->type = decl->type;
|
||||
access->resolve_status = RESOLVE_DONE;
|
||||
expr->expr_kind = EXPR_BINARY;
|
||||
expr->binary_expr = (ExprBinary) { .left = exprid(access), .right = exprid(arg), .operator = BINARYOP_ASSIGN };
|
||||
return sema_expr_analyse_binary(context, NULL, expr, NULL);
|
||||
}
|
||||
|
||||
static inline bool sema_call_analyse_member_get(SemaContext *context, Expr *expr)
|
||||
{
|
||||
if (vec_size(expr->call_expr.arguments) != 1)
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "Expected a single argument to '.get'.");
|
||||
}
|
||||
if (!sema_call_may_not_have_attributes(context, expr)) return false;
|
||||
Expr *get = exprptr(expr->call_expr.function);
|
||||
Decl *decl = get->member_get_expr;
|
||||
Expr *inner = expr->call_expr.arguments[0];
|
||||
bool is_bitstruct;
|
||||
if (!sema_analyse_member_get_set_common(context, decl, inner, &is_bitstruct)) return false;
|
||||
expr->expr_kind = is_bitstruct ? EXPR_BITACCESS : EXPR_ACCESS_RESOLVED;
|
||||
expr->access_resolved_expr = (ExprResolvedAccess) { .parent = inner, .ref = decl };
|
||||
expr->type = decl->type;
|
||||
return true;
|
||||
@@ -3228,19 +3261,17 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr, bool
|
||||
if (no_match_ref) *no_match_ref = true;
|
||||
Expr *func_expr = exprptr(expr->call_expr.function);
|
||||
if (!sema_analyse_expr_value(context, func_expr)) return false;
|
||||
if (func_expr->expr_kind == EXPR_MACRO_BODY_EXPANSION)
|
||||
{
|
||||
return sema_call_analyse_body_expansion(context, expr);
|
||||
}
|
||||
if (func_expr->expr_kind == EXPR_MEMBER_GET)
|
||||
{
|
||||
return sema_call_analyse_member_get(context, expr);
|
||||
}
|
||||
bool optional = func_expr->type && IS_OPTIONAL(func_expr);
|
||||
Decl *decl;
|
||||
Expr *struct_var = NULL;
|
||||
switch (func_expr->expr_kind)
|
||||
{
|
||||
case EXPR_MACRO_BODY_EXPANSION:
|
||||
return sema_call_analyse_body_expansion(context, expr);
|
||||
case EXPR_MEMBER_GET:
|
||||
return sema_call_analyse_member_get(context, expr);
|
||||
case EXPR_MEMBER_SET:
|
||||
return sema_call_analyse_member_set(context, expr);
|
||||
case EXPR_TYPECALL:
|
||||
return sema_expr_analyse_typecall(context, expr);
|
||||
case EXPR_BUILTIN:
|
||||
@@ -4548,6 +4579,11 @@ static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *e
|
||||
expr->expr_kind = EXPR_TYPECALL;
|
||||
expr->type_call_expr = (ExprTypeCall) { .type = decl, .property = type_property };
|
||||
return true;
|
||||
case TYPE_PROPERTY_SET:
|
||||
expr->expr_kind = EXPR_MEMBER_SET;
|
||||
expr->member_get_expr = decl;
|
||||
expr->type = type_void;
|
||||
return true;
|
||||
case TYPE_PROPERTY_GET:
|
||||
expr->expr_kind = EXPR_MEMBER_GET;
|
||||
expr->member_get_expr = decl;
|
||||
@@ -5082,6 +5118,7 @@ static bool sema_expr_rewrite_to_typeid_property(SemaContext *context, Expr *exp
|
||||
case TYPE_PROPERTY_EXTNAMEOF:
|
||||
case TYPE_PROPERTY_FROM_ORDINAL:
|
||||
case TYPE_PROPERTY_GET:
|
||||
case TYPE_PROPERTY_SET:
|
||||
case TYPE_PROPERTY_HAS_TAGOF:
|
||||
case TYPE_PROPERTY_INF:
|
||||
case TYPE_PROPERTY_IS_EQ:
|
||||
@@ -5235,6 +5272,7 @@ static bool sema_type_property_is_valid_for_type(Type *original_type, TypeProper
|
||||
case TYPE_PROPERTY_NONE:
|
||||
return false;
|
||||
case TYPE_PROPERTY_GET:
|
||||
case TYPE_PROPERTY_SET:
|
||||
return type == type_member;
|
||||
case TYPE_PROPERTY_INF:
|
||||
case TYPE_PROPERTY_NAN:
|
||||
@@ -5390,6 +5428,7 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
case TYPE_PROPERTY_GET:
|
||||
case TYPE_PROPERTY_SET:
|
||||
UNREACHABLE
|
||||
case TYPE_PROPERTY_MEMBERSOF:
|
||||
{
|
||||
@@ -10093,6 +10132,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
||||
case EXPR_TYPEID_INFO:
|
||||
case EXPR_TYPECALL:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_SPLAT:
|
||||
case EXPR_EXT_TRUNC:
|
||||
case EXPR_INT_TO_BOOL:
|
||||
@@ -10445,6 +10485,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
|
||||
case EXPR_MACRO_BODY:
|
||||
case EXPR_MACRO_BODY_EXPANSION:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_NAMED_ARGUMENT:
|
||||
case EXPR_NOP:
|
||||
case EXPR_OPERATOR_CHARS:
|
||||
@@ -10744,8 +10785,10 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr, bool mutat
|
||||
if (!expr_ok(expr)) return false;
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_MEMBER_SET:
|
||||
RETURN_SEMA_ERROR(expr, "Expected two parameters to 'set', e.g. '$member.set(v, new_value)'.");
|
||||
case EXPR_MEMBER_GET:
|
||||
RETURN_SEMA_ERROR(expr, "Expected a parameter to 'get', e.g. '$member.get(value)'.");
|
||||
RETURN_SEMA_ERROR(expr, "Expected a parameter to 'get', e.g. '$member.get(v)'.");
|
||||
case EXPR_MACRO_BODY_EXPANSION:
|
||||
if (!expr->body_expansion_expr.first_stmt)
|
||||
{
|
||||
@@ -10993,6 +11036,7 @@ IDENT_CHECK:;
|
||||
case EXPR_MAKE_ANY:
|
||||
case EXPR_MAKE_SLICE:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_NAMED_ARGUMENT:
|
||||
case EXPR_NOP:
|
||||
case EXPR_OPERATOR_CHARS:
|
||||
|
||||
@@ -260,6 +260,7 @@ RETRY:
|
||||
case EXPR_SUBSCRIPT_ASSIGN:
|
||||
case EXPR_OPERATOR_CHARS:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_NAMED_ARGUMENT:
|
||||
case UNRESOLVED_EXPRS:
|
||||
UNREACHABLE
|
||||
|
||||
@@ -762,6 +762,7 @@ static inline bool sema_expr_valid_try_expression(Expr *expr)
|
||||
case EXPR_LAST_FAULT:
|
||||
case EXPR_TYPECALL:
|
||||
case EXPR_MEMBER_GET:
|
||||
case EXPR_MEMBER_SET:
|
||||
case EXPR_SPLAT:
|
||||
case EXPR_MAKE_ANY:
|
||||
case EXPR_DISCARD:
|
||||
|
||||
@@ -184,6 +184,7 @@ void symtab_init(uint32_t capacity)
|
||||
type_property_list[TYPE_PROPERTY_PARENTOF] = KW_DEF("parentof");
|
||||
type_property_list[TYPE_PROPERTY_QNAMEOF] = KW_DEF("qnameof");
|
||||
type_property_list[TYPE_PROPERTY_RETURNS] = KW_DEF("returns");
|
||||
type_property_list[TYPE_PROPERTY_SET] = KW_DEF("set");
|
||||
type_property_list[TYPE_PROPERTY_SIZEOF] = KW_DEF("sizeof");
|
||||
type_property_list[TYPE_PROPERTY_TAGOF] = KW_DEF("tagof");
|
||||
type_property_list[TYPE_PROPERTY_HAS_TAGOF] = KW_DEF("has_tagof");
|
||||
|
||||
232
test/test_suite/bitstruct/bitstruct_with_get_set.c3t
Normal file
232
test/test_suite/bitstruct/bitstruct_with_get_set.c3t
Normal file
@@ -0,0 +1,232 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
import std;
|
||||
bitstruct Foo (Printable) : long
|
||||
{
|
||||
int a : 2..4;
|
||||
uint b: 5..10;
|
||||
}
|
||||
fn usz? Foo.to_format(&self, Formatter *f) @dynamic => io::struct_to_format(*self, f, false);
|
||||
|
||||
fn int main()
|
||||
{
|
||||
Foo d = { 1, 11 };
|
||||
Foo.membersof[0].set(d, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define i64 @test.Foo.to_format(ptr %0, ptr %1, ptr %2) #0 {
|
||||
entry:
|
||||
%reterr = alloca i64, align 8
|
||||
%value = alloca i64, align 8
|
||||
%total = alloca i64, align 8
|
||||
%error_var = alloca i64, align 8
|
||||
%retparam = alloca i64, align 8
|
||||
%error_var1 = alloca i64, align 8
|
||||
%varargslots = alloca [1 x %any], align 16
|
||||
%taddr = alloca %"char[]", align 8
|
||||
%retparam2 = alloca i64, align 8
|
||||
%error_var8 = alloca i64, align 8
|
||||
%varargslots9 = alloca [1 x %any], align 16
|
||||
%taddr10 = alloca i32, align 4
|
||||
%retparam11 = alloca i64, align 8
|
||||
%error_var18 = alloca i64, align 8
|
||||
%retparam19 = alloca i64, align 8
|
||||
%error_var26 = alloca i64, align 8
|
||||
%varargslots27 = alloca [1 x %any], align 16
|
||||
%taddr28 = alloca %"char[]", align 8
|
||||
%retparam29 = alloca i64, align 8
|
||||
%error_var36 = alloca i64, align 8
|
||||
%varargslots37 = alloca [1 x %any], align 16
|
||||
%taddr39 = alloca i32, align 4
|
||||
%retparam40 = alloca i64, align 8
|
||||
%retparam47 = alloca i64, align 8
|
||||
%3 = load i64, ptr %1, align 8
|
||||
store i64 %3, ptr %value, align 8
|
||||
%4 = call i64 @std.io.Formatter.print(ptr %retparam, ptr %2, ptr @.str, i64 2)
|
||||
%not_err = icmp eq i64 %4, 0
|
||||
%5 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
||||
br i1 %5, label %after_check, label %assign_optional
|
||||
|
||||
assign_optional: ; preds = %entry
|
||||
store i64 %4, ptr %error_var, align 8
|
||||
br label %guard_block
|
||||
|
||||
after_check: ; preds = %entry
|
||||
br label %noerr_block
|
||||
|
||||
guard_block: ; preds = %assign_optional
|
||||
%6 = load i64, ptr %error_var, align 8
|
||||
store i64 %6, ptr %reterr, align 8
|
||||
br label %err_retblock
|
||||
|
||||
noerr_block: ; preds = %after_check
|
||||
%7 = load i64, ptr %retparam, align 8
|
||||
store i64 %7, ptr %total, align 8
|
||||
%8 = load i64, ptr %total, align 8
|
||||
store %"char[]" { ptr @.str.2, i64 1 }, ptr %taddr, align 8
|
||||
%9 = insertvalue %any undef, ptr %taddr, 0
|
||||
%10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.String" to i64), 1
|
||||
store %any %10, ptr %varargslots, align 16
|
||||
%11 = call i64 @std.io.Formatter.printf(ptr %retparam2, ptr %2, ptr @.str.1, i64 4, ptr %varargslots, i64 1)
|
||||
%not_err3 = icmp eq i64 %11, 0
|
||||
%12 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true)
|
||||
br i1 %12, label %after_check5, label %assign_optional4
|
||||
|
||||
assign_optional4: ; preds = %noerr_block
|
||||
store i64 %11, ptr %error_var1, align 8
|
||||
br label %guard_block6
|
||||
|
||||
after_check5: ; preds = %noerr_block
|
||||
br label %noerr_block7
|
||||
|
||||
guard_block6: ; preds = %assign_optional4
|
||||
%13 = load i64, ptr %error_var1, align 8
|
||||
store i64 %13, ptr %reterr, align 8
|
||||
br label %err_retblock
|
||||
|
||||
noerr_block7: ; preds = %after_check5
|
||||
%14 = load i64, ptr %retparam2, align 8
|
||||
%add = add i64 %8, %14
|
||||
store i64 %add, ptr %total, align 8
|
||||
%15 = load i64, ptr %total, align 8
|
||||
%16 = load i64, ptr %value, align 8
|
||||
%shl = shl i64 %16, 59
|
||||
%ashr = ashr i64 %shl, 61
|
||||
%trunc = trunc i64 %ashr to i32
|
||||
store i32 %trunc, ptr %taddr10, align 4
|
||||
%17 = insertvalue %any undef, ptr %taddr10, 0
|
||||
%18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.int" to i64), 1
|
||||
store %any %18, ptr %varargslots9, align 16
|
||||
%19 = call i64 @std.io.Formatter.printf(ptr %retparam11, ptr %2, ptr @.str.3, i64 2, ptr %varargslots9, i64 1)
|
||||
%not_err12 = icmp eq i64 %19, 0
|
||||
%20 = call i1 @llvm.expect.i1(i1 %not_err12, i1 true)
|
||||
br i1 %20, label %after_check14, label %assign_optional13
|
||||
|
||||
assign_optional13: ; preds = %noerr_block7
|
||||
store i64 %19, ptr %error_var8, align 8
|
||||
br label %guard_block15
|
||||
|
||||
after_check14: ; preds = %noerr_block7
|
||||
br label %noerr_block16
|
||||
|
||||
guard_block15: ; preds = %assign_optional13
|
||||
%21 = load i64, ptr %error_var8, align 8
|
||||
store i64 %21, ptr %reterr, align 8
|
||||
br label %err_retblock
|
||||
|
||||
noerr_block16: ; preds = %after_check14
|
||||
%22 = load i64, ptr %retparam11, align 8
|
||||
%add17 = add i64 %15, %22
|
||||
store i64 %add17, ptr %total, align 8
|
||||
%23 = load i64, ptr %total, align 8
|
||||
%24 = call i64 @std.io.Formatter.print(ptr %retparam19, ptr %2, ptr @.str.4, i64 2)
|
||||
%not_err20 = icmp eq i64 %24, 0
|
||||
%25 = call i1 @llvm.expect.i1(i1 %not_err20, i1 true)
|
||||
br i1 %25, label %after_check22, label %assign_optional21
|
||||
|
||||
assign_optional21: ; preds = %noerr_block16
|
||||
store i64 %24, ptr %error_var18, align 8
|
||||
br label %guard_block23
|
||||
|
||||
after_check22: ; preds = %noerr_block16
|
||||
br label %noerr_block24
|
||||
|
||||
guard_block23: ; preds = %assign_optional21
|
||||
%26 = load i64, ptr %error_var18, align 8
|
||||
store i64 %26, ptr %reterr, align 8
|
||||
br label %err_retblock
|
||||
|
||||
noerr_block24: ; preds = %after_check22
|
||||
%27 = load i64, ptr %retparam19, align 8
|
||||
%add25 = add i64 %23, %27
|
||||
store i64 %add25, ptr %total, align 8
|
||||
%28 = load i64, ptr %total, align 8
|
||||
store %"char[]" { ptr @.str.6, i64 1 }, ptr %taddr28, align 8
|
||||
%29 = insertvalue %any undef, ptr %taddr28, 0
|
||||
%30 = insertvalue %any %29, i64 ptrtoint (ptr @"$ct.String" to i64), 1
|
||||
store %any %30, ptr %varargslots27, align 16
|
||||
%31 = call i64 @std.io.Formatter.printf(ptr %retparam29, ptr %2, ptr @.str.5, i64 4, ptr %varargslots27, i64 1)
|
||||
%not_err30 = icmp eq i64 %31, 0
|
||||
%32 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true)
|
||||
br i1 %32, label %after_check32, label %assign_optional31
|
||||
|
||||
assign_optional31: ; preds = %noerr_block24
|
||||
store i64 %31, ptr %error_var26, align 8
|
||||
br label %guard_block33
|
||||
|
||||
after_check32: ; preds = %noerr_block24
|
||||
br label %noerr_block34
|
||||
|
||||
guard_block33: ; preds = %assign_optional31
|
||||
%33 = load i64, ptr %error_var26, align 8
|
||||
store i64 %33, ptr %reterr, align 8
|
||||
br label %err_retblock
|
||||
|
||||
noerr_block34: ; preds = %after_check32
|
||||
%34 = load i64, ptr %retparam29, align 8
|
||||
%add35 = add i64 %28, %34
|
||||
store i64 %add35, ptr %total, align 8
|
||||
%35 = load i64, ptr %total, align 8
|
||||
%36 = load i64, ptr %value, align 8
|
||||
%lshrl = lshr i64 %36, 5
|
||||
%37 = and i64 63, %lshrl
|
||||
%trunc38 = trunc i64 %37 to i32
|
||||
store i32 %trunc38, ptr %taddr39, align 4
|
||||
%38 = insertvalue %any undef, ptr %taddr39, 0
|
||||
%39 = insertvalue %any %38, i64 ptrtoint (ptr @"$ct.uint" to i64), 1
|
||||
store %any %39, ptr %varargslots37, align 16
|
||||
%40 = call i64 @std.io.Formatter.printf(ptr %retparam40, ptr %2, ptr @.str.7, i64 2, ptr %varargslots37, i64 1)
|
||||
%not_err41 = icmp eq i64 %40, 0
|
||||
%41 = call i1 @llvm.expect.i1(i1 %not_err41, i1 true)
|
||||
br i1 %41, label %after_check43, label %assign_optional42
|
||||
|
||||
assign_optional42: ; preds = %noerr_block34
|
||||
store i64 %40, ptr %error_var36, align 8
|
||||
br label %guard_block44
|
||||
|
||||
after_check43: ; preds = %noerr_block34
|
||||
br label %noerr_block45
|
||||
|
||||
guard_block44: ; preds = %assign_optional42
|
||||
%42 = load i64, ptr %error_var36, align 8
|
||||
store i64 %42, ptr %reterr, align 8
|
||||
br label %err_retblock
|
||||
|
||||
noerr_block45: ; preds = %after_check43
|
||||
%43 = load i64, ptr %retparam40, align 8
|
||||
%add46 = add i64 %35, %43
|
||||
store i64 %add46, ptr %total, align 8
|
||||
%44 = load i64, ptr %total, align 8
|
||||
%45 = call i64 @std.io.Formatter.print(ptr %retparam47, ptr %2, ptr @.str.8, i64 2)
|
||||
%not_err48 = icmp eq i64 %45, 0
|
||||
%46 = call i1 @llvm.expect.i1(i1 %not_err48, i1 true)
|
||||
br i1 %46, label %after_check50, label %assign_optional49
|
||||
|
||||
assign_optional49: ; preds = %noerr_block45
|
||||
store i64 %45, ptr %reterr, align 8
|
||||
br label %err_retblock
|
||||
|
||||
after_check50: ; preds = %noerr_block45
|
||||
%47 = load i64, ptr %retparam47, align 8
|
||||
%add51 = add i64 %44, %47
|
||||
store i64 %add51, ptr %0, align 8
|
||||
ret i64 0
|
||||
|
||||
err_retblock: ; preds = %assign_optional49, %guard_block44, %guard_block33, %guard_block23, %guard_block15, %guard_block6, %guard_block
|
||||
%48 = load i64, ptr %reterr, align 8
|
||||
ret i64 %48
|
||||
}
|
||||
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
%d = alloca i64, align 8
|
||||
store i64 356, ptr %d, align 8
|
||||
%0 = load i64, ptr %d, align 8
|
||||
%1 = and i64 %0, -29
|
||||
%2 = or i64 %1, 12
|
||||
store i64 %2, ptr %d, align 8
|
||||
ret i32 0
|
||||
}
|
||||
Reference in New Issue
Block a user