zig icon indicating copy to clipboard operation
zig copied to clipboard

Corrupted slice in release build

Open ghost opened this issue 4 years ago • 20 comments
trafficstars

I've been hammering at a weird bug for a while and finally got a reduced case. See the code and output. I have a string slice being passed around and at some point the slice value (ptr and/or len?) is getting corrupted. union(enum)s are involved but I don't know if that's relevant.

The weirdest thing is the problem will shift or go away if you change seemingly innocuous bits of code (see the comments I left throughout the code sample). This makes it a bit tricky to pare the test case down even further.

This problem only happens in ReleaseSmall and ReleaseFast. It has been around since at least 0.6.0. I'm sure the release build of my projects used to work at some point, I'm going to guess it broke some time after 0.5.0?

Apologies for the size of the code snippet, a lot of it is types. Scroll down and start with the main function and it's pretty easy to follow I think.

const std = @import("std");

pub const TempRef = struct {
    index: usize,
    is_weak: bool,
};

pub const BuiltinEnum = struct {
    name: []const u8,
};

pub const ParamType = union(enum) {
    boolean,
    buffer,
    // one way to make the problem go away: make `one_of` a plain
    // enum value with no data (get rid of BuiltinEnum)
    one_of: BuiltinEnum,
};

pub const CallArg = struct {
    value: Expression,
};

pub const Expression = union(enum) {
    literal_boolean: bool,
    literal_enum_value: EnumLiteral,
};

pub const EnumLiteral = struct {
    label: []const u8,
};

pub const ExpressionResult = union(enum) {
    temp_buffer: TempRef,
    literal_boolean: bool,
    literal_enum_value: []const u8,
};

fn commitCalleeParam(
    result: ExpressionResult,
    callee_param_type: ParamType,
) ExpressionResult {
    // another way to make the problem go away: copy `result` into
    // a local variable here, and use the copy below
    switch (callee_param_type) {
        .boolean => {
            return result;
        },
        .buffer => {
            // another way to make the problem go away: replace this with
            // a simple `return result;`
            return ExpressionResult{
                .temp_buffer = .{ .index = 0, .is_weak = false },
            };
        },
        .one_of => {
            return result;
        },
    }
}

fn genExpression(expr: Expression) ExpressionResult {
    switch (expr) {
        .literal_boolean => |value| {
            return ExpressionResult{
                .literal_boolean = value,
            };
        },
        .literal_enum_value => |v| {
            std.debug.warn("literal enum \"{}\"\n", .{v.label});
            const result: ExpressionResult = .{
                .literal_enum_value = v.label,
            };
            // another way to make the problem go away: comment out this
            // switch block (which does nothing but print something)
            switch (result) {
                .literal_enum_value => |w| {
                    std.debug.warn("in result \"{}\"\n", .{w});
                },
                else => {},
            }
            return result;
        },
    }
}

pub fn main() void {
    var param: ParamType = .{
        .one_of = .{ .name = "FilterType" },
    };
    var arg: CallArg = .{
        .value = .{
            .literal_enum_value = .{
                .label = "what happened to me",
            },
        },
    };

    const result = genExpression(arg.value);

    switch (result) {
        .literal_enum_value => |w| {
            std.debug.warn("after genExpression \"{}\"\n", .{w});
        },
        else => {},
    }

    // comment out all the code below this point and the problem goes away as
    // well (it even affects the output of the print BEFORE this point)
    const derp = commitCalleeParam(result, param);

    switch (derp) {
        .literal_enum_value => |w| {
            std.debug.warn("after commit \"{}\"\n", .{w});
        },
        else => {},
    }
}
$ zig version
0.7.0+9af53f8e0
$ zig run -O ReleaseFast asdf.zig
literal enum "what happened to me"
in result "what happened to me"
after genExpression "w"
after commit "w"

I'm on a Mac.

ghost avatar Dec 07 '20 08:12 ghost

I ran out of time to debug this but I've got a pretty good idea of what's wrong. The SROA pass kicks in and becomes confused by the is_weak: bool field, the pass gets something wrong (that doesn't trip any assertion) and ends up writing the is_weak part of .temp_buffer = .{ .index = 0, .is_weak = false }, into result's slice len field.

Running the following LLVM IR code with opt -debug -S -O3 < file.ll gives something like this, I've highlighted the important parts:

; ModuleID = 'foo'
source_filename = "foo"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%"[]u8" = type { i8*, i64 }
%std.builtin.StackTrace = type { i64, %"[]usize" }
%"[]usize" = type { i64*, i64 }
%std.target.LinuxVersionRange = type { %std.builtin.Range, %std.builtin.Version }
%std.builtin.Range = type { %std.builtin.Version, %std.builtin.Version }
%std.builtin.Version = type { i32, i32, i32 }
%std.target.Set = type { [3 x i64] }
%std.target.Model = type { %"[]u8", %"?[:0]const u8", %std.target.Set }
%"?[:0]const u8" = type { %"[]u8", i1 }
%std.mutex.Dummy = type { i1 }
%ParamType = type { %BuiltinEnum, i2 }
%BuiltinEnum = type { %"[]u8" }
%CallArg = type { %Expression }
%Expression = type { %EnumLiteral, i1 }
%EnumLiteral = type { %"[]u8" }
%ExpressionResult = type { %TempRef, i2 }
%TempRef = type { i64, i1 }
%"?std.mutex.Held" = type { %std.mutex.Held, i1 }
%std.mutex.Held = type { %std.mutex.Dummy* }
%"?usize" = type { i64, i1 }
%"struct:96:29" = type { %"[]u8", %"[]u8" }
%std.fs.file.File = type { i32 }
%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)" = type { %std.fs.file.File }
%"[]std.target.x86.Feature" = type { i8*, i64 }
%std.fmt.FormatOptions = type { %"?usize", %"?usize", i2, i8 }
%"std.os.struct:4571:51" = type { i64 }

@panic.1 = internal unnamed_addr constant void (%"[]u8"*, %std.builtin.StackTrace*)* @panic, align 8
@output_mode = internal unnamed_addr constant i2 0, align 1
@link_libc = internal unnamed_addr constant i1 false, align 1
@os = internal unnamed_addr constant { <{ i6, [3 x i8] }>, { %std.target.LinuxVersionRange, i2, [3 x i8] } } { <{ i6, [3 x i8] }> <{ i6 8, [3 x i8] undef }>, { %std.target.LinuxVersionRange, i2, [3 x i8] } { %std.target.LinuxVersionRange { %std.builtin.Range { %std.builtin.Version { i32 4, i32 19, i32 0 }, %std.builtin.Version { i32 4, i32 19, i32 0 } }, %std.builtin.Version { i32 2, i32 28, i32 0 } }, i2 -2, [3 x i8] undef } }, align 4
@0 = internal unnamed_addr constant [10 x i8] c"ivybridge\00", align 1
@ivybridge = internal unnamed_addr constant { %"[]u8", { %"[]u8", i1, [7 x i8] }, %std.target.Set } { %"[]u8" { i8* getelementptr inbounds ([10 x i8], [10 x i8]* @0, i64 0, i64 0), i64 9 }, { %"[]u8", i1, [7 x i8] } { %"[]u8" { i8* getelementptr inbounds ([10 x i8], [10 x i8]* @0, i64 0, i64 0), i64 9 }, i1 true, [7 x i8] undef }, %std.target.Set { [3 x i64] [i64 685253747084886276, i64 2310381932816443448, i64 21] } }, align 8
@cpu = internal unnamed_addr constant { <{ i6, [7 x i8] }>, %std.target.Model*, %std.target.Set } { <{ i6, [7 x i8] }> <{ i6 31, [7 x i8] undef }>, %std.target.Model* bitcast ({ %"[]u8", { %"[]u8", i1, [7 x i8] }, %std.target.Set }* @ivybridge to %std.target.Model*), %std.target.Set { [3 x i64] [i64 685253747084886276, i64 2332477718471452728, i64 21] } }, align 8
@abi = internal unnamed_addr constant i5 1, align 1
@current = internal unnamed_addr constant { { <{ i6, [7 x i8] }>, %std.target.Model*, %std.target.Set }, { <{ i6, [3 x i8] }>, { %std.target.LinuxVersionRange, i2, [3 x i8] } }, <{ i5, [3 x i8] }> } { { <{ i6, [7 x i8] }>, %std.target.Model*, %std.target.Set } { <{ i6, [7 x i8] }> <{ i6 31, [7 x i8] undef }>, %std.target.Model* bitcast ({ %"[]u8", { %"[]u8", i1, [7 x i8] }, %std.target.Set }* @ivybridge to %std.target.Model*), %std.target.Set { [3 x i64] [i64 685253747084886276, i64 2332477718471452728, i64 21] } }, { <{ i6, [3 x i8] }>, { %std.target.LinuxVersionRange, i2, [3 x i8] } } { <{ i6, [3 x i8] }> <{ i6 8, [3 x i8] undef }>, { %std.target.LinuxVersionRange, i2, [3 x i8] } { %std.target.LinuxVersionRange { %std.builtin.Range { %std.builtin.Version { i32 4, i32 19, i32 0 }, %std.builtin.Version { i32 4, i32 19, i32 0 } }, %std.builtin.Version { i32 2, i32 28, i32 0 } }, i2 -2, [3 x i8] undef } }, <{ i5, [3 x i8] }> <{ i5 1, [3 x i8] undef }> }, align 8
@arch = internal unnamed_addr constant i6 31, align 1
@1 = internal unnamed_addr constant [7 x i8] c"_start\00", align 1
@start_sym_name = internal unnamed_addr constant [7 x i8]* @1, align 8
@single_threaded = internal unnamed_addr constant i1 true, align 1
@mode = internal unnamed_addr constant i2 0, align 1
@runtime_safety = internal unnamed_addr constant i1 true, align 1
@lock_init = internal unnamed_addr constant i1 false, align 1
@stderr_mutex = internal unnamed_addr global %std.mutex.Dummy zeroinitializer, align 1
@is_mips = internal unnamed_addr constant i1 false, align 1
@is_sparc = internal unnamed_addr constant i1 false, align 1
@mode.2 = internal unnamed_addr constant i1 false, align 1
@is_async = internal unnamed_addr constant i1 false, align 1
@is_windows = internal unnamed_addr constant i1 false, align 1
@assert = internal unnamed_addr constant void (i1)* @std.debug.assert, align 8
@errno = internal unnamed_addr constant i12 (i64)* @std.os.linux.getErrno, align 8
@unexpected_error_tracing = internal unnamed_addr constant i1 true, align 1
@strip_debug_info = internal unnamed_addr constant i1 true, align 1
@assert.3 = internal unnamed_addr constant void (i1)* @std.debug.assert, align 8
@assert.4 = internal unnamed_addr constant void (i1)* @std.debug.assert, align 8
@2 = internal unnamed_addr constant %ParamType { %BuiltinEnum undef, i2 1 }, align 8
@3 = internal unnamed_addr constant [20 x i8] c"what happened to me\00", align 1
@4 = internal unnamed_addr constant %CallArg { %Expression { %EnumLiteral { %"[]u8" { i8* getelementptr inbounds ([20 x i8], [20 x i8]* @3, i64 0, i64 0), i64 19 } }, i1 true } }, align 8
@5 = internal unnamed_addr constant [31 x i8] c"access of inactive union field\00", align 1
@6 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([31 x i8], [31 x i8]* @5, i64 0, i64 0), i64 30 }, align 8
@7 = internal unnamed_addr constant [3 x i64] zeroinitializer, align 8
@8 = internal unnamed_addr constant [17 x i8] c"division by zero\00", align 1
@9 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([17 x i8], [17 x i8]* @8, i64 0, i64 0), i64 16 }, align 8
@10 = internal unnamed_addr constant [45 x i8] c"remainder division by zero or negative value\00", align 1
@11 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([45 x i8], [45 x i8]* @10, i64 0, i64 0), i64 44 }, align 8
@12 = internal unnamed_addr constant [28 x i8] c"integer cast truncated bits\00", align 1
@13 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([28 x i8], [28 x i8]* @12, i64 0, i64 0), i64 27 }, align 8
@14 = internal unnamed_addr constant [20 x i8] c"index out of bounds\00", align 1
@15 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([20 x i8], [20 x i8]* @14, i64 0, i64 0), i64 19 }, align 8
@16 = internal unnamed_addr constant [25 x i8] c"reached unreachable code\00", align 1
@17 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([25 x i8], [25 x i8]* @16, i64 0, i64 0), i64 24 }, align 8
@18 = internal unnamed_addr constant %ExpressionResult { %TempRef undef, i2 0 }, align 8
@19 = internal unnamed_addr constant [18 x i8] c"deadlock detected\00", align 1
@20 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([18 x i8], [18 x i8]* @19, i64 0, i64 0), i64 17 }, align 8
@21 = internal unnamed_addr constant %"?std.mutex.Held" { %std.mutex.Held undef, i1 false }, align 8
@22 = internal unnamed_addr constant { %"?usize", %"?usize", i2, <{ i8, [6 x i8] }> } { %"?usize" { i64 undef, i1 false }, %"?usize" { i64 undef, i1 false }, i2 -2, <{ i8, [6 x i8] }> <{ i8 32, [6 x i8] undef }> }, align 8
@23 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@24 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@25 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@26 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@27 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@28 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@29 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@30 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@31 = internal unnamed_addr constant [17 x i8] c"integer overflow\00", align 1
@32 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([17 x i8], [17 x i8]* @31, i64 0, i64 0), i64 16 }, align 8
@33 = internal unnamed_addr constant [51 x i8] c"attempt to cast negative value to unsigned integer\00", align 1
@34 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([51 x i8], [51 x i8]* @33, i64 0, i64 0), i64 50 }, align 8
@35 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@36 = internal unnamed_addr constant [31 x i8] c"cast causes pointer to be null\00", align 1
@37 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([31 x i8], [31 x i8]* @36, i64 0, i64 0), i64 30 }, align 8
@38 = internal unnamed_addr constant [43 x i8] c"shift amount is greater than the type size\00", align 1
@39 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([43 x i8], [43 x i8]* @38, i64 0, i64 0), i64 42 }, align 8
@40 = internal unnamed_addr constant { %"?usize", %"?usize", i2, <{ i8, [6 x i8] }> } { %"?usize" { i64 undef, i1 false }, %"?usize" { i64 undef, i1 false }, i2 -2, <{ i8, [6 x i8] }> <{ i8 32, [6 x i8] undef }> }, align 8
@41 = internal unnamed_addr constant [22 x i8] c"unexpected errno: {}\0A\00", align 1
@42 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([22 x i8], [22 x i8]* @41, i64 0, i64 0), i64 18 }, align 8
@43 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@44 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@45 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@46 = internal unnamed_addr constant %"?usize" { i64 undef, i1 false }, align 8
@47 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([22 x i8], [22 x i8]* @41, i64 0, i64 20), i64 1 }, align 8
@48 = internal unnamed_addr constant { %"?usize", %"?usize", i2, <{ i8, [6 x i8] }> } { %"?usize" { i64 undef, i1 false }, %"?usize" { i64 undef, i1 false }, i2 -2, <{ i8, [6 x i8] }> <{ i8 32, [6 x i8] undef }> }, align 8
@49 = internal unnamed_addr constant [49 x i8] c"Unable to dump stack trace: debug info stripped\0A\00", align 1
@50 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([49 x i8], [49 x i8]* @49, i64 0, i64 0), i64 48 }, align 8

; Function Attrs: nobuiltin noreturn nounwind
define internal fastcc void @panic(%"[]u8"* nonnull readonly align 8 %0, %std.builtin.StackTrace* align 8 %1) unnamed_addr #0 {
Entry:
  %error_return_trace = alloca %std.builtin.StackTrace*, align 8
  store %std.builtin.StackTrace* %1, %std.builtin.StackTrace** %error_return_trace, align 8
  br label %WhileCond

WhileCond:                                        ; preds = %WhileCond, %Entry
  br label %WhileCond
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.debug.assert(i1 %0) unnamed_addr #1 {
Entry:
  %ok = alloca i1, align 1
  store i1 %0, i1* %ok, align 1
  %1 = load i1, i1* %ok, align 1
  %2 = icmp eq i1 %1, false
  br i1 %2, label %Then, label %Else

Then:                                             ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @17, %std.builtin.StackTrace* null)
  unreachable

Else:                                             ; preds = %Entry
  br label %EndIf

EndIf:                                            ; preds = %Else
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i12 @std.os.linux.getErrno(i64 %0) unnamed_addr #1 {
Entry:
  %result = alloca i12, align 2
  %signed_r = alloca i64, align 8
  %r = alloca i64, align 8
  store i64 %0, i64* %r, align 8
  %1 = load i64, i64* %r, align 8
  store i64 %1, i64* %signed_r, align 8
  %2 = load i64, i64* %signed_r, align 8
  %3 = sext i64 %2 to i65
  %4 = icmp sgt i65 %3, -4096
  br i1 %4, label %BoolAndTrue, label %BoolAndFalse

BoolAndTrue:                                      ; preds = %Entry
  %5 = load i64, i64* %signed_r, align 8
  %6 = icmp slt i64 %5, 0
  br label %BoolAndFalse

BoolAndFalse:                                     ; preds = %BoolAndTrue, %Entry
  %7 = phi i1 [ %4, %Entry ], [ %6, %BoolAndTrue ]
  br i1 %7, label %Then, label %Else

Then:                                             ; preds = %BoolAndFalse
  %8 = load i64, i64* %signed_r, align 8
  %9 = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 0, i64 %8)
  %10 = extractvalue { i64, i1 } %9, 0
  %11 = extractvalue { i64, i1 } %9, 1
  br i1 %11, label %OverflowFail, label %OverflowOk

Else:                                             ; preds = %BoolAndFalse
  store i12 0, i12* %result, align 2
  br label %EndIf

EndIf:                                            ; preds = %Else, %CastShortenOk
  %12 = load i12, i12* %result, align 2
  ret i12 %12

OverflowFail:                                     ; preds = %Then
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk:                                       ; preds = %Then
  %13 = icmp sge i64 %10, 0
  br i1 %13, label %SignCastOk, label %SignCastFail

SignCastOk:                                       ; preds = %OverflowOk
  %14 = trunc i64 %10 to i12
  %15 = zext i12 %14 to i64
  %16 = icmp eq i64 %10, %15
  br i1 %16, label %CastShortenOk, label %CastShortenFail

SignCastFail:                                     ; preds = %OverflowOk
  call fastcc void @panic(%"[]u8"* @34, %std.builtin.StackTrace* null)
  unreachable

CastShortenOk:                                    ; preds = %SignCastOk
  store i12 %14, i12* %result, align 2
  br label %EndIf

CastShortenFail:                                  ; preds = %SignCastOk
  call fastcc void @panic(%"[]u8"* @13, %std.builtin.StackTrace* null)
  unreachable
}

; Function Attrs: nobuiltin noinline nounwind alignstack(16)
define void @_start() #2 {
Entry:
  %param = alloca %ParamType, align 8
  %arg = alloca %CallArg, align 8
  %result = alloca %ExpressionResult, align 8
  %old = alloca %"[]u8", align 8
  %derp = alloca %ExpressionResult, align 8
  %0 = alloca %"struct:96:29", align 8
  %1 = bitcast %ParamType* %param to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %1, i8* align 8 bitcast (%ParamType* @2 to i8*), i64 24, i1 false)
  %2 = bitcast %CallArg* %arg to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %2, i8* align 8 bitcast (%CallArg* @4 to i8*), i64 24, i1 false)
  %3 = getelementptr inbounds %CallArg, %CallArg* %arg, i32 0, i32 0
  call fastcc void @genExpression(%ExpressionResult* sret %result, %Expression* %3)
  %4 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result, i32 0, i32 1
  %5 = load i2, i2* %4, align 1
  %6 = icmp eq i2 %5, -2
  br i1 %6, label %UnionCheckOk, label %UnionCheckFail

UnionCheckOk:                                     ; preds = %Entry
  %7 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result, i32 0, i32 0
  %8 = bitcast %TempRef* %7 to %"[]u8"*
  %9 = bitcast %"[]u8"* %8 to i8*
  %10 = bitcast %"[]u8"* %old to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %10, i8* align 8 %9, i64 16, i1 false)
  call fastcc void @commitCalleeParam(%ExpressionResult* sret %derp, %ExpressionResult* %result, %ParamType* %param)
  %11 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result, i32 0, i32 1
  %12 = load i2, i2* %11, align 1
  %13 = icmp eq i2 %12, -2
  br i1 %13, label %UnionCheckOk1, label %UnionCheckFail2

UnionCheckFail:                                   ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @6, %std.builtin.StackTrace* null)
  unreachable

UnionCheckOk1:                                    ; preds = %UnionCheckOk
  %14 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result, i32 0, i32 0
  %15 = bitcast %TempRef* %14 to %"[]u8"*
  %16 = getelementptr inbounds %"struct:96:29", %"struct:96:29"* %0, i32 0, i32 0
  %17 = bitcast %"[]u8"* %15 to i8*
  %18 = bitcast %"[]u8"* %16 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %18, i8* align 8 %17, i64 16, i1 false)
  %19 = getelementptr inbounds %"struct:96:29", %"struct:96:29"* %0, i32 0, i32 1
  %20 = bitcast %"[]u8"* %old to i8*
  %21 = bitcast %"[]u8"* %19 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %21, i8* align 8 %20, i64 16, i1 false)
  call fastcc void @std.debug.print(%"struct:96:29"* %0)
  ret void

UnionCheckFail2:                                  ; preds = %UnionCheckOk
  call fastcc void @panic(%"[]u8"* @6, %std.builtin.StackTrace* null)
  unreachable
}

; Function Attrs: argmemonly nounwind willreturn
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #3

; Function Attrs: nobuiltin nounwind
define internal fastcc void @genExpression(%ExpressionResult* nonnull sret %0, %Expression* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %value = alloca i1, align 1
  %v = alloca %EnumLiteral, align 8
  %result = alloca %ExpressionResult, align 8
  %2 = getelementptr inbounds %Expression, %Expression* %1, i32 0, i32 1
  %3 = load i1, i1* %2, align 1
  switch i1 %3, label %SwitchElse [
    i1 false, label %SwitchProng
    i1 true, label %SwitchProng1
  ]

SwitchProng:                                      ; preds = %Entry
  %4 = getelementptr inbounds %Expression, %Expression* %1, i32 0, i32 0
  %5 = bitcast %EnumLiteral* %4 to i1*
  %6 = load i1, i1* %5, align 1
  store i1 %6, i1* %value, align 1
  %7 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %0, i32 0, i32 1
  store i2 1, i2* %7, align 1
  %8 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %0, i32 0, i32 0
  %9 = bitcast %TempRef* %8 to i1*
  %10 = load i1, i1* %value, align 1
  store i1 %10, i1* %9, align 1
  ret void

SwitchProng1:                                     ; preds = %Entry
  %11 = getelementptr inbounds %Expression, %Expression* %1, i32 0, i32 0
  %12 = bitcast %EnumLiteral* %11 to i8*
  %13 = bitcast %EnumLiteral* %v to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %13, i8* align 8 %12, i64 16, i1 false)
  %14 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result, i32 0, i32 1
  store i2 -2, i2* %14, align 1
  %15 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result, i32 0, i32 0
  %16 = bitcast %TempRef* %15 to %"[]u8"*
  %17 = getelementptr inbounds %EnumLiteral, %EnumLiteral* %v, i32 0, i32 0
  %18 = bitcast %"[]u8"* %17 to i8*
  %19 = bitcast %"[]u8"* %16 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %19, i8* align 8 %18, i64 16, i1 false)
  %20 = bitcast %ExpressionResult* %result to i8*
  %21 = bitcast %ExpressionResult* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %21, i8* align 8 %20, i64 24, i1 false)
  ret void

SwitchElse:                                       ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @17, %std.builtin.StackTrace* null)
  unreachable
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @commitCalleeParam(%ExpressionResult* nonnull sret %0, %ExpressionResult* nonnull readonly align 8 %1, %ParamType* nonnull readonly align 8 %2) unnamed_addr #1 {
Entry:
  %rr = alloca %ExpressionResult, align 8
  %3 = getelementptr inbounds %ParamType, %ParamType* %2, i32 0, i32 1
  %4 = load i2, i2* %3, align 1
  switch i2 %4, label %SwitchElse [
    i2 0, label %SwitchProng
    i2 1, label %SwitchProng1
    i2 -2, label %SwitchProng2
  ]

SwitchProng:                                      ; preds = %Entry
  %5 = bitcast %ExpressionResult* %1 to i8*
  %6 = bitcast %ExpressionResult* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %6, i8* align 8 %5, i64 24, i1 false)
  ret void

SwitchProng1:                                     ; preds = %Entry
  %7 = bitcast %ExpressionResult* %rr to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %7, i8* align 8 bitcast (%ExpressionResult* @18 to i8*), i64 24, i1 false)
  %8 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %rr, i32 0, i32 1
  %9 = load i2, i2* %8, align 1
  %10 = icmp eq i2 %9, 0
  br i1 %10, label %UnionCheckOk, label %UnionCheckFail

SwitchProng2:                                     ; preds = %Entry
  %11 = bitcast %ExpressionResult* %1 to i8*
  %12 = bitcast %ExpressionResult* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %12, i8* align 8 %11, i64 24, i1 false)
  ret void

SwitchElse:                                       ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @17, %std.builtin.StackTrace* null)
  unreachable

UnionCheckOk:                                     ; preds = %SwitchProng1
  %13 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %rr, i32 0, i32 0
  %14 = getelementptr inbounds %TempRef, %TempRef* %13, i32 0, i32 0
  store i64 0, i64* %14, align 8
  %15 = getelementptr inbounds %TempRef, %TempRef* %13, i32 0, i32 1
  store i1 true, i1* %15, align 1
  %16 = bitcast %ExpressionResult* %rr to i8*
  %17 = bitcast %ExpressionResult* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %17, i8* align 8 %16, i64 24, i1 false)
  ret void

UnionCheckFail:                                   ; preds = %SwitchProng1
  call fastcc void @panic(%"[]u8"* @6, %std.builtin.StackTrace* null)
  unreachable
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.debug.print(%"struct:96:29"* nonnull readonly align 8 %0) unnamed_addr #1 {
Entry:
  %held = alloca %std.mutex.Held, align 8
  %1 = alloca %std.fs.file.File, align 4
  %stderr = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %2 = alloca %"struct:96:29", align 8
  %3 = alloca i16, align 2
  call fastcc void @std.mutex.Dummy.acquire(%std.mutex.Held* sret %held, %std.mutex.Dummy* @stderr_mutex)
  call fastcc void @std.io.getStdErr(%std.fs.file.File* sret %1)
  call fastcc void @std.fs.file.File.writer(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* sret %stderr, %std.fs.file.File* %1)
  %4 = bitcast %"struct:96:29"* %0 to i8*
  %5 = bitcast %"struct:96:29"* %2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %5, i8* align 8 %4, i64 32, i1 false)
  %6 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %stderr, %"struct:96:29"* %0)
  store i16 %6, i16* %3, align 2
  %7 = icmp ne i16 %6, 0
  br i1 %7, label %UnwrapErrError, label %UnwrapErrOk

UnwrapErrError:                                   ; preds = %Entry
  call fastcc void @std.mutex.Held.release(%std.mutex.Held* %held)
  ret void

UnwrapErrOk:                                      ; preds = %Entry
  br label %UnwrapErrEnd

UnwrapErrEnd:                                     ; preds = %UnwrapErrOk
  call fastcc void @std.mutex.Held.release(%std.mutex.Held* %held)
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @"std.target.Feature.feature_set_fns(std.target.x86.Feature).featureSet"(%std.target.Set* nonnull sret %0, %"[]std.target.x86.Feature"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %x = alloca %std.target.Set, align 8
  %i = alloca i64, align 8
  %feature = alloca i8, align 1
  call fastcc void @std.target.Set.empty_workaround(%std.target.Set* sret %x)
  store i64 0, i64* %i, align 8
  %2 = getelementptr inbounds %"[]std.target.x86.Feature", %"[]std.target.x86.Feature"* %1, i32 0, i32 1
  %3 = load i64, i64* %2, align 8
  br label %ForCond

ForCond:                                          ; preds = %ForBody, %Entry
  %4 = load i64, i64* %i, align 8
  %5 = icmp ult i64 %4, %3
  br i1 %5, label %ForBody, label %ForEnd

ForBody:                                          ; preds = %ForCond
  %6 = getelementptr inbounds %"[]std.target.x86.Feature", %"[]std.target.x86.Feature"* %1, i32 0, i32 0
  %7 = load i8*, i8** %6, align 8
  %8 = getelementptr inbounds i8, i8* %7, i64 %4
  %9 = load i8, i8* %8, align 1
  store i8 %9, i8* %feature, align 1
  %10 = load i8, i8* %feature, align 1
  call fastcc void @std.target.Set.addFeature(%std.target.Set* %x, i8 %10)
  %11 = add nuw i64 %4, 1
  store i64 %11, i64* %i, align 8
  br label %ForCond

ForEnd:                                           ; preds = %ForCond
  %12 = bitcast %std.target.Set* %x to i8*
  %13 = bitcast %std.target.Set* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %13, i8* align 8 %12, i64 24, i1 false)
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.target.Set.empty_workaround(%std.target.Set* nonnull sret %0) unnamed_addr #1 {
Entry:
  %1 = getelementptr inbounds %std.target.Set, %std.target.Set* %0, i32 0, i32 0
  %2 = bitcast [3 x i64]* %1 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %2, i8* align 8 bitcast ([3 x i64]* @7 to i8*), i64 24, i1 false)
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.target.Set.addFeature(%std.target.Set* nonnull align 8 %0, i8 %1) unnamed_addr #1 {
Entry:
  %usize_index = alloca i8, align 1
  %bit_index = alloca i6, align 1
  %set = alloca %std.target.Set*, align 8
  %arch_feature_index = alloca i8, align 1
  store %std.target.Set* %0, %std.target.Set** %set, align 8
  store i8 %1, i8* %arch_feature_index, align 1
  %2 = load i8, i8* %arch_feature_index, align 1
  br i1 false, label %DivZeroFail, label %DivZeroOk

DivZeroFail:                                      ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @9, %std.builtin.StackTrace* null)
  unreachable

DivZeroOk:                                        ; preds = %Entry
  %3 = udiv i8 %2, 64
  store i8 %3, i8* %usize_index, align 1
  %4 = load i8, i8* %arch_feature_index, align 1
  br i1 false, label %RemZeroFail, label %RemZeroOk

RemZeroOk:                                        ; preds = %DivZeroOk
  %5 = urem i8 %4, 64
  %6 = trunc i8 %5 to i6
  %7 = zext i6 %6 to i8
  %8 = icmp eq i8 %5, %7
  br i1 %8, label %CastShortenOk, label %CastShortenFail

RemZeroFail:                                      ; preds = %DivZeroOk
  call fastcc void @panic(%"[]u8"* @11, %std.builtin.StackTrace* null)
  unreachable

CastShortenOk:                                    ; preds = %RemZeroOk
  store i6 %6, i6* %bit_index, align 1
  %9 = load %std.target.Set*, %std.target.Set** %set, align 8
  %10 = getelementptr inbounds %std.target.Set, %std.target.Set* %9, i32 0, i32 0
  %11 = load i8, i8* %usize_index, align 1
  %12 = zext i8 %11 to i64
  %13 = icmp ult i64 %12, 3
  br i1 %13, label %BoundsCheckOk, label %BoundsCheckFail

CastShortenFail:                                  ; preds = %RemZeroOk
  call fastcc void @panic(%"[]u8"* @13, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckFail:                                  ; preds = %CastShortenOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk:                                    ; preds = %CastShortenOk
  %14 = getelementptr inbounds [3 x i64], [3 x i64]* %10, i64 0, i64 %12
  %15 = load i64, i64* %14, align 8
  %16 = load i6, i6* %bit_index, align 1
  %17 = zext i6 %16 to i64
  %18 = shl i64 1, %17
  %19 = or i64 %15, %18
  store i64 %19, i64* %14, align 8
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i1 @std.target.Arch.isWasm(i6 %0) unnamed_addr #1 {
Entry:
  %result = alloca i1, align 1
  %arch = alloca i6, align 1
  store i6 %0, i6* %arch, align 1
  %1 = load i6, i6* %arch, align 1
  switch i6 %1, label %SwitchElse [
    i6 -18, label %SwitchProng
    i6 -17, label %SwitchProng
  ]

SwitchElse:                                       ; preds = %Entry
  store i1 false, i1* %result, align 1
  br label %SwitchEnd

SwitchProng:                                      ; preds = %Entry, %Entry
  store i1 true, i1* %result, align 1
  br label %SwitchEnd

SwitchEnd:                                        ; preds = %SwitchProng, %SwitchElse
  %2 = load i1, i1* %result, align 1
  ret i1 %2
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i1 @std.target.Arch.isMIPS(i6 %0) unnamed_addr #1 {
Entry:
  %result = alloca i1, align 1
  %arch = alloca i6, align 1
  store i6 %0, i6* %arch, align 1
  %1 = load i6, i6* %arch, align 1
  switch i6 %1, label %SwitchElse [
    i6 10, label %SwitchProng
    i6 11, label %SwitchProng
    i6 12, label %SwitchProng
    i6 13, label %SwitchProng
  ]

SwitchElse:                                       ; preds = %Entry
  store i1 false, i1* %result, align 1
  br label %SwitchEnd

SwitchProng:                                      ; preds = %Entry, %Entry, %Entry, %Entry
  store i1 true, i1* %result, align 1
  br label %SwitchEnd

SwitchEnd:                                        ; preds = %SwitchProng, %SwitchElse
  %2 = load i1, i1* %result, align 1
  ret i1 %2
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.mutex.Dummy.acquire(%std.mutex.Held* nonnull sret %0, %std.mutex.Dummy* nonnull align 1 %1) unnamed_addr #1 {
Entry:
  %2 = alloca %"?std.mutex.Held", align 8
  %self = alloca %std.mutex.Dummy*, align 8
  store %std.mutex.Dummy* %1, %std.mutex.Dummy** %self, align 8
  %3 = load %std.mutex.Dummy*, %std.mutex.Dummy** %self, align 8
  call fastcc void @std.mutex.Dummy.tryAcquire(%"?std.mutex.Held"* sret %2, %std.mutex.Dummy* %3)
  %4 = getelementptr inbounds %"?std.mutex.Held", %"?std.mutex.Held"* %2, i32 0, i32 1
  %5 = load i1, i1* %4, align 1
  br i1 %5, label %OptionalNonNull, label %OptionalNull

OptionalNull:                                     ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @20, %std.builtin.StackTrace* null)
  unreachable

OptionalNonNull:                                  ; preds = %Entry
  %6 = getelementptr inbounds %"?std.mutex.Held", %"?std.mutex.Held"* %2, i32 0, i32 0
  %7 = bitcast %std.mutex.Held* %6 to i8*
  %8 = bitcast %std.mutex.Held* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %8, i8* align 8 %7, i64 8, i1 false)
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.io.getStdErr(%std.fs.file.File* nonnull sret %0) unnamed_addr #1 {
Entry:
  %1 = getelementptr inbounds %std.fs.file.File, %std.fs.file.File* %0, i32 0, i32 0
  %2 = call fastcc i32 @std.io.getStdErrHandle()
  store i32 %2, i32* %1, align 4
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.fs.file.File.writer(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull sret %0, %std.fs.file.File* nonnull readonly align 4 %1) unnamed_addr #1 {
Entry:
  %2 = getelementptr inbounds %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, i32 0, i32 0
  %3 = bitcast %std.fs.file.File* %1 to i8*
  %4 = bitcast %std.fs.file.File* %2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %4, i8* align 4 %3, i64 4, i1 false)
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %0, %"struct:96:29"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %2 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %3 = alloca %"struct:96:29", align 8
  %4 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0 to i8*
  %5 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %5, i8* align 4 %4, i64 4, i1 false)
  %6 = bitcast %"struct:96:29"* %1 to i8*
  %7 = bitcast %"struct:96:29"* %3 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %7, i8* align 8 %6, i64 32, i1 false)
  %8 = call fastcc i16 @std.fmt.format(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, %"struct:96:29"* %1)
  store i16 %8, i16* %result, align 2
  %9 = load i16, i16* %result, align 2
  ret i16 %9
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.mutex.Held.release(%std.mutex.Held* nonnull readonly align 8 %0) unnamed_addr #1 {
Entry:
  %1 = getelementptr inbounds %std.mutex.Held, %std.mutex.Held* %0, i32 0, i32 0
  %2 = load %std.mutex.Dummy*, %std.mutex.Dummy** %1, align 8
  %3 = getelementptr inbounds %std.mutex.Dummy, %std.mutex.Dummy* %2, i32 0, i32 0
  store i1 false, i1* %3, align 1
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.mutex.Dummy.tryAcquire(%"?std.mutex.Held"* nonnull sret %0, %std.mutex.Dummy* nonnull align 1 %1) unnamed_addr #1 {
Entry:
  %self = alloca %std.mutex.Dummy*, align 8
  store %std.mutex.Dummy* %1, %std.mutex.Dummy** %self, align 8
  %2 = load %std.mutex.Dummy*, %std.mutex.Dummy** %self, align 8
  %3 = getelementptr inbounds %std.mutex.Dummy, %std.mutex.Dummy* %2, i32 0, i32 0
  %4 = load i1, i1* %3, align 1
  br i1 %4, label %Then, label %Else

Then:                                             ; preds = %Entry
  %5 = bitcast %"?std.mutex.Held"* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %5, i8* align 8 bitcast (%"?std.mutex.Held"* @21 to i8*), i64 16, i1 false)
  ret void

Else:                                             ; preds = %Entry
  br label %EndIf

EndIf:                                            ; preds = %Else
  %6 = load %std.mutex.Dummy*, %std.mutex.Dummy** %self, align 8
  %7 = getelementptr inbounds %std.mutex.Dummy, %std.mutex.Dummy* %6, i32 0, i32 0
  store i1 true, i1* %7, align 1
  %8 = getelementptr inbounds %"?std.mutex.Held", %"?std.mutex.Held"* %0, i32 0, i32 1
  store i1 true, i1* %8, align 1
  %9 = getelementptr inbounds %"?std.mutex.Held", %"?std.mutex.Held"* %0, i32 0, i32 0
  %10 = getelementptr inbounds %std.mutex.Held, %std.mutex.Held* %9, i32 0, i32 0
  %11 = load %std.mutex.Dummy*, %std.mutex.Dummy** %self, align 8
  store %std.mutex.Dummy* %11, %std.mutex.Dummy** %10, align 8
  %12 = getelementptr inbounds %"?std.mutex.Held", %"?std.mutex.Held"* %0, i32 0, i32 1
  store i1 true, i1* %12, align 1
  %13 = getelementptr inbounds %"?std.mutex.Held", %"?std.mutex.Held"* %0, i32 0, i32 0
  %14 = bitcast %std.mutex.Held* %9 to i8*
  %15 = bitcast %std.mutex.Held* %13 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %15, i8* align 8 %14, i64 8, i1 false)
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i1 @std.target.Arch.isSPARC(i6 %0) unnamed_addr #1 {
Entry:
  %result = alloca i1, align 1
  %arch = alloca i6, align 1
  store i6 %0, i6* %arch, align 1
  %1 = load i6, i6* %arch, align 1
  switch i6 %1, label %SwitchElse [
    i6 22, label %SwitchProng
    i6 24, label %SwitchProng
    i6 23, label %SwitchProng
  ]

SwitchElse:                                       ; preds = %Entry
  store i1 false, i1* %result, align 1
  br label %SwitchEnd

SwitchProng:                                      ; preds = %Entry, %Entry, %Entry
  store i1 true, i1* %result, align 1
  br label %SwitchEnd

SwitchEnd:                                        ; preds = %SwitchProng, %SwitchElse
  %2 = load i1, i1* %result, align 1
  ret i1 %2
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i32 @std.io.getStdErrHandle() unnamed_addr #1 {
Entry:
  %result = alloca i32, align 4
  store i32 2, i32* %result, align 4
  %0 = load i32, i32* %result, align 4
  ret i32 %0
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.fs.file.File.write({ i64, i16 }* nonnull sret %0, %std.fs.file.File* nonnull readonly align 4 %1, %"[]u8"* nonnull readonly align 8 %2) unnamed_addr #1 {
Entry:
  %3 = getelementptr inbounds %std.fs.file.File, %std.fs.file.File* %1, i32 0, i32 0
  %4 = load i32, i32* %3, align 4
  call fastcc void @std.os.write({ i64, i16 }* sret %0, i32 %4, %"[]u8"* %2)
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.os.write({ i64, i16 }* nonnull sret %0, i32 %1, %"[]u8"* nonnull readonly align 8 %2) unnamed_addr #1 {
Entry:
  %3 = alloca i64, align 8
  %adjusted_len = alloca i64, align 8
  %rc = alloca i64, align 8
  %4 = alloca i12, align 2
  %err = alloca i12, align 2
  %fd = alloca i32, align 4
  store i32 %1, i32* %fd, align 4
  %5 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 1
  %6 = load i64, i64* %5, align 8
  store i64 %6, i64* %3, align 8
  %7 = call fastcc i64 @std.math.min(i64 %6)
  store i64 %7, i64* %adjusted_len, align 8
  br label %WhileCond

WhileCond:                                        ; preds = %SwitchProng1, %Entry
  br label %WhileBody

WhileBody:                                        ; preds = %WhileCond
  %8 = load i32, i32* %fd, align 4
  %9 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 0
  %10 = load i8*, i8** %9, align 8
  %11 = load i64, i64* %adjusted_len, align 8
  %12 = call fastcc i64 @std.os.linux.write(i32 %8, i8* %10, i64 %11)
  store i64 %12, i64* %rc, align 8
  %13 = load i64, i64* %rc, align 8
  %14 = call fastcc i12 @std.os.linux.getErrno(i64 %13)
  store i12 %14, i12* %4, align 2
  switch i12 %14, label %SwitchElse [
    i12 0, label %SwitchProng
    i12 4, label %SwitchProng1
    i12 22, label %SwitchProng2
    i12 14, label %SwitchProng3
    i12 11, label %SwitchProng4
    i12 9, label %SwitchProng5
    i12 89, label %SwitchProng6
    i12 122, label %SwitchProng7
    i12 27, label %SwitchProng8
    i12 5, label %SwitchProng9
    i12 28, label %SwitchProng10
    i12 1, label %SwitchProng11
    i12 32, label %SwitchProng12
  ]

SwitchElse:                                       ; preds = %WhileBody
  store i12 %14, i12* %err, align 2
  %15 = load i12, i12* %err, align 2
  %16 = zext i12 %15 to i64
  %17 = call fastcc i16 @std.os.unexpectedErrno(i64 %16)
  %18 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 %17, i16* %18, align 2
  ret void

SwitchProng:                                      ; preds = %WhileBody
  %19 = load i64, i64* %rc, align 8
  %20 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %20, align 2
  %21 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 0
  store i64 %19, i64* %21, align 8
  ret void

SwitchProng1:                                     ; preds = %WhileBody
  br label %WhileCond

SwitchProng2:                                     ; preds = %WhileBody
  call fastcc void @panic(%"[]u8"* @17, %std.builtin.StackTrace* null)
  unreachable

SwitchProng3:                                     ; preds = %WhileBody
  call fastcc void @panic(%"[]u8"* @17, %std.builtin.StackTrace* null)
  unreachable

SwitchProng4:                                     ; preds = %WhileBody
  %22 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 10, i16* %22, align 2
  ret void

SwitchProng5:                                     ; preds = %WhileBody
  %23 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 9, i16* %23, align 2
  ret void

SwitchProng6:                                     ; preds = %WhileBody
  call fastcc void @panic(%"[]u8"* @17, %std.builtin.StackTrace* null)
  unreachable

SwitchProng7:                                     ; preds = %WhileBody
  %24 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 1, i16* %24, align 2
  ret void

SwitchProng8:                                     ; preds = %WhileBody
  %25 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 2, i16* %25, align 2
  ret void

SwitchProng9:                                     ; preds = %WhileBody
  %26 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 3, i16* %26, align 2
  ret void

SwitchProng10:                                    ; preds = %WhileBody
  %27 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 4, i16* %27, align 2
  ret void

SwitchProng11:                                    ; preds = %WhileBody
  %28 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 5, i16* %28, align 2
  ret void

SwitchProng12:                                    ; preds = %WhileBody
  %29 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 6, i16* %29, align 2
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.format(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %0, %"struct:96:29"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %options = alloca %std.fmt.FormatOptions, align 8
  %2 = alloca %"[]u8", align 8
  %3 = alloca %std.fmt.FormatOptions, align 8
  %4 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %5 = alloca i16, align 2
  %6 = alloca %"[]u8", align 8
  %7 = alloca %std.fmt.FormatOptions, align 8
  %8 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %9 = alloca i16, align 2
  %10 = bitcast %std.fmt.FormatOptions* %options to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %10, i8* align 8 bitcast ({ %"?usize", %"?usize", i2, <{ i8, [6 x i8] }> }* @22 to i8*), i64 40, i1 false)
  %11 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 0
  %12 = bitcast %"?usize"* %11 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %12, i8* align 8 bitcast (%"?usize"* @23 to i8*), i64 16, i1 false)
  %13 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 1
  %14 = bitcast %"?usize"* %13 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %14, i8* align 8 bitcast (%"?usize"* @24 to i8*), i64 16, i1 false)
  %15 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 2
  store i2 -2, i2* %15, align 1
  %16 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 3
  store i8 32, i8* %16, align 1
  %17 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 1
  %18 = bitcast %"?usize"* %17 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %18, i8* align 8 bitcast (%"?usize"* @25 to i8*), i64 16, i1 false)
  br label %BlockEnd

BlockEnd:                                         ; preds = %Entry
  %19 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 0
  %20 = bitcast %"?usize"* %19 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %20, i8* align 8 bitcast (%"?usize"* @26 to i8*), i64 16, i1 false)
  br label %BlockEnd1

BlockEnd1:                                        ; preds = %BlockEnd
  %21 = getelementptr inbounds %"struct:96:29", %"struct:96:29"* %1, i32 0, i32 0
  %22 = bitcast %"[]u8"* %21 to i8*
  %23 = bitcast %"[]u8"* %2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %23, i8* align 8 %22, i64 16, i1 false)
  %24 = bitcast %std.fmt.FormatOptions* %options to i8*
  %25 = bitcast %std.fmt.FormatOptions* %3 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %25, i8* align 8 %24, i64 40, i1 false)
  %26 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0 to i8*
  %27 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %4 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %27, i8* align 4 %26, i64 4, i1 false)
  %28 = call fastcc i16 @std.fmt.formatType(%"[]u8"* %21, %std.fmt.FormatOptions* %options, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, i64 3)
  store i16 %28, i16* %5, align 2
  %29 = icmp ne i16 %28, 0
  br i1 %29, label %ErrRetReturn, label %ErrRetContinue

ErrRetReturn:                                     ; preds = %BlockEnd1
  %30 = load i16, i16* %5, align 2
  store i16 %30, i16* %result, align 2
  ret i16 %30

ErrRetContinue:                                   ; preds = %BlockEnd1
  %31 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 0
  %32 = bitcast %"?usize"* %31 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %32, i8* align 8 bitcast (%"?usize"* @27 to i8*), i64 16, i1 false)
  %33 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 1
  %34 = bitcast %"?usize"* %33 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %34, i8* align 8 bitcast (%"?usize"* @28 to i8*), i64 16, i1 false)
  %35 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 2
  store i2 -2, i2* %35, align 1
  %36 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 3
  store i8 32, i8* %36, align 1
  %37 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 1
  %38 = bitcast %"?usize"* %37 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %38, i8* align 8 bitcast (%"?usize"* @29 to i8*), i64 16, i1 false)
  br label %BlockEnd2

BlockEnd2:                                        ; preds = %ErrRetContinue
  %39 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 0
  %40 = bitcast %"?usize"* %39 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %40, i8* align 8 bitcast (%"?usize"* @30 to i8*), i64 16, i1 false)
  br label %BlockEnd3

BlockEnd3:                                        ; preds = %BlockEnd2
  %41 = getelementptr inbounds %"struct:96:29", %"struct:96:29"* %1, i32 0, i32 1
  %42 = bitcast %"[]u8"* %41 to i8*
  %43 = bitcast %"[]u8"* %6 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %43, i8* align 8 %42, i64 16, i1 false)
  %44 = bitcast %std.fmt.FormatOptions* %options to i8*
  %45 = bitcast %std.fmt.FormatOptions* %7 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %45, i8* align 8 %44, i64 40, i1 false)
  %46 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0 to i8*
  %47 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %8 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %47, i8* align 4 %46, i64 4, i1 false)
  %48 = call fastcc i16 @std.fmt.formatType(%"[]u8"* %41, %std.fmt.FormatOptions* %options, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, i64 3)
  store i16 %48, i16* %9, align 2
  %49 = icmp ne i16 %48, 0
  br i1 %49, label %ErrRetReturn4, label %ErrRetContinue5

ErrRetReturn4:                                    ; preds = %BlockEnd3
  %50 = load i16, i16* %9, align 2
  store i16 %50, i16* %result, align 2
  ret i16 %50

ErrRetContinue5:                                  ; preds = %BlockEnd3
  store i16 0, i16* %result, align 2
  ret i16 0
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i64 @std.math.min(i64 %0) unnamed_addr #1 {
Entry:
  %result = alloca i64, align 8
  %y = alloca i64, align 8
  store i64 %0, i64* %y, align 8
  %1 = load i64, i64* %y, align 8
  %2 = icmp ult i64 2147479552, %1
  br i1 %2, label %Then, label %Else

Then:                                             ; preds = %Entry
  store i64 2147479552, i64* %result, align 8
  %3 = load i64, i64* %result, align 8
  ret i64 %3

Else:                                             ; preds = %Entry
  %4 = load i64, i64* %y, align 8
  store i64 %4, i64* %result, align 8
  %5 = load i64, i64* %result, align 8
  ret i64 %5
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i64 @std.os.linux.write(i32 %0, i8* nonnull readonly align 1 %1, i64 %2) unnamed_addr #1 {
Entry:
  %result = alloca i64, align 8
  %fd = alloca i32, align 4
  %buf = alloca i8*, align 8
  %count = alloca i64, align 8
  store i32 %0, i32* %fd, align 4
  store i8* %1, i8** %buf, align 8
  store i64 %2, i64* %count, align 8
  %3 = load i32, i32* %fd, align 4
  %4 = sext i32 %3 to i64
  %5 = sext i32 %3 to i64
  %6 = load i8*, i8** %buf, align 8
  %7 = ptrtoint i8* %6 to i64
  %8 = load i64, i64* %count, align 8
  %9 = call fastcc i64 @std.os.linux.x86_64.syscall3(i64 1, i64 %5, i64 %7, i64 %8)
  store i64 %9, i64* %result, align 8
  %10 = load i64, i64* %result, align 8
  ret i64 %10
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.os.unexpectedErrno(i64 %0) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %1 = alloca %"std.os.struct:4571:51", align 8
  %err = alloca i64, align 8
  store i64 %0, i64* %err, align 8
  %2 = load i64, i64* %err, align 8
  %3 = getelementptr inbounds %"std.os.struct:4571:51", %"std.os.struct:4571:51"* %1, i32 0, i32 0
  store i64 %2, i64* %3, align 8
  call fastcc void @std.debug.print.5(%"std.os.struct:4571:51"* %1)
  call fastcc void @std.debug.dumpCurrentStackTrace(%"?usize"* @35)
  store i16 11, i16* %result, align 2
  %4 = load i16, i16* %result, align 2
  ret i16 %4
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.formatType(%"[]u8"* nonnull readonly align 8 %0, %std.fmt.FormatOptions* nonnull readonly align 8 %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %2, i64 %3) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %4 = alloca %std.fmt.FormatOptions, align 8
  %5 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %max_depth = alloca i64, align 8
  store i64 %3, i64* %max_depth, align 8
  %6 = bitcast %std.fmt.FormatOptions* %1 to i8*
  %7 = bitcast %std.fmt.FormatOptions* %4 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %7, i8* align 8 %6, i64 40, i1 false)
  %8 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2 to i8*
  %9 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %5 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %9, i8* align 4 %8, i64 4, i1 false)
  %10 = call fastcc i16 @std.fmt.formatText(%"[]u8"* %0, %std.fmt.FormatOptions* %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2)
  store i16 %10, i16* %result, align 2
  %11 = load i16, i16* %result, align 2
  ret i16 %11
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.formatText(%"[]u8"* nonnull readonly align 8 %0, %std.fmt.FormatOptions* nonnull readonly align 8 %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %2) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %3 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %4 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2 to i8*
  %5 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %3 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %5, i8* align 4 %4, i64 4, i1 false)
  %6 = call fastcc i16 @std.fmt.formatBuf(%"[]u8"* %0, %std.fmt.FormatOptions* %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2)
  store i16 %6, i16* %result, align 2
  %7 = load i16, i16* %result, align 2
  ret i16 %7
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i64 @std.os.linux.x86_64.syscall3(i64 %0, i64 %1, i64 %2, i64 %3) unnamed_addr #1 {
Entry:
  %result = alloca i64, align 8
  %number = alloca i64, align 8
  %arg1 = alloca i64, align 8
  %arg2 = alloca i64, align 8
  %arg3 = alloca i64, align 8
  store i64 %0, i64* %number, align 8
  store i64 %1, i64* %arg1, align 8
  store i64 %2, i64* %arg2, align 8
  store i64 %3, i64* %arg3, align 8
  %4 = load i64, i64* %number, align 8
  %5 = load i64, i64* %arg1, align 8
  %6 = load i64, i64* %arg2, align 8
  %7 = load i64, i64* %arg3, align 8
  %8 = call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 %4, i64 %5, i64 %6, i64 %7)
  store i64 %8, i64* %result, align 8
  %9 = load i64, i64* %result, align 8
  ret i64 %9
}

; Function Attrs: nounwind readnone speculatable willreturn
declare { i64, i1 } @llvm.ssub.with.overflow.i64(i64, i64) #4

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.debug.print.5(%"std.os.struct:4571:51"* nonnull readonly align 8 %0) unnamed_addr #1 {
Entry:
  %held = alloca %std.mutex.Held, align 8
  %1 = alloca %std.fs.file.File, align 4
  %stderr = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %2 = alloca %"std.os.struct:4571:51", align 8
  %3 = alloca i16, align 2
  call fastcc void @std.mutex.Dummy.acquire(%std.mutex.Held* sret %held, %std.mutex.Dummy* @stderr_mutex)
  call fastcc void @std.io.getStdErr(%std.fs.file.File* sret %1)
  call fastcc void @std.fs.file.File.writer(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* sret %stderr, %std.fs.file.File* %1)
  %4 = bitcast %"std.os.struct:4571:51"* %0 to i8*
  %5 = bitcast %"std.os.struct:4571:51"* %2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %5, i8* align 8 %4, i64 8, i1 false)
  %6 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.7"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %stderr, %"std.os.struct:4571:51"* %0)
  store i16 %6, i16* %3, align 2
  %7 = icmp ne i16 %6, 0
  br i1 %7, label %UnwrapErrError, label %UnwrapErrOk

UnwrapErrError:                                   ; preds = %Entry
  call fastcc void @std.mutex.Held.release(%std.mutex.Held* %held)
  ret void

UnwrapErrOk:                                      ; preds = %Entry
  br label %UnwrapErrEnd

UnwrapErrEnd:                                     ; preds = %UnwrapErrOk
  call fastcc void @std.mutex.Held.release(%std.mutex.Held* %held)
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.debug.dumpCurrentStackTrace(%"?usize"* nonnull readonly align 8 %0) unnamed_addr #1 {
Entry:
  %1 = alloca %std.fs.file.File, align 4
  %stderr = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %2 = alloca i16, align 2
  call fastcc void @std.io.getStdErr(%std.fs.file.File* sret %1)
  call fastcc void @std.fs.file.File.writer(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* sret %stderr, %std.fs.file.File* %1)
  %3 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.8"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %stderr)
  store i16 %3, i16* %2, align 2
  %4 = icmp ne i16 %3, 0
  br i1 %4, label %UnwrapErrError, label %UnwrapErrOk

UnwrapErrError:                                   ; preds = %Entry
  ret void

UnwrapErrOk:                                      ; preds = %Entry
  br label %UnwrapErrEnd

UnwrapErrEnd:                                     ; preds = %UnwrapErrOk
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.formatBuf(%"[]u8"* nonnull readonly align 8 %0, %std.fmt.FormatOptions* nonnull readonly align 8 %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %2) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %min_width = alloca i64, align 8
  %3 = alloca { i64, i16 }, align 8
  %_ = alloca i16, align 2
  %width = alloca i64, align 8
  %padding = alloca i64, align 8
  %4 = alloca i16, align 2
  %5 = alloca i16, align 2
  %left_padding = alloca i64, align 8
  %right_padding = alloca i64, align 8
  %6 = alloca i16, align 2
  %7 = alloca i16, align 2
  %8 = alloca i16, align 2
  %9 = alloca i16, align 2
  %10 = alloca i16, align 2
  %11 = alloca i16, align 2
  %12 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %1, i32 0, i32 1
  %13 = getelementptr inbounds %"?usize", %"?usize"* %12, i32 0, i32 1
  %14 = load i1, i1* %13, align 1
  br i1 %14, label %OptionalThen, label %OptionalElse

OptionalThen:                                     ; preds = %Entry
  %15 = getelementptr inbounds %"?usize", %"?usize"* %12, i32 0, i32 0
  %16 = load i64, i64* %15, align 8
  store i64 %16, i64* %min_width, align 8
  call fastcc void @std.unicode.utf8CountCodepoints({ i64, i16 }* sret %3, %"[]u8"* %0)
  %17 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %3, i32 0, i32 1
  %18 = load i16, i16* %17, align 2
  %19 = icmp ne i16 %18, 0
  br i1 %19, label %UnwrapErrError, label %UnwrapErrOk

UnwrapErrError:                                   ; preds = %OptionalThen
  %20 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %3, i32 0, i32 1
  %21 = load i16, i16* %20, align 2
  store i16 %21, i16* %_, align 2
  %22 = getelementptr inbounds %"[]u8", %"[]u8"* %0, i32 0, i32 1
  %23 = load i64, i64* %22, align 8
  store i64 %23, i64* %width, align 8
  br label %UnwrapErrEnd

UnwrapErrOk:                                      ; preds = %OptionalThen
  %24 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %3, i32 0, i32 0
  %25 = load i64, i64* %24, align 8
  store i64 %25, i64* %width, align 8
  br label %UnwrapErrEnd

UnwrapErrEnd:                                     ; preds = %UnwrapErrOk, %UnwrapErrError
  %26 = load i64, i64* %width, align 8
  %27 = load i64, i64* %min_width, align 8
  %28 = icmp ult i64 %26, %27
  br i1 %28, label %Then, label %Else

Then:                                             ; preds = %UnwrapErrEnd
  %29 = load i64, i64* %min_width, align 8
  %30 = load i64, i64* %width, align 8
  %31 = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %29, i64 %30)
  %32 = extractvalue { i64, i1 } %31, 0
  %33 = extractvalue { i64, i1 } %31, 1
  br i1 %33, label %OverflowFail, label %OverflowOk

Else:                                             ; preds = %UnwrapErrEnd
  store i64 0, i64* %padding, align 8
  br label %EndIf

EndIf:                                            ; preds = %Else, %OverflowOk
  %34 = load i64, i64* %padding, align 8
  %35 = icmp eq i64 %34, 0
  br i1 %35, label %Then1, label %Else2

Then1:                                            ; preds = %EndIf
  %36 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2, %"[]u8"* %0)
  store i16 %36, i16* %result, align 2
  %37 = load i16, i16* %result, align 2
  ret i16 %37

Else2:                                            ; preds = %EndIf
  br label %EndIf3

EndIf3:                                           ; preds = %Else2
  %38 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %1, i32 0, i32 2
  %39 = load i2, i2* %38, align 1
  switch i2 %39, label %SwitchElse [
    i2 0, label %SwitchProng
    i2 1, label %SwitchProng5
    i2 -2, label %SwitchProng11
  ]

SwitchProng:                                      ; preds = %EndIf3
  %40 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2, %"[]u8"* %0)
  store i16 %40, i16* %4, align 2
  %41 = icmp ne i16 %40, 0
  br i1 %41, label %ErrRetReturn, label %ErrRetContinue

ErrRetReturn:                                     ; preds = %SwitchProng
  %42 = load i16, i16* %4, align 2
  store i16 %42, i16* %result, align 2
  ret i16 %42

ErrRetContinue:                                   ; preds = %SwitchProng
  %43 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %1, i32 0, i32 3
  %44 = load i8, i8* %43, align 1
  %45 = load i64, i64* %padding, align 8
  %46 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeByteNTimes"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2, i8 %44, i64 %45)
  store i16 %46, i16* %5, align 2
  %47 = icmp ne i16 %46, 0
  br i1 %47, label %ErrRetReturn4, label %ErrRetContinue15

ErrRetReturn4:                                    ; preds = %ErrRetContinue
  %48 = load i16, i16* %5, align 2
  store i16 %48, i16* %result, align 2
  ret i16 %48

SwitchProng5:                                     ; preds = %EndIf3
  %49 = load i64, i64* %padding, align 8
  br i1 false, label %DivZeroFail, label %DivZeroOk

ErrRetReturn6:                                    ; preds = %DivZeroOk23
  %50 = load i16, i16* %6, align 2
  store i16 %50, i16* %result, align 2
  ret i16 %50

ErrRetContinue7:                                  ; preds = %DivZeroOk23
  %51 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2, %"[]u8"* %0)
  store i16 %51, i16* %7, align 2
  %52 = icmp ne i16 %51, 0
  br i1 %52, label %ErrRetReturn8, label %ErrRetContinue9

ErrRetReturn8:                                    ; preds = %ErrRetContinue7
  %53 = load i16, i16* %7, align 2
  store i16 %53, i16* %result, align 2
  ret i16 %53

ErrRetContinue9:                                  ; preds = %ErrRetContinue7
  %54 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %1, i32 0, i32 3
  %55 = load i8, i8* %54, align 1
  %56 = load i64, i64* %right_padding, align 8
  %57 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeByteNTimes"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2, i8 %55, i64 %56)
  store i16 %57, i16* %8, align 2
  %58 = icmp ne i16 %57, 0
  br i1 %58, label %ErrRetReturn10, label %ErrRetContinue16

ErrRetReturn10:                                   ; preds = %ErrRetContinue9
  %59 = load i16, i16* %8, align 2
  store i16 %59, i16* %result, align 2
  ret i16 %59

SwitchProng11:                                    ; preds = %EndIf3
  %60 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %1, i32 0, i32 3
  %61 = load i8, i8* %60, align 1
  %62 = load i64, i64* %padding, align 8
  %63 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeByteNTimes"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2, i8 %61, i64 %62)
  store i16 %63, i16* %9, align 2
  %64 = icmp ne i16 %63, 0
  br i1 %64, label %ErrRetReturn12, label %ErrRetContinue13

ErrRetReturn12:                                   ; preds = %SwitchProng11
  %65 = load i16, i16* %9, align 2
  store i16 %65, i16* %result, align 2
  ret i16 %65

ErrRetContinue13:                                 ; preds = %SwitchProng11
  %66 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2, %"[]u8"* %0)
  store i16 %66, i16* %10, align 2
  %67 = icmp ne i16 %66, 0
  br i1 %67, label %ErrRetReturn14, label %ErrRetContinue17

ErrRetReturn14:                                   ; preds = %ErrRetContinue13
  %68 = load i16, i16* %10, align 2
  store i16 %68, i16* %result, align 2
  ret i16 %68

SwitchElse:                                       ; preds = %EndIf3
  call fastcc void @panic(%"[]u8"* @17, %std.builtin.StackTrace* null)
  unreachable

ErrRetContinue15:                                 ; preds = %ErrRetContinue
  br label %SwitchEnd

ErrRetContinue16:                                 ; preds = %ErrRetContinue9
  br label %SwitchEnd

ErrRetContinue17:                                 ; preds = %ErrRetContinue13
  br label %SwitchEnd

OptionalElse:                                     ; preds = %Entry
  %69 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2, %"[]u8"* %0)
  store i16 %69, i16* %11, align 2
  %70 = icmp ne i16 %69, 0
  br i1 %70, label %ErrRetReturn18, label %ErrRetContinue19

ErrRetReturn18:                                   ; preds = %OptionalElse
  %71 = load i16, i16* %11, align 2
  store i16 %71, i16* %result, align 2
  ret i16 %71

SwitchEnd:                                        ; preds = %ErrRetContinue17, %ErrRetContinue16, %ErrRetContinue15
  br label %OptionalEndIf

ErrRetContinue19:                                 ; preds = %OptionalElse
  br label %OptionalEndIf

OptionalEndIf:                                    ; preds = %ErrRetContinue19, %SwitchEnd
  store i16 0, i16* %result, align 2
  ret i16 0

OverflowFail:                                     ; preds = %Then
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk:                                       ; preds = %Then
  store i64 %32, i64* %padding, align 8
  br label %EndIf

DivZeroFail:                                      ; preds = %SwitchProng5
  call fastcc void @panic(%"[]u8"* @9, %std.builtin.StackTrace* null)
  unreachable

DivZeroOk:                                        ; preds = %SwitchProng5
  %72 = udiv i64 %49, 2
  store i64 %72, i64* %left_padding, align 8
  %73 = load i64, i64* %padding, align 8
  %74 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %73, i64 1)
  %75 = extractvalue { i64, i1 } %74, 0
  %76 = extractvalue { i64, i1 } %74, 1
  br i1 %76, label %OverflowFail20, label %OverflowOk21

OverflowFail20:                                   ; preds = %DivZeroOk
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk21:                                     ; preds = %DivZeroOk
  br i1 false, label %DivZeroFail22, label %DivZeroOk23

DivZeroFail22:                                    ; preds = %OverflowOk21
  call fastcc void @panic(%"[]u8"* @9, %std.builtin.StackTrace* null)
  unreachable

DivZeroOk23:                                      ; preds = %OverflowOk21
  %77 = udiv i64 %75, 2
  store i64 %77, i64* %right_padding, align 8
  %78 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %1, i32 0, i32 3
  %79 = load i8, i8* %78, align 1
  %80 = load i64, i64* %left_padding, align 8
  %81 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeByteNTimes"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2, i8 %79, i64 %80)
  store i16 %81, i16* %6, align 2
  %82 = icmp ne i16 %81, 0
  br i1 %82, label %ErrRetReturn6, label %ErrRetContinue7
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.unicode.utf8CountCodepoints({ i64, i16 }* nonnull sret %0, %"[]u8"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %len = alloca i64, align 8
  %i = alloca i64, align 8
  %2 = alloca %"[]u8", align 8
  %3 = alloca [8 x i8]*, align 8
  %v = alloca i64, align 8
  %4 = alloca { i3, i16 }, align 2
  %5 = alloca { i64, i16 }, align 8
  %n = alloca i3, align 1
  %6 = alloca %"[]u8", align 8
  %7 = alloca { i21, i16 }, align 4
  %8 = alloca { i64, i16 }, align 8
  store i64 0, i64* %len, align 8
  store i64 0, i64* %i, align 8
  br label %WhileCond

WhileCond:                                        ; preds = %EndIf10, %Entry
  %9 = load i64, i64* %i, align 8
  %10 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %11 = load i64, i64* %10, align 8
  %12 = icmp ult i64 %9, %11
  br i1 %12, label %WhileBody, label %WhileEnd11

WhileBody:                                        ; preds = %WhileCond
  br label %WhileCond1

WhileCond1:                                       ; preds = %OverflowOk21, %WhileBody
  %13 = load i64, i64* %i, align 8
  %14 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %13, i64 8)
  %15 = extractvalue { i64, i1 } %14, 0
  %16 = extractvalue { i64, i1 } %14, 1
  br i1 %16, label %OverflowFail, label %OverflowOk

WhileBody2:                                       ; preds = %OverflowOk
  %17 = load i64, i64* %i, align 8
  %18 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %19 = load i64, i64* %18, align 8
  %20 = icmp ule i64 %17, %19
  br i1 %20, label %BoundsCheckOk, label %BoundsCheckFail

Then:                                             ; preds = %BoundsCheckOk17
  br label %WhileEnd

Else:                                             ; preds = %BoundsCheckOk17
  br label %EndIf

EndIf:                                            ; preds = %Else
  %21 = load i64, i64* %len, align 8
  %22 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %21, i64 8)
  %23 = extractvalue { i64, i1 } %22, 0
  %24 = extractvalue { i64, i1 } %22, 1
  br i1 %24, label %OverflowFail18, label %OverflowOk19

WhileEnd:                                         ; preds = %Then, %OverflowOk
  %25 = load i64, i64* %i, align 8
  %26 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %27 = load i64, i64* %26, align 8
  %28 = icmp ult i64 %25, %27
  br i1 %28, label %Then3, label %Else9

Then3:                                            ; preds = %WhileEnd
  %29 = load i64, i64* %i, align 8
  %30 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %31 = load i64, i64* %30, align 8
  %32 = icmp ult i64 %29, %31
  br i1 %32, label %BoundsCheckOk23, label %BoundsCheckFail22

ErrRetReturn:                                     ; preds = %BoundsCheckOk23
  %33 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %4, i32 0, i32 1
  %34 = load i16, i16* %33, align 2
  %35 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 %34, i16* %35, align 2
  %36 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %5, i32 0, i32 1
  store i16 %34, i16* %36, align 2
  ret void

ErrRetContinue:                                   ; preds = %BoundsCheckOk23
  %37 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %4, i32 0, i32 0
  %38 = load i3, i3* %37, align 1
  store i3 %38, i3* %n, align 1
  %39 = load i64, i64* %i, align 8
  %40 = load i3, i3* %n, align 1
  %41 = zext i3 %40 to i64
  %42 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %39, i64 %41)
  %43 = extractvalue { i64, i1 } %42, 0
  %44 = extractvalue { i64, i1 } %42, 1
  br i1 %44, label %OverflowFail24, label %OverflowOk25

Then4:                                            ; preds = %OverflowOk25
  %45 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 13, i16* %45, align 2
  ret void

Else5:                                            ; preds = %OverflowOk25
  br label %EndIf6

EndIf6:                                           ; preds = %Else5
  %46 = load i3, i3* %n, align 1
  switch i3 %46, label %SwitchElse [
    i3 1, label %SwitchProng
  ]

SwitchElse:                                       ; preds = %EndIf6
  %47 = load i64, i64* %i, align 8
  %48 = load i64, i64* %i, align 8
  %49 = load i3, i3* %n, align 1
  %50 = zext i3 %49 to i64
  %51 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %48, i64 %50)
  %52 = extractvalue { i64, i1 } %51, 0
  %53 = extractvalue { i64, i1 } %51, 1
  br i1 %53, label %OverflowFail26, label %OverflowOk27

ErrRetReturn7:                                    ; preds = %BoundsCheckOk31
  %54 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %7, i32 0, i32 1
  %55 = load i16, i16* %54, align 2
  %56 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 %55, i16* %56, align 2
  %57 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %8, i32 0, i32 1
  store i16 %55, i16* %57, align 2
  ret void

ErrRetContinue8:                                  ; preds = %BoundsCheckOk31
  %58 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %7, i32 0, i32 0
  br label %SwitchEnd

SwitchProng:                                      ; preds = %EndIf6
  br label %SwitchEnd

SwitchEnd:                                        ; preds = %SwitchProng, %ErrRetContinue8
  %59 = load i64, i64* %i, align 8
  %60 = load i3, i3* %n, align 1
  %61 = zext i3 %60 to i64
  %62 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %59, i64 %61)
  %63 = extractvalue { i64, i1 } %62, 0
  %64 = extractvalue { i64, i1 } %62, 1
  br i1 %64, label %OverflowFail32, label %OverflowOk33

Else9:                                            ; preds = %WhileEnd
  br label %EndIf10

EndIf10:                                          ; preds = %Else9, %OverflowOk35
  br label %WhileCond

WhileEnd11:                                       ; preds = %WhileCond
  %65 = load i64, i64* %len, align 8
  %66 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %66, align 2
  %67 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %0, i32 0, i32 0
  store i64 %65, i64* %67, align 8
  ret void

OverflowFail:                                     ; preds = %WhileCond1
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk:                                       ; preds = %WhileCond1
  %68 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %69 = load i64, i64* %68, align 8
  %70 = icmp ule i64 %15, %69
  br i1 %70, label %WhileBody2, label %WhileEnd

BoundsCheckFail:                                  ; preds = %WhileBody2
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk:                                    ; preds = %WhileBody2
  %71 = icmp ule i64 %19, %19
  br i1 %71, label %BoundsCheckOk13, label %BoundsCheckFail12

BoundsCheckFail12:                                ; preds = %BoundsCheckOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk13:                                  ; preds = %BoundsCheckOk
  %72 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %73 = load i8*, i8** %72, align 8
  %74 = getelementptr inbounds i8, i8* %73, i64 %17
  %75 = sub nuw i64 %19, %17
  %76 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 0
  store i8* %74, i8** %76, align 8
  %77 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 1
  store i64 %75, i64* %77, align 8
  %78 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 1
  %79 = load i64, i64* %78, align 8
  br i1 true, label %BoundsCheckOk15, label %BoundsCheckFail14

BoundsCheckFail14:                                ; preds = %BoundsCheckOk13
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk15:                                  ; preds = %BoundsCheckOk13
  %80 = icmp ule i64 8, %79
  br i1 %80, label %BoundsCheckOk17, label %BoundsCheckFail16

BoundsCheckFail16:                                ; preds = %BoundsCheckOk15
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk17:                                  ; preds = %BoundsCheckOk15
  %81 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 0
  %82 = load i8*, i8** %81, align 8
  %83 = getelementptr inbounds i8, i8* %82, i64 0
  %84 = bitcast i8* %83 to [8 x i8]*
  store [8 x i8]* %84, [8 x i8]** %3, align 8
  %85 = call fastcc i64 @std.mem.readIntNative([8 x i8]* %84)
  store i64 %85, i64* %v, align 8
  %86 = load i64, i64* %v, align 8
  %87 = and i64 %86, -9187201950435737472
  %88 = icmp ne i64 %87, 0
  br i1 %88, label %Then, label %Else

OverflowFail18:                                   ; preds = %EndIf
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk19:                                     ; preds = %EndIf
  store i64 %23, i64* %len, align 8
  %89 = load i64, i64* %i, align 8
  %90 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %89, i64 8)
  %91 = extractvalue { i64, i1 } %90, 0
  %92 = extractvalue { i64, i1 } %90, 1
  br i1 %92, label %OverflowFail20, label %OverflowOk21

OverflowFail20:                                   ; preds = %OverflowOk19
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk21:                                     ; preds = %OverflowOk19
  store i64 %91, i64* %i, align 8
  br label %WhileCond1

BoundsCheckFail22:                                ; preds = %Then3
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk23:                                  ; preds = %Then3
  %93 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %94 = load i8*, i8** %93, align 8
  %95 = getelementptr inbounds i8, i8* %94, i64 %29
  %96 = load i8, i8* %95, align 1
  call fastcc void @std.unicode.utf8ByteSequenceLength({ i3, i16 }* sret %4, i8 %96)
  %97 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %4, i32 0, i32 1
  %98 = load i16, i16* %97, align 2
  %99 = icmp ne i16 %98, 0
  br i1 %99, label %ErrRetReturn, label %ErrRetContinue

OverflowFail24:                                   ; preds = %ErrRetContinue
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk25:                                     ; preds = %ErrRetContinue
  %100 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %101 = load i64, i64* %100, align 8
  %102 = icmp ugt i64 %43, %101
  br i1 %102, label %Then4, label %Else5

OverflowFail26:                                   ; preds = %SwitchElse
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk27:                                     ; preds = %SwitchElse
  %103 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %104 = load i64, i64* %103, align 8
  %105 = icmp ule i64 %47, %52
  br i1 %105, label %BoundsCheckOk29, label %BoundsCheckFail28

BoundsCheckFail28:                                ; preds = %OverflowOk27
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk29:                                  ; preds = %OverflowOk27
  %106 = icmp ule i64 %52, %104
  br i1 %106, label %BoundsCheckOk31, label %BoundsCheckFail30

BoundsCheckFail30:                                ; preds = %BoundsCheckOk29
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk31:                                  ; preds = %BoundsCheckOk29
  %107 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %108 = load i8*, i8** %107, align 8
  %109 = getelementptr inbounds i8, i8* %108, i64 %47
  %110 = sub nuw i64 %52, %47
  %111 = getelementptr inbounds %"[]u8", %"[]u8"* %6, i32 0, i32 0
  store i8* %109, i8** %111, align 8
  %112 = getelementptr inbounds %"[]u8", %"[]u8"* %6, i32 0, i32 1
  store i64 %110, i64* %112, align 8
  call fastcc void @std.unicode.utf8Decode({ i21, i16 }* sret %7, %"[]u8"* %6)
  %113 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %7, i32 0, i32 1
  %114 = load i16, i16* %113, align 2
  %115 = icmp ne i16 %114, 0
  br i1 %115, label %ErrRetReturn7, label %ErrRetContinue8

OverflowFail32:                                   ; preds = %SwitchEnd
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk33:                                     ; preds = %SwitchEnd
  store i64 %63, i64* %i, align 8
  %116 = load i64, i64* %len, align 8
  %117 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %116, i64 1)
  %118 = extractvalue { i64, i1 } %117, 0
  %119 = extractvalue { i64, i1 } %117, 1
  br i1 %119, label %OverflowFail34, label %OverflowOk35

OverflowFail34:                                   ; preds = %OverflowOk33
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk35:                                     ; preds = %OverflowOk33
  store i64 %118, i64* %len, align 8
  br label %EndIf10
}

; Function Attrs: nounwind readnone speculatable willreturn
declare { i64, i1 } @llvm.usub.with.overflow.i64(i64, i64) #4

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %0, %"[]u8"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %index = alloca i64, align 8
  %2 = alloca %"[]u8", align 8
  %3 = alloca { i64, i16 }, align 8
  store i64 0, i64* %index, align 8
  br label %WhileCond

WhileCond:                                        ; preds = %OverflowOk, %Entry
  %4 = load i64, i64* %index, align 8
  %5 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %6 = load i64, i64* %5, align 8
  %7 = icmp ne i64 %4, %6
  br i1 %7, label %WhileBody, label %WhileEnd

WhileBody:                                        ; preds = %WhileCond
  %8 = load i64, i64* %index, align 8
  %9 = load i64, i64* %index, align 8
  %10 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %11 = load i64, i64* %10, align 8
  %12 = icmp ule i64 %9, %11
  br i1 %12, label %BoundsCheckOk, label %BoundsCheckFail

ErrRetReturn:                                     ; preds = %BoundsCheckOk2
  %13 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %3, i32 0, i32 1
  %14 = load i16, i16* %13, align 2
  store i16 %14, i16* %result, align 2
  ret i16 %14

ErrRetContinue:                                   ; preds = %BoundsCheckOk2
  %15 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %3, i32 0, i32 0
  %16 = load i64, i64* %15, align 8
  %17 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %8, i64 %16)
  %18 = extractvalue { i64, i1 } %17, 0
  %19 = extractvalue { i64, i1 } %17, 1
  br i1 %19, label %OverflowFail, label %OverflowOk

WhileEnd:                                         ; preds = %WhileCond
  store i16 0, i16* %result, align 2
  ret i16 0

BoundsCheckFail:                                  ; preds = %WhileBody
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk:                                    ; preds = %WhileBody
  %20 = icmp ule i64 %11, %11
  br i1 %20, label %BoundsCheckOk2, label %BoundsCheckFail1

BoundsCheckFail1:                                 ; preds = %BoundsCheckOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk2:                                   ; preds = %BoundsCheckOk
  %21 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %22 = load i8*, i8** %21, align 8
  %23 = getelementptr inbounds i8, i8* %22, i64 %9
  %24 = sub nuw i64 %11, %9
  %25 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 0
  store i8* %23, i8** %25, align 8
  %26 = getelementptr inbounds %"[]u8", %"[]u8"* %2, i32 0, i32 1
  store i64 %24, i64* %26, align 8
  call fastcc void @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).write"({ i64, i16 }* sret %3, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, %"[]u8"* %2)
  %27 = getelementptr inbounds { i64, i16 }, { i64, i16 }* %3, i32 0, i32 1
  %28 = load i16, i16* %27, align 2
  %29 = icmp ne i16 %28, 0
  br i1 %29, label %ErrRetReturn, label %ErrRetContinue

OverflowFail:                                     ; preds = %ErrRetContinue
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk:                                       ; preds = %ErrRetContinue
  store i64 %18, i64* %index, align 8
  br label %WhileCond
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeByteNTimes"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %0, i8 %1, i64 %2) unnamed_addr #1 {
Entry:
  %3 = alloca [6 x i64], align 8
  %result = alloca i16, align 2
  %bytes = alloca [256 x i8], align 1
  %4 = alloca [256 x i8]*, align 8
  %5 = alloca i8, align 1
  %6 = alloca %"[]u8", align 8
  %remaining = alloca i64, align 8
  %7 = alloca i64, align 8
  %to_write = alloca i64, align 8
  %8 = alloca %"[]u8", align 8
  %9 = alloca i16, align 2
  %byte = alloca i8, align 1
  %n = alloca i64, align 8
  store i8 %1, i8* %byte, align 1
  store i64 %2, i64* %n, align 8
  %10 = bitcast [256 x i8]* %bytes to i8*
  call void @llvm.memset.p0i8.i64(i8* align 1 %10, i8 -86, i64 256, i1 false)
  %11 = ptrtoint i8* %10 to i64
  %12 = getelementptr inbounds [6 x i64], [6 x i64]* %3, i64 0, i64 0
  store i64 1296236545, i64* %12, align 8
  %13 = getelementptr inbounds [6 x i64], [6 x i64]* %3, i64 0, i64 1
  store i64 %11, i64* %13, align 8
  %14 = getelementptr inbounds [6 x i64], [6 x i64]* %3, i64 0, i64 2
  store i64 256, i64* %14, align 8
  %15 = getelementptr inbounds [6 x i64], [6 x i64]* %3, i64 0, i64 3
  store i64 0, i64* %15, align 8
  %16 = getelementptr inbounds [6 x i64], [6 x i64]* %3, i64 0, i64 4
  store i64 0, i64* %16, align 8
  %17 = getelementptr inbounds [6 x i64], [6 x i64]* %3, i64 0, i64 5
  store i64 0, i64* %17, align 8
  %18 = ptrtoint [6 x i64]* %3 to i64
  %19 = call i64 asm sideeffect "rolq $$3,  %rdi ; rolq $$13, %rdi\0Arolq $$61, %rdi ; rolq $$51, %rdi\0Axchgq %rbx,%rbx\0A", "={rdx},{rax},0,~{cc},~{memory}"(i64 %18, i64 0)
  br i1 true, label %BoundsCheckOk, label %BoundsCheckFail

WhileCond:                                        ; preds = %OverflowOk, %BoundsCheckOk
  %20 = load i64, i64* %remaining, align 8
  %21 = icmp ugt i64 %20, 0
  br i1 %21, label %WhileBody, label %WhileEnd

WhileBody:                                        ; preds = %WhileCond
  %22 = load i64, i64* %remaining, align 8
  store i64 %22, i64* %7, align 8
  %23 = call fastcc i64 @std.math.min.6(i64 %22, i64 256)
  store i64 %23, i64* %to_write, align 8
  %24 = load i64, i64* %to_write, align 8
  %25 = icmp ule i64 0, %24
  br i1 %25, label %BoundsCheckOk2, label %BoundsCheckFail1

ErrRetReturn:                                     ; preds = %BoundsCheckOk4
  %26 = load i16, i16* %9, align 2
  store i16 %26, i16* %result, align 2
  ret i16 %26

ErrRetContinue:                                   ; preds = %BoundsCheckOk4
  %27 = load i64, i64* %remaining, align 8
  %28 = load i64, i64* %to_write, align 8
  %29 = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %27, i64 %28)
  %30 = extractvalue { i64, i1 } %29, 0
  %31 = extractvalue { i64, i1 } %29, 1
  br i1 %31, label %OverflowFail, label %OverflowOk

WhileEnd:                                         ; preds = %WhileCond
  store i16 0, i16* %result, align 2
  ret i16 0

BoundsCheckFail:                                  ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk:                                    ; preds = %Entry
  %32 = getelementptr inbounds [256 x i8], [256 x i8]* %bytes, i64 0, i64 0
  %33 = bitcast i8* %32 to [256 x i8]*
  store [256 x i8]* %33, [256 x i8]** %4, align 8
  %34 = load i8, i8* %byte, align 1
  store i8 %34, i8* %5, align 1
  %35 = getelementptr inbounds %"[]u8", %"[]u8"* %6, i32 0, i32 0
  %36 = getelementptr inbounds [256 x i8], [256 x i8]* %33, i64 0, i64 0
  store i8* %36, i8** %35, align 8
  %37 = getelementptr inbounds %"[]u8", %"[]u8"* %6, i32 0, i32 1
  store i64 256, i64* %37, align 8
  call fastcc void @std.mem.set(%"[]u8"* %6, i8 %34)
  %38 = load i64, i64* %n, align 8
  store i64 %38, i64* %remaining, align 8
  br label %WhileCond

BoundsCheckFail1:                                 ; preds = %WhileBody
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk2:                                   ; preds = %WhileBody
  %39 = icmp ule i64 %24, 256
  br i1 %39, label %BoundsCheckOk4, label %BoundsCheckFail3

BoundsCheckFail3:                                 ; preds = %BoundsCheckOk2
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk4:                                   ; preds = %BoundsCheckOk2
  %40 = getelementptr inbounds [256 x i8], [256 x i8]* %bytes, i64 0, i64 0
  %41 = sub nuw i64 %24, 0
  %42 = getelementptr inbounds %"[]u8", %"[]u8"* %8, i32 0, i32 0
  store i8* %40, i8** %42, align 8
  %43 = getelementptr inbounds %"[]u8", %"[]u8"* %8, i32 0, i32 1
  store i64 %41, i64* %43, align 8
  %44 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, %"[]u8"* %8)
  store i16 %44, i16* %9, align 2
  %45 = icmp ne i16 %44, 0
  br i1 %45, label %ErrRetReturn, label %ErrRetContinue

OverflowFail:                                     ; preds = %ErrRetContinue
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk:                                       ; preds = %ErrRetContinue
  store i64 %30, i64* %remaining, align 8
  br label %WhileCond
}

; Function Attrs: nounwind readnone speculatable willreturn
declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) #4

; Function Attrs: nobuiltin nounwind
define internal fastcc i64 @std.mem.readIntNative([8 x i8]* nonnull readonly align 1 %0) unnamed_addr #1 {
Entry:
  %result = alloca i64, align 8
  %bytes = alloca [8 x i8]*, align 8
  store [8 x i8]* %0, [8 x i8]** %bytes, align 8
  %1 = load [8 x i8]*, [8 x i8]** %bytes, align 8
  %2 = bitcast [8 x i8]* %1 to i64*
  %3 = icmp ne i64* %2, null
  br i1 %3, label %PtrCastOk, label %PtrCastFail

PtrCastFail:                                      ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @37, %std.builtin.StackTrace* null)
  unreachable

PtrCastOk:                                        ; preds = %Entry
  %4 = load i64, i64* %2, align 1
  store i64 %4, i64* %result, align 8
  %5 = load i64, i64* %result, align 8
  ret i64 %5
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.unicode.utf8ByteSequenceLength({ i3, i16 }* nonnull sret %0, i8 %1) unnamed_addr #1 {
Entry:
  %first_byte = alloca i8, align 1
  store i8 %1, i8* %first_byte, align 1
  %2 = load i8, i8* %first_byte, align 1
  %3 = icmp ule i8 %2, 127
  %4 = and i1 true, %3
  br i1 %4, label %SwitchRangeYes, label %SwitchRangeNo

SwitchRangeYes:                                   ; preds = %Entry
  %5 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %5, align 2
  %6 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %0, i32 0, i32 0
  store i3 1, i3* %6, align 1
  br label %SwitchEnd

SwitchRangeNo:                                    ; preds = %Entry
  %7 = icmp uge i8 %2, -64
  %8 = icmp ule i8 %2, -33
  %9 = and i1 %7, %8
  br i1 %9, label %SwitchRangeYes1, label %SwitchRangeNo2

SwitchRangeYes1:                                  ; preds = %SwitchRangeNo
  %10 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %10, align 2
  %11 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %0, i32 0, i32 0
  store i3 2, i3* %11, align 1
  br label %SwitchEnd

SwitchRangeNo2:                                   ; preds = %SwitchRangeNo
  %12 = icmp uge i8 %2, -32
  %13 = icmp ule i8 %2, -17
  %14 = and i1 %12, %13
  br i1 %14, label %SwitchRangeYes3, label %SwitchRangeNo4

SwitchRangeYes3:                                  ; preds = %SwitchRangeNo2
  %15 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %15, align 2
  %16 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %0, i32 0, i32 0
  store i3 3, i3* %16, align 1
  br label %SwitchEnd

SwitchRangeNo4:                                   ; preds = %SwitchRangeNo2
  %17 = icmp uge i8 %2, -16
  %18 = icmp ule i8 %2, -9
  %19 = and i1 %17, %18
  br i1 %19, label %SwitchRangeYes5, label %SwitchRangeNo6

SwitchRangeYes5:                                  ; preds = %SwitchRangeNo4
  %20 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %20, align 2
  %21 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %0, i32 0, i32 0
  store i3 -4, i3* %21, align 1
  br label %SwitchEnd

SwitchRangeNo6:                                   ; preds = %SwitchRangeNo4
  br label %SwitchElse

SwitchElse:                                       ; preds = %SwitchRangeNo6
  %22 = getelementptr inbounds { i3, i16 }, { i3, i16 }* %0, i32 0, i32 1
  store i16 12, i16* %22, align 2
  br label %SwitchEnd

SwitchEnd:                                        ; preds = %SwitchElse, %SwitchRangeYes5, %SwitchRangeYes3, %SwitchRangeYes1, %SwitchRangeYes
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.unicode.utf8Decode({ i21, i16 }* nonnull sret %0, %"[]u8"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %2 = alloca { i21, i16 }, align 4
  %3 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %4 = load i64, i64* %3, align 8
  switch i64 %4, label %SwitchElse [
    i64 1, label %SwitchProng
    i64 2, label %SwitchProng1
    i64 3, label %SwitchProng2
    i64 4, label %SwitchProng3
  ]

SwitchElse:                                       ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @17, %std.builtin.StackTrace* null)
  unreachable

SwitchProng:                                      ; preds = %Entry
  %5 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %6 = load i64, i64* %5, align 8
  %7 = icmp ult i64 0, %6
  br i1 %7, label %BoundsCheckOk, label %BoundsCheckFail

SwitchProng1:                                     ; preds = %Entry
  call fastcc void @std.unicode.utf8Decode2({ i21, i16 }* sret %0, %"[]u8"* %1)
  %8 = bitcast { i21, i16 }* %0 to i8*
  %9 = bitcast { i21, i16 }* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %9, i8* align 4 %8, i64 8, i1 false)
  br label %SwitchEnd

SwitchProng2:                                     ; preds = %Entry
  call fastcc void @std.unicode.utf8Decode3({ i21, i16 }* sret %0, %"[]u8"* %1)
  %10 = bitcast { i21, i16 }* %0 to i8*
  %11 = bitcast { i21, i16 }* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %11, i8* align 4 %10, i64 8, i1 false)
  br label %SwitchEnd

SwitchProng3:                                     ; preds = %Entry
  call fastcc void @std.unicode.utf8Decode4({ i21, i16 }* sret %0, %"[]u8"* %1)
  %12 = bitcast { i21, i16 }* %0 to i8*
  %13 = bitcast { i21, i16 }* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %13, i8* align 4 %12, i64 8, i1 false)
  br label %SwitchEnd

SwitchEnd:                                        ; preds = %SwitchProng3, %SwitchProng2, %SwitchProng1, %BoundsCheckOk
  ret void

BoundsCheckFail:                                  ; preds = %SwitchProng
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk:                                    ; preds = %SwitchProng
  %14 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %15 = load i8*, i8** %14, align 8
  %16 = getelementptr inbounds i8, i8* %15, i64 0
  %17 = load i8, i8* %16, align 1
  %18 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %18, align 2
  %19 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 0
  %20 = zext i8 %17 to i21
  store i21 %20, i21* %19, align 4
  %21 = zext i8 %17 to i21
  store i21 %21, i21* %19, align 4
  %22 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %2, i32 0, i32 1
  store i16 0, i16* %22, align 2
  %23 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %2, i32 0, i32 0
  store i21 %21, i21* %23, align 4
  br label %SwitchEnd
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.unicode.utf8Decode2({ i21, i16 }* nonnull sret %0, %"[]u8"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %value = alloca i21, align 4
  %2 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %3 = load i64, i64* %2, align 8
  %4 = icmp eq i64 %3, 2
  call fastcc void @std.debug.assert(i1 %4)
  %5 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %6 = load i64, i64* %5, align 8
  %7 = icmp ult i64 0, %6
  br i1 %7, label %BoundsCheckOk, label %BoundsCheckFail

Then:                                             ; preds = %BoundsCheckOk7
  %8 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 14, i16* %8, align 2
  ret void

Else:                                             ; preds = %BoundsCheckOk7
  br label %EndIf

EndIf:                                            ; preds = %Else
  %9 = load i21, i21* %value, align 4
  br i1 true, label %CheckOk, label %CheckFail

Then1:                                            ; preds = %BoundsCheckOk9
  %10 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 15, i16* %10, align 2
  ret void

Else2:                                            ; preds = %BoundsCheckOk9
  br label %EndIf3

EndIf3:                                           ; preds = %Else2
  %11 = load i21, i21* %value, align 4
  %12 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %12, align 2
  %13 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 0
  store i21 %11, i21* %13, align 4
  ret void

BoundsCheckFail:                                  ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk:                                    ; preds = %Entry
  %14 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %15 = load i8*, i8** %14, align 8
  %16 = getelementptr inbounds i8, i8* %15, i64 0
  %17 = load i8, i8* %16, align 1
  %18 = and i8 %17, -32
  %19 = icmp eq i8 %18, -64
  call fastcc void @std.debug.assert(i1 %19)
  %20 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %21 = load i64, i64* %20, align 8
  %22 = icmp ult i64 0, %21
  br i1 %22, label %BoundsCheckOk5, label %BoundsCheckFail4

BoundsCheckFail4:                                 ; preds = %BoundsCheckOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk5:                                   ; preds = %BoundsCheckOk
  %23 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %24 = load i8*, i8** %23, align 8
  %25 = getelementptr inbounds i8, i8* %24, i64 0
  %26 = load i8, i8* %25, align 1
  %27 = and i8 %26, 31
  %28 = zext i8 %27 to i21
  store i21 %28, i21* %value, align 4
  %29 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %30 = load i64, i64* %29, align 8
  %31 = icmp ult i64 1, %30
  br i1 %31, label %BoundsCheckOk7, label %BoundsCheckFail6

BoundsCheckFail6:                                 ; preds = %BoundsCheckOk5
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk7:                                   ; preds = %BoundsCheckOk5
  %32 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %33 = load i8*, i8** %32, align 8
  %34 = getelementptr inbounds i8, i8* %33, i64 1
  %35 = load i8, i8* %34, align 1
  %36 = and i8 %35, -64
  %37 = icmp ne i8 %36, -128
  br i1 %37, label %Then, label %Else

CheckFail:                                        ; preds = %EndIf
  call fastcc void @panic(%"[]u8"* @39, %std.builtin.StackTrace* null)
  unreachable

CheckOk:                                          ; preds = %EndIf
  %38 = shl i21 %9, 6
  store i21 %38, i21* %value, align 4
  %39 = load i21, i21* %value, align 4
  %40 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %41 = load i64, i64* %40, align 8
  %42 = icmp ult i64 1, %41
  br i1 %42, label %BoundsCheckOk9, label %BoundsCheckFail8

BoundsCheckFail8:                                 ; preds = %CheckOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk9:                                   ; preds = %CheckOk
  %43 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %44 = load i8*, i8** %43, align 8
  %45 = getelementptr inbounds i8, i8* %44, i64 1
  %46 = load i8, i8* %45, align 1
  %47 = and i8 %46, 63
  %48 = zext i8 %47 to i21
  %49 = or i21 %39, %48
  store i21 %49, i21* %value, align 4
  %50 = load i21, i21* %value, align 4
  %51 = icmp ult i21 %50, 128
  br i1 %51, label %Then1, label %Else2
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.unicode.utf8Decode3({ i21, i16 }* nonnull sret %0, %"[]u8"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %value = alloca i21, align 4
  %2 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %3 = load i64, i64* %2, align 8
  %4 = icmp eq i64 %3, 3
  call fastcc void @std.debug.assert(i1 %4)
  %5 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %6 = load i64, i64* %5, align 8
  %7 = icmp ult i64 0, %6
  br i1 %7, label %BoundsCheckOk, label %BoundsCheckFail

Then:                                             ; preds = %BoundsCheckOk13
  %8 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 14, i16* %8, align 2
  ret void

Else:                                             ; preds = %BoundsCheckOk13
  br label %EndIf

EndIf:                                            ; preds = %Else
  %9 = load i21, i21* %value, align 4
  br i1 true, label %CheckOk, label %CheckFail

Then1:                                            ; preds = %BoundsCheckOk17
  %10 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 14, i16* %10, align 2
  ret void

Else2:                                            ; preds = %BoundsCheckOk17
  br label %EndIf3

EndIf3:                                           ; preds = %Else2
  %11 = load i21, i21* %value, align 4
  br i1 true, label %CheckOk19, label %CheckFail18

Then4:                                            ; preds = %BoundsCheckOk21
  %12 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 15, i16* %12, align 2
  ret void

Else5:                                            ; preds = %BoundsCheckOk21
  br label %EndIf6

EndIf6:                                           ; preds = %Else5
  %13 = load i21, i21* %value, align 4
  %14 = icmp ule i21 55296, %13
  br i1 %14, label %BoolAndTrue, label %BoolAndFalse

BoolAndTrue:                                      ; preds = %EndIf6
  %15 = load i21, i21* %value, align 4
  %16 = icmp ule i21 %15, 57343
  br label %BoolAndFalse

BoolAndFalse:                                     ; preds = %BoolAndTrue, %EndIf6
  %17 = phi i1 [ %14, %EndIf6 ], [ %16, %BoolAndTrue ]
  br i1 %17, label %Then7, label %Else8

Then7:                                            ; preds = %BoolAndFalse
  %18 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 16, i16* %18, align 2
  ret void

Else8:                                            ; preds = %BoolAndFalse
  br label %EndIf9

EndIf9:                                           ; preds = %Else8
  %19 = load i21, i21* %value, align 4
  %20 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %20, align 2
  %21 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 0
  store i21 %19, i21* %21, align 4
  ret void

BoundsCheckFail:                                  ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk:                                    ; preds = %Entry
  %22 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %23 = load i8*, i8** %22, align 8
  %24 = getelementptr inbounds i8, i8* %23, i64 0
  %25 = load i8, i8* %24, align 1
  %26 = and i8 %25, -16
  %27 = icmp eq i8 %26, -32
  call fastcc void @std.debug.assert(i1 %27)
  %28 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %29 = load i64, i64* %28, align 8
  %30 = icmp ult i64 0, %29
  br i1 %30, label %BoundsCheckOk11, label %BoundsCheckFail10

BoundsCheckFail10:                                ; preds = %BoundsCheckOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk11:                                  ; preds = %BoundsCheckOk
  %31 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %32 = load i8*, i8** %31, align 8
  %33 = getelementptr inbounds i8, i8* %32, i64 0
  %34 = load i8, i8* %33, align 1
  %35 = and i8 %34, 15
  %36 = zext i8 %35 to i21
  store i21 %36, i21* %value, align 4
  %37 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %38 = load i64, i64* %37, align 8
  %39 = icmp ult i64 1, %38
  br i1 %39, label %BoundsCheckOk13, label %BoundsCheckFail12

BoundsCheckFail12:                                ; preds = %BoundsCheckOk11
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk13:                                  ; preds = %BoundsCheckOk11
  %40 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %41 = load i8*, i8** %40, align 8
  %42 = getelementptr inbounds i8, i8* %41, i64 1
  %43 = load i8, i8* %42, align 1
  %44 = and i8 %43, -64
  %45 = icmp ne i8 %44, -128
  br i1 %45, label %Then, label %Else

CheckFail:                                        ; preds = %EndIf
  call fastcc void @panic(%"[]u8"* @39, %std.builtin.StackTrace* null)
  unreachable

CheckOk:                                          ; preds = %EndIf
  %46 = shl i21 %9, 6
  store i21 %46, i21* %value, align 4
  %47 = load i21, i21* %value, align 4
  %48 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %49 = load i64, i64* %48, align 8
  %50 = icmp ult i64 1, %49
  br i1 %50, label %BoundsCheckOk15, label %BoundsCheckFail14

BoundsCheckFail14:                                ; preds = %CheckOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk15:                                  ; preds = %CheckOk
  %51 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %52 = load i8*, i8** %51, align 8
  %53 = getelementptr inbounds i8, i8* %52, i64 1
  %54 = load i8, i8* %53, align 1
  %55 = and i8 %54, 63
  %56 = zext i8 %55 to i21
  %57 = or i21 %47, %56
  store i21 %57, i21* %value, align 4
  %58 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %59 = load i64, i64* %58, align 8
  %60 = icmp ult i64 2, %59
  br i1 %60, label %BoundsCheckOk17, label %BoundsCheckFail16

BoundsCheckFail16:                                ; preds = %BoundsCheckOk15
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk17:                                  ; preds = %BoundsCheckOk15
  %61 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %62 = load i8*, i8** %61, align 8
  %63 = getelementptr inbounds i8, i8* %62, i64 2
  %64 = load i8, i8* %63, align 1
  %65 = and i8 %64, -64
  %66 = icmp ne i8 %65, -128
  br i1 %66, label %Then1, label %Else2

CheckFail18:                                      ; preds = %EndIf3
  call fastcc void @panic(%"[]u8"* @39, %std.builtin.StackTrace* null)
  unreachable

CheckOk19:                                        ; preds = %EndIf3
  %67 = shl i21 %11, 6
  store i21 %67, i21* %value, align 4
  %68 = load i21, i21* %value, align 4
  %69 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %70 = load i64, i64* %69, align 8
  %71 = icmp ult i64 2, %70
  br i1 %71, label %BoundsCheckOk21, label %BoundsCheckFail20

BoundsCheckFail20:                                ; preds = %CheckOk19
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk21:                                  ; preds = %CheckOk19
  %72 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %73 = load i8*, i8** %72, align 8
  %74 = getelementptr inbounds i8, i8* %73, i64 2
  %75 = load i8, i8* %74, align 1
  %76 = and i8 %75, 63
  %77 = zext i8 %76 to i21
  %78 = or i21 %68, %77
  store i21 %78, i21* %value, align 4
  %79 = load i21, i21* %value, align 4
  %80 = icmp ult i21 %79, 2048
  br i1 %80, label %Then4, label %Else5
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.unicode.utf8Decode4({ i21, i16 }* nonnull sret %0, %"[]u8"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %value = alloca i21, align 4
  %2 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %3 = load i64, i64* %2, align 8
  %4 = icmp eq i64 %3, 4
  call fastcc void @std.debug.assert(i1 %4)
  %5 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %6 = load i64, i64* %5, align 8
  %7 = icmp ult i64 0, %6
  br i1 %7, label %BoundsCheckOk, label %BoundsCheckFail

Then:                                             ; preds = %BoundsCheckOk16
  %8 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 14, i16* %8, align 2
  ret void

Else:                                             ; preds = %BoundsCheckOk16
  br label %EndIf

EndIf:                                            ; preds = %Else
  %9 = load i21, i21* %value, align 4
  br i1 true, label %CheckOk, label %CheckFail

Then1:                                            ; preds = %BoundsCheckOk20
  %10 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 14, i16* %10, align 2
  ret void

Else2:                                            ; preds = %BoundsCheckOk20
  br label %EndIf3

EndIf3:                                           ; preds = %Else2
  %11 = load i21, i21* %value, align 4
  br i1 true, label %CheckOk22, label %CheckFail21

Then4:                                            ; preds = %BoundsCheckOk26
  %12 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 14, i16* %12, align 2
  ret void

Else5:                                            ; preds = %BoundsCheckOk26
  br label %EndIf6

EndIf6:                                           ; preds = %Else5
  %13 = load i21, i21* %value, align 4
  br i1 true, label %CheckOk28, label %CheckFail27

Then7:                                            ; preds = %BoundsCheckOk30
  %14 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 15, i16* %14, align 2
  ret void

Else8:                                            ; preds = %BoundsCheckOk30
  br label %EndIf9

EndIf9:                                           ; preds = %Else8
  %15 = load i21, i21* %value, align 4
  %16 = icmp ugt i21 %15, -983041
  br i1 %16, label %Then10, label %Else11

Then10:                                           ; preds = %EndIf9
  %17 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 17, i16* %17, align 2
  ret void

Else11:                                           ; preds = %EndIf9
  br label %EndIf12

EndIf12:                                          ; preds = %Else11
  %18 = load i21, i21* %value, align 4
  %19 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 1
  store i16 0, i16* %19, align 2
  %20 = getelementptr inbounds { i21, i16 }, { i21, i16 }* %0, i32 0, i32 0
  store i21 %18, i21* %20, align 4
  ret void

BoundsCheckFail:                                  ; preds = %Entry
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk:                                    ; preds = %Entry
  %21 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %22 = load i8*, i8** %21, align 8
  %23 = getelementptr inbounds i8, i8* %22, i64 0
  %24 = load i8, i8* %23, align 1
  %25 = and i8 %24, -8
  %26 = icmp eq i8 %25, -16
  call fastcc void @std.debug.assert(i1 %26)
  %27 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %28 = load i64, i64* %27, align 8
  %29 = icmp ult i64 0, %28
  br i1 %29, label %BoundsCheckOk14, label %BoundsCheckFail13

BoundsCheckFail13:                                ; preds = %BoundsCheckOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk14:                                  ; preds = %BoundsCheckOk
  %30 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %31 = load i8*, i8** %30, align 8
  %32 = getelementptr inbounds i8, i8* %31, i64 0
  %33 = load i8, i8* %32, align 1
  %34 = and i8 %33, 7
  %35 = zext i8 %34 to i21
  store i21 %35, i21* %value, align 4
  %36 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %37 = load i64, i64* %36, align 8
  %38 = icmp ult i64 1, %37
  br i1 %38, label %BoundsCheckOk16, label %BoundsCheckFail15

BoundsCheckFail15:                                ; preds = %BoundsCheckOk14
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk16:                                  ; preds = %BoundsCheckOk14
  %39 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %40 = load i8*, i8** %39, align 8
  %41 = getelementptr inbounds i8, i8* %40, i64 1
  %42 = load i8, i8* %41, align 1
  %43 = and i8 %42, -64
  %44 = icmp ne i8 %43, -128
  br i1 %44, label %Then, label %Else

CheckFail:                                        ; preds = %EndIf
  call fastcc void @panic(%"[]u8"* @39, %std.builtin.StackTrace* null)
  unreachable

CheckOk:                                          ; preds = %EndIf
  %45 = shl i21 %9, 6
  store i21 %45, i21* %value, align 4
  %46 = load i21, i21* %value, align 4
  %47 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %48 = load i64, i64* %47, align 8
  %49 = icmp ult i64 1, %48
  br i1 %49, label %BoundsCheckOk18, label %BoundsCheckFail17

BoundsCheckFail17:                                ; preds = %CheckOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk18:                                  ; preds = %CheckOk
  %50 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %51 = load i8*, i8** %50, align 8
  %52 = getelementptr inbounds i8, i8* %51, i64 1
  %53 = load i8, i8* %52, align 1
  %54 = and i8 %53, 63
  %55 = zext i8 %54 to i21
  %56 = or i21 %46, %55
  store i21 %56, i21* %value, align 4
  %57 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %58 = load i64, i64* %57, align 8
  %59 = icmp ult i64 2, %58
  br i1 %59, label %BoundsCheckOk20, label %BoundsCheckFail19

BoundsCheckFail19:                                ; preds = %BoundsCheckOk18
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk20:                                  ; preds = %BoundsCheckOk18
  %60 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %61 = load i8*, i8** %60, align 8
  %62 = getelementptr inbounds i8, i8* %61, i64 2
  %63 = load i8, i8* %62, align 1
  %64 = and i8 %63, -64
  %65 = icmp ne i8 %64, -128
  br i1 %65, label %Then1, label %Else2

CheckFail21:                                      ; preds = %EndIf3
  call fastcc void @panic(%"[]u8"* @39, %std.builtin.StackTrace* null)
  unreachable

CheckOk22:                                        ; preds = %EndIf3
  %66 = shl i21 %11, 6
  store i21 %66, i21* %value, align 4
  %67 = load i21, i21* %value, align 4
  %68 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %69 = load i64, i64* %68, align 8
  %70 = icmp ult i64 2, %69
  br i1 %70, label %BoundsCheckOk24, label %BoundsCheckFail23

BoundsCheckFail23:                                ; preds = %CheckOk22
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk24:                                  ; preds = %CheckOk22
  %71 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %72 = load i8*, i8** %71, align 8
  %73 = getelementptr inbounds i8, i8* %72, i64 2
  %74 = load i8, i8* %73, align 1
  %75 = and i8 %74, 63
  %76 = zext i8 %75 to i21
  %77 = or i21 %67, %76
  store i21 %77, i21* %value, align 4
  %78 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %79 = load i64, i64* %78, align 8
  %80 = icmp ult i64 3, %79
  br i1 %80, label %BoundsCheckOk26, label %BoundsCheckFail25

BoundsCheckFail25:                                ; preds = %BoundsCheckOk24
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk26:                                  ; preds = %BoundsCheckOk24
  %81 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %82 = load i8*, i8** %81, align 8
  %83 = getelementptr inbounds i8, i8* %82, i64 3
  %84 = load i8, i8* %83, align 1
  %85 = and i8 %84, -64
  %86 = icmp ne i8 %85, -128
  br i1 %86, label %Then4, label %Else5

CheckFail27:                                      ; preds = %EndIf6
  call fastcc void @panic(%"[]u8"* @39, %std.builtin.StackTrace* null)
  unreachable

CheckOk28:                                        ; preds = %EndIf6
  %87 = shl i21 %13, 6
  store i21 %87, i21* %value, align 4
  %88 = load i21, i21* %value, align 4
  %89 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %90 = load i64, i64* %89, align 8
  %91 = icmp ult i64 3, %90
  br i1 %91, label %BoundsCheckOk30, label %BoundsCheckFail29

BoundsCheckFail29:                                ; preds = %CheckOk28
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk30:                                  ; preds = %CheckOk28
  %92 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %93 = load i8*, i8** %92, align 8
  %94 = getelementptr inbounds i8, i8* %93, i64 3
  %95 = load i8, i8* %94, align 1
  %96 = and i8 %95, 63
  %97 = zext i8 %96 to i21
  %98 = or i21 %88, %97
  store i21 %98, i21* %value, align 4
  %99 = load i21, i21* %value, align 4
  %100 = icmp ult i21 %99, 65536
  br i1 %100, label %Then7, label %Else8
}

; Function Attrs: nobuiltin nounwind
define internal fastcc void @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).write"({ i64, i16 }* nonnull sret %0, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %1, %"[]u8"* nonnull readonly align 8 %2) unnamed_addr #1 {
Entry:
  %3 = getelementptr inbounds %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %1, i32 0, i32 0
  call fastcc void @std.fs.file.File.write({ i64, i16 }* sret %0, %std.fs.file.File* %3, %"[]u8"* %2)
  ret void
}

; Function Attrs: argmemonly nounwind willreturn writeonly
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #5

; Function Attrs: nobuiltin nounwind
define internal fastcc void @std.mem.set(%"[]u8"* nonnull readonly align 8 %0, i8 %1) unnamed_addr #1 {
Entry:
  %i = alloca i64, align 8
  %d = alloca i8*, align 8
  %value = alloca i8, align 1
  store i8 %1, i8* %value, align 1
  store i64 0, i64* %i, align 8
  %2 = getelementptr inbounds %"[]u8", %"[]u8"* %0, i32 0, i32 1
  %3 = load i64, i64* %2, align 8
  br label %ForCond

ForCond:                                          ; preds = %ForBody, %Entry
  %4 = load i64, i64* %i, align 8
  %5 = icmp ult i64 %4, %3
  br i1 %5, label %ForBody, label %ForEnd

ForBody:                                          ; preds = %ForCond
  %6 = getelementptr inbounds %"[]u8", %"[]u8"* %0, i32 0, i32 0
  %7 = load i8*, i8** %6, align 8
  %8 = getelementptr inbounds i8, i8* %7, i64 %4
  store i8* %8, i8** %d, align 8
  %9 = load i8*, i8** %d, align 8
  %10 = load i8, i8* %value, align 1
  store i8 %10, i8* %9, align 1
  %11 = add nuw i64 %4, 1
  store i64 %11, i64* %i, align 8
  br label %ForCond

ForEnd:                                           ; preds = %ForCond
  ret void
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i64 @std.math.min.6(i64 %0, i64 %1) unnamed_addr #1 {
Entry:
  %result = alloca i64, align 8
  %x = alloca i64, align 8
  %y = alloca i64, align 8
  store i64 %0, i64* %x, align 8
  store i64 %1, i64* %y, align 8
  %2 = load i64, i64* %x, align 8
  %3 = load i64, i64* %y, align 8
  %4 = icmp ult i64 %2, %3
  br i1 %4, label %Then, label %Else

Then:                                             ; preds = %Entry
  %5 = load i64, i64* %x, align 8
  store i64 %5, i64* %result, align 8
  %6 = load i64, i64* %result, align 8
  ret i64 %6

Else:                                             ; preds = %Entry
  %7 = load i64, i64* %y, align 8
  store i64 %7, i64* %result, align 8
  %8 = load i64, i64* %result, align 8
  ret i64 %8
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.7"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %0, %"std.os.struct:4571:51"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %2 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %3 = alloca %"std.os.struct:4571:51", align 8
  %4 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0 to i8*
  %5 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %5, i8* align 4 %4, i64 4, i1 false)
  %6 = bitcast %"std.os.struct:4571:51"* %1 to i8*
  %7 = bitcast %"std.os.struct:4571:51"* %3 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %7, i8* align 8 %6, i64 8, i1 false)
  %8 = call fastcc i16 @std.fmt.format.9(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, %"std.os.struct:4571:51"* %1)
  store i16 %8, i16* %result, align 2
  %9 = load i16, i16* %result, align 2
  ret i16 %9
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.8"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %0) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %1 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %2 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0 to i8*
  %3 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %1 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %3, i8* align 4 %2, i64 4, i1 false)
  %4 = call fastcc i16 @std.fmt.format.10(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0)
  store i16 %4, i16* %result, align 2
  %5 = load i16, i16* %result, align 2
  ret i16 %5
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.format.9(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %0, %"std.os.struct:4571:51"* nonnull readonly align 8 %1) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %options = alloca %std.fmt.FormatOptions, align 8
  %2 = alloca i16, align 2
  %3 = alloca i64, align 8
  %4 = alloca %std.fmt.FormatOptions, align 8
  %5 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %6 = alloca i16, align 2
  %7 = alloca i16, align 2
  %8 = bitcast %std.fmt.FormatOptions* %options to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %8, i8* align 8 bitcast ({ %"?usize", %"?usize", i2, <{ i8, [6 x i8] }> }* @40 to i8*), i64 40, i1 false)
  %9 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, %"[]u8"* @42)
  store i16 %9, i16* %2, align 2
  %10 = icmp ne i16 %9, 0
  br i1 %10, label %ErrRetReturn, label %ErrRetContinue

ErrRetReturn:                                     ; preds = %Entry
  %11 = load i16, i16* %2, align 2
  store i16 %11, i16* %result, align 2
  ret i16 %11

ErrRetContinue:                                   ; preds = %Entry
  %12 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 0
  %13 = bitcast %"?usize"* %12 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %13, i8* align 8 bitcast (%"?usize"* @43 to i8*), i64 16, i1 false)
  %14 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 1
  %15 = bitcast %"?usize"* %14 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %15, i8* align 8 bitcast (%"?usize"* @44 to i8*), i64 16, i1 false)
  %16 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 2
  store i2 -2, i2* %16, align 1
  %17 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 3
  store i8 32, i8* %17, align 1
  %18 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 1
  %19 = bitcast %"?usize"* %18 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %19, i8* align 8 bitcast (%"?usize"* @45 to i8*), i64 16, i1 false)
  br label %BlockEnd

BlockEnd:                                         ; preds = %ErrRetContinue
  %20 = getelementptr inbounds %std.fmt.FormatOptions, %std.fmt.FormatOptions* %options, i32 0, i32 0
  %21 = bitcast %"?usize"* %20 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %21, i8* align 8 bitcast (%"?usize"* @46 to i8*), i64 16, i1 false)
  br label %BlockEnd1

BlockEnd1:                                        ; preds = %BlockEnd
  %22 = getelementptr inbounds %"std.os.struct:4571:51", %"std.os.struct:4571:51"* %1, i32 0, i32 0
  %23 = load i64, i64* %22, align 8
  store i64 %23, i64* %3, align 8
  %24 = bitcast %std.fmt.FormatOptions* %options to i8*
  %25 = bitcast %std.fmt.FormatOptions* %4 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %25, i8* align 8 %24, i64 40, i1 false)
  %26 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0 to i8*
  %27 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %5 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %27, i8* align 4 %26, i64 4, i1 false)
  %28 = call fastcc i16 @std.fmt.formatType.11(i64 %23, %std.fmt.FormatOptions* %options, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, i64 3)
  store i16 %28, i16* %6, align 2
  %29 = icmp ne i16 %28, 0
  br i1 %29, label %ErrRetReturn2, label %ErrRetContinue3

ErrRetReturn2:                                    ; preds = %BlockEnd1
  %30 = load i16, i16* %6, align 2
  store i16 %30, i16* %result, align 2
  ret i16 %30

ErrRetContinue3:                                  ; preds = %BlockEnd1
  %31 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, %"[]u8"* @47)
  store i16 %31, i16* %7, align 2
  %32 = icmp ne i16 %31, 0
  br i1 %32, label %ErrRetReturn4, label %ErrRetContinue5

ErrRetReturn4:                                    ; preds = %ErrRetContinue3
  %33 = load i16, i16* %7, align 2
  store i16 %33, i16* %result, align 2
  ret i16 %33

ErrRetContinue5:                                  ; preds = %ErrRetContinue3
  store i16 0, i16* %result, align 2
  ret i16 0
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.format.10(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %0) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %options = alloca %std.fmt.FormatOptions, align 8
  %1 = alloca i16, align 2
  %2 = bitcast %std.fmt.FormatOptions* %options to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %2, i8* align 8 bitcast ({ %"?usize", %"?usize", i2, <{ i8, [6 x i8] }> }* @48 to i8*), i64 40, i1 false)
  %3 = call fastcc i16 @"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll"(%"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %0, %"[]u8"* @50)
  store i16 %3, i16* %1, align 2
  %4 = icmp ne i16 %3, 0
  br i1 %4, label %ErrRetReturn, label %ErrRetContinue

ErrRetReturn:                                     ; preds = %Entry
  %5 = load i16, i16* %1, align 2
  store i16 %5, i16* %result, align 2
  ret i16 %5

ErrRetContinue:                                   ; preds = %Entry
  store i16 0, i16* %result, align 2
  ret i16 0
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.formatType.11(i64 %0, %std.fmt.FormatOptions* nonnull readonly align 8 %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %2, i64 %3) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %4 = alloca i64, align 8
  %5 = alloca %std.fmt.FormatOptions, align 8
  %6 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %value = alloca i64, align 8
  %max_depth = alloca i64, align 8
  store i64 %0, i64* %value, align 8
  store i64 %3, i64* %max_depth, align 8
  %7 = load i64, i64* %value, align 8
  store i64 %7, i64* %4, align 8
  %8 = bitcast %std.fmt.FormatOptions* %1 to i8*
  %9 = bitcast %std.fmt.FormatOptions* %5 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %9, i8* align 8 %8, i64 40, i1 false)
  %10 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2 to i8*
  %11 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %6 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %11, i8* align 4 %10, i64 4, i1 false)
  %12 = call fastcc i16 @std.fmt.formatValue(i64 %7, %std.fmt.FormatOptions* %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2)
  store i16 %12, i16* %result, align 2
  %13 = load i16, i16* %result, align 2
  ret i16 %13
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.formatValue(i64 %0, %std.fmt.FormatOptions* nonnull readonly align 8 %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %2) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %3 = alloca i64, align 8
  %4 = alloca %std.fmt.FormatOptions, align 8
  %5 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %value = alloca i64, align 8
  store i64 %0, i64* %value, align 8
  %6 = load i64, i64* %value, align 8
  store i64 %6, i64* %3, align 8
  %7 = bitcast %std.fmt.FormatOptions* %1 to i8*
  %8 = bitcast %std.fmt.FormatOptions* %4 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %8, i8* align 8 %7, i64 40, i1 false)
  %9 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2 to i8*
  %10 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %5 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %10, i8* align 4 %9, i64 4, i1 false)
  %11 = call fastcc i16 @std.fmt.formatIntValue(i64 %6, %std.fmt.FormatOptions* %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2)
  store i16 %11, i16* %result, align 2
  %12 = load i16, i16* %result, align 2
  ret i16 %12
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.formatIntValue(i64 %0, %std.fmt.FormatOptions* nonnull readonly align 8 %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %2) unnamed_addr #1 {
Entry:
  %result = alloca i16, align 2
  %int_value = alloca i64, align 8
  %3 = alloca i64, align 8
  %4 = alloca %std.fmt.FormatOptions, align 8
  %5 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %value = alloca i64, align 8
  store i64 %0, i64* %value, align 8
  %6 = load i64, i64* %value, align 8
  store i64 %6, i64* %int_value, align 8
  %7 = load i64, i64* %int_value, align 8
  store i64 %7, i64* %3, align 8
  %8 = bitcast %std.fmt.FormatOptions* %1 to i8*
  %9 = bitcast %std.fmt.FormatOptions* %4 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %9, i8* align 8 %8, i64 40, i1 false)
  %10 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2 to i8*
  %11 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %5 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %11, i8* align 4 %10, i64 4, i1 false)
  %12 = call fastcc i16 @std.fmt.formatInt(i64 %7, i8 10, i1 false, %std.fmt.FormatOptions* %1, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %2)
  store i16 %12, i16* %result, align 2
  %13 = load i16, i16* %result, align 2
  ret i16 %13
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i16 @std.fmt.formatInt(i64 %0, i8 %1, i1 %2, %std.fmt.FormatOptions* nonnull readonly align 8 %3, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* nonnull readonly align 4 %4) unnamed_addr #1 {
Entry:
  %5 = alloca [6 x i64], align 8
  %result = alloca i16, align 2
  %int_value = alloca i64, align 8
  %6 = alloca i64, align 8
  %abs_value = alloca i64, align 8
  %buf = alloca [65 x i8], align 1
  %a = alloca i64, align 8
  %index = alloca i64, align 8
  %digit = alloca i64, align 8
  %7 = alloca %"[]u8", align 8
  %8 = alloca %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)", align 4
  %value = alloca i64, align 8
  %base = alloca i8, align 1
  %uppercase = alloca i1, align 1
  store i64 %0, i64* %value, align 8
  store i8 %1, i8* %base, align 1
  store i1 %2, i1* %uppercase, align 1
  %9 = load i8, i8* %base, align 1
  %10 = icmp uge i8 %9, 2
  call fastcc void @std.debug.assert(i1 %10)
  %11 = load i64, i64* %value, align 8
  store i64 %11, i64* %int_value, align 8
  %12 = load i64, i64* %int_value, align 8
  store i64 %12, i64* %6, align 8
  %13 = call fastcc i64 @std.math.absCast(i64 %12)
  store i64 %13, i64* %abs_value, align 8
  %14 = bitcast [65 x i8]* %buf to i8*
  call void @llvm.memset.p0i8.i64(i8* align 1 %14, i8 -86, i64 65, i1 false)
  %15 = ptrtoint i8* %14 to i64
  %16 = getelementptr inbounds [6 x i64], [6 x i64]* %5, i64 0, i64 0
  store i64 1296236545, i64* %16, align 8
  %17 = getelementptr inbounds [6 x i64], [6 x i64]* %5, i64 0, i64 1
  store i64 %15, i64* %17, align 8
  %18 = getelementptr inbounds [6 x i64], [6 x i64]* %5, i64 0, i64 2
  store i64 65, i64* %18, align 8
  %19 = getelementptr inbounds [6 x i64], [6 x i64]* %5, i64 0, i64 3
  store i64 0, i64* %19, align 8
  %20 = getelementptr inbounds [6 x i64], [6 x i64]* %5, i64 0, i64 4
  store i64 0, i64* %20, align 8
  %21 = getelementptr inbounds [6 x i64], [6 x i64]* %5, i64 0, i64 5
  store i64 0, i64* %21, align 8
  %22 = ptrtoint [6 x i64]* %5 to i64
  %23 = call i64 asm sideeffect "rolq $$3,  %rdi ; rolq $$13, %rdi\0Arolq $$61, %rdi ; rolq $$51, %rdi\0Axchgq %rbx,%rbx\0A", "={rdx},{rax},0,~{cc},~{memory}"(i64 %22, i64 0)
  %24 = load i64, i64* %abs_value, align 8
  store i64 %24, i64* %a, align 8
  store i64 65, i64* %index, align 8
  br label %WhileCond

WhileCond:                                        ; preds = %EndIf, %Entry
  br label %WhileBody

WhileBody:                                        ; preds = %WhileCond
  %25 = load i64, i64* %a, align 8
  %26 = load i8, i8* %base, align 1
  %27 = zext i8 %26 to i64
  %28 = icmp eq i64 %27, 0
  br i1 %28, label %RemZeroFail, label %RemZeroOk

Then:                                             ; preds = %DivZeroOk
  br label %WhileEnd

Else:                                             ; preds = %DivZeroOk
  br label %EndIf

EndIf:                                            ; preds = %Else
  br label %WhileCond

WhileEnd:                                         ; preds = %Then
  %29 = load i64, i64* %index, align 8
  %30 = icmp ule i64 %29, 65
  br i1 %30, label %BoundsCheckOk2, label %BoundsCheckFail1

RemZeroOk:                                        ; preds = %WhileBody
  %31 = urem i64 %25, %27
  store i64 %31, i64* %digit, align 8
  %32 = load i64, i64* %index, align 8
  %33 = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %32, i64 1)
  %34 = extractvalue { i64, i1 } %33, 0
  %35 = extractvalue { i64, i1 } %33, 1
  br i1 %35, label %OverflowFail, label %OverflowOk

RemZeroFail:                                      ; preds = %WhileBody
  call fastcc void @panic(%"[]u8"* @11, %std.builtin.StackTrace* null)
  unreachable

OverflowFail:                                     ; preds = %RemZeroOk
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk:                                       ; preds = %RemZeroOk
  store i64 %34, i64* %index, align 8
  %36 = load i64, i64* %index, align 8
  %37 = icmp ult i64 %36, 65
  br i1 %37, label %BoundsCheckOk, label %BoundsCheckFail

BoundsCheckFail:                                  ; preds = %OverflowOk
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk:                                    ; preds = %OverflowOk
  %38 = getelementptr inbounds [65 x i8], [65 x i8]* %buf, i64 0, i64 %36
  %39 = load i64, i64* %digit, align 8
  %40 = trunc i64 %39 to i8
  %41 = zext i8 %40 to i64
  %42 = icmp eq i64 %39, %41
  br i1 %42, label %CastShortenOk, label %CastShortenFail

CastShortenOk:                                    ; preds = %BoundsCheckOk
  %43 = load i1, i1* %uppercase, align 1
  %44 = call fastcc i8 @std.fmt.digitToChar(i8 %40, i1 %43)
  store i8 %44, i8* %38, align 1
  %45 = load i64, i64* %a, align 8
  %46 = load i8, i8* %base, align 1
  %47 = zext i8 %46 to i64
  %48 = icmp eq i64 %47, 0
  br i1 %48, label %DivZeroFail, label %DivZeroOk

CastShortenFail:                                  ; preds = %BoundsCheckOk
  call fastcc void @panic(%"[]u8"* @13, %std.builtin.StackTrace* null)
  unreachable

DivZeroFail:                                      ; preds = %CastShortenOk
  call fastcc void @panic(%"[]u8"* @9, %std.builtin.StackTrace* null)
  unreachable

DivZeroOk:                                        ; preds = %CastShortenOk
  %49 = udiv i64 %45, %47
  store i64 %49, i64* %a, align 8
  %50 = load i64, i64* %a, align 8
  %51 = icmp eq i64 %50, 0
  br i1 %51, label %Then, label %Else

BoundsCheckFail1:                                 ; preds = %WhileEnd
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk2:                                   ; preds = %WhileEnd
  br i1 true, label %BoundsCheckOk4, label %BoundsCheckFail3

BoundsCheckFail3:                                 ; preds = %BoundsCheckOk2
  call fastcc void @panic(%"[]u8"* @15, %std.builtin.StackTrace* null)
  unreachable

BoundsCheckOk4:                                   ; preds = %BoundsCheckOk2
  %52 = getelementptr inbounds [65 x i8], [65 x i8]* %buf, i64 0, i64 %29
  %53 = sub nuw i64 65, %29
  %54 = getelementptr inbounds %"[]u8", %"[]u8"* %7, i32 0, i32 0
  store i8* %52, i8** %54, align 8
  %55 = getelementptr inbounds %"[]u8", %"[]u8"* %7, i32 0, i32 1
  store i64 %53, i64* %55, align 8
  %56 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %4 to i8*
  %57 = bitcast %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %8 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %57, i8* align 4 %56, i64 4, i1 false)
  %58 = call fastcc i16 @std.fmt.formatBuf(%"[]u8"* %7, %std.fmt.FormatOptions* %3, %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %4)
  store i16 %58, i16* %result, align 2
  %59 = load i16, i16* %result, align 2
  ret i16 %59
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i64 @std.math.absCast(i64 %0) unnamed_addr #1 {
Entry:
  %result = alloca i64, align 8
  %x = alloca i64, align 8
  store i64 %0, i64* %x, align 8
  %1 = load i64, i64* %x, align 8
  store i64 %1, i64* %result, align 8
  %2 = load i64, i64* %result, align 8
  ret i64 %2
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i8 @std.fmt.digitToChar(i8 %0, i1 %1) unnamed_addr #1 {
Entry:
  %result = alloca i8, align 1
  %2 = alloca i8, align 1
  %digit = alloca i8, align 1
  %uppercase = alloca i1, align 1
  store i8 %0, i8* %digit, align 1
  store i1 %1, i1* %uppercase, align 1
  %3 = load i8, i8* %digit, align 1
  %4 = icmp ule i8 %3, 9
  %5 = and i1 true, %4
  br i1 %5, label %SwitchRangeYes, label %SwitchRangeNo

SwitchRangeYes:                                   ; preds = %Entry
  %6 = load i8, i8* %digit, align 1
  %7 = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %6, i8 48)
  %8 = extractvalue { i8, i1 } %7, 0
  %9 = extractvalue { i8, i1 } %7, 1
  br i1 %9, label %OverflowFail, label %OverflowOk

SwitchRangeNo:                                    ; preds = %Entry
  %10 = icmp uge i8 %3, 10
  %11 = icmp ule i8 %3, 35
  %12 = and i1 %10, %11
  br i1 %12, label %SwitchRangeYes1, label %SwitchRangeNo2

SwitchRangeYes1:                                  ; preds = %SwitchRangeNo
  %13 = load i8, i8* %digit, align 1
  %14 = load i1, i1* %uppercase, align 1
  br i1 %14, label %Then, label %Else

Then:                                             ; preds = %SwitchRangeYes1
  store i8 65, i8* %2, align 1
  store i8 65, i8* %2, align 1
  br label %EndIf

Else:                                             ; preds = %SwitchRangeYes1
  store i8 97, i8* %2, align 1
  store i8 97, i8* %2, align 1
  br label %EndIf

EndIf:                                            ; preds = %Else, %Then
  %15 = phi i8 [ 65, %Then ], [ 97, %Else ]
  %16 = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %15, i8 10)
  %17 = extractvalue { i8, i1 } %16, 0
  %18 = extractvalue { i8, i1 } %16, 1
  br i1 %18, label %OverflowFail3, label %OverflowOk4

SwitchRangeNo2:                                   ; preds = %SwitchRangeNo
  br label %SwitchElse

SwitchElse:                                       ; preds = %SwitchRangeNo2
  call fastcc void @panic(%"[]u8"* @17, %std.builtin.StackTrace* null)
  unreachable

SwitchEnd:                                        ; preds = %OverflowOk6, %OverflowOk
  %19 = load i8, i8* %result, align 1
  ret i8 %19

OverflowFail:                                     ; preds = %SwitchRangeYes
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk:                                       ; preds = %SwitchRangeYes
  store i8 %8, i8* %result, align 1
  br label %SwitchEnd

OverflowFail3:                                    ; preds = %EndIf
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk4:                                      ; preds = %EndIf
  %20 = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %13, i8 %17)
  %21 = extractvalue { i8, i1 } %20, 0
  %22 = extractvalue { i8, i1 } %20, 1
  br i1 %22, label %OverflowFail5, label %OverflowOk6

OverflowFail5:                                    ; preds = %OverflowOk4
  call fastcc void @panic(%"[]u8"* @32, %std.builtin.StackTrace* null)
  unreachable

OverflowOk6:                                      ; preds = %OverflowOk4
  store i8 %21, i8* %result, align 1
  br label %SwitchEnd
}

; Function Attrs: nounwind readnone speculatable willreturn
declare { i8, i1 } @llvm.uadd.with.overflow.i8(i8, i8) #4

; Function Attrs: nounwind readnone speculatable willreturn
declare { i8, i1 } @llvm.usub.with.overflow.i8(i8, i8) #4

; Function Attrs: nounwind
declare void @llvm.stackprotector(i8*, i8**) #6

attributes #0 = { nobuiltin noreturn nounwind "frame-pointer"="all" "probe-stack"="__zig_probe_stack" }
attributes #1 = { nobuiltin nounwind "frame-pointer"="all" "probe-stack"="__zig_probe_stack" }
attributes #2 = { nobuiltin noinline nounwind alignstack=16 "frame-pointer"="all" "probe-stack"="__zig_probe_stack" }
attributes #3 = { argmemonly nounwind willreturn }
attributes #4 = { nounwind readnone speculatable willreturn }
attributes #5 = { argmemonly nounwind willreturn writeonly }
attributes #6 = { nounwind }

!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}

!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = !{i32 2, !"Dwarf Version", i32 4}
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "zig 0.7.0", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !4)
!3 = !DIFile(filename: "foo", directory: "/tmp")
!4 = !{!5, !12, !53, !73, !79, !133, !155, !161, !167, !173, !177, !182, !320, !341, !347}
!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.builtin.OutputMode", scope: !6, file: !6, line: 450, baseType: !7, size: 8, align: 8, elements: !8)
!6 = !DIFile(filename: "builtin.zig", directory: "/home/lemonboy/code/zig/lib/std")
!7 = !DIBasicType(name: "u2", size: 8, encoding: DW_ATE_unsigned)
!8 = !{!9, !10, !11}
!9 = !DIEnumerator(name: "Exe", value: 0)
!10 = !DIEnumerator(name: "Lib", value: 1)
!11 = !DIEnumerator(name: "Obj", value: 2)
!12 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.target.Tag", scope: !13, file: !13, line: 23, baseType: !14, size: 8, align: 8, elements: !15)
!13 = !DIFile(filename: "target.zig", directory: "/home/lemonboy/code/zig/lib/std")
!14 = !DIBasicType(name: "u6", size: 8, encoding: DW_ATE_unsigned)
!15 = !{!16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45, !46, !47, !48, !49, !50, !51, !52}
!16 = !DIEnumerator(name: "freestanding", value: 0)
!17 = !DIEnumerator(name: "ananas", value: 1)
!18 = !DIEnumerator(name: "cloudabi", value: 2)
!19 = !DIEnumerator(name: "dragonfly", value: 3)
!20 = !DIEnumerator(name: "freebsd", value: 4)
!21 = !DIEnumerator(name: "fuchsia", value: 5)
!22 = !DIEnumerator(name: "ios", value: 6)
!23 = !DIEnumerator(name: "kfreebsd", value: 7)
!24 = !DIEnumerator(name: "linux", value: 8)
!25 = !DIEnumerator(name: "lv2", value: 9)
!26 = !DIEnumerator(name: "macos", value: 10)
!27 = !DIEnumerator(name: "netbsd", value: 11)
!28 = !DIEnumerator(name: "openbsd", value: 12)
!29 = !DIEnumerator(name: "solaris", value: 13)
!30 = !DIEnumerator(name: "windows", value: 14)
!31 = !DIEnumerator(name: "haiku", value: 15)
!32 = !DIEnumerator(name: "minix", value: 16)
!33 = !DIEnumerator(name: "rtems", value: 17)
!34 = !DIEnumerator(name: "nacl", value: 18)
!35 = !DIEnumerator(name: "cnk", value: 19)
!36 = !DIEnumerator(name: "aix", value: 20)
!37 = !DIEnumerator(name: "cuda", value: 21)
!38 = !DIEnumerator(name: "nvcl", value: 22)
!39 = !DIEnumerator(name: "amdhsa", value: 23)
!40 = !DIEnumerator(name: "ps4", value: 24)
!41 = !DIEnumerator(name: "elfiamcu", value: 25)
!42 = !DIEnumerator(name: "tvos", value: 26)
!43 = !DIEnumerator(name: "watchos", value: 27)
!44 = !DIEnumerator(name: "mesa3d", value: 28)
!45 = !DIEnumerator(name: "contiki", value: 29)
!46 = !DIEnumerator(name: "amdpal", value: 30)
!47 = !DIEnumerator(name: "hermit", value: 31)
!48 = !DIEnumerator(name: "hurd", value: 32)
!49 = !DIEnumerator(name: "wasi", value: 33)
!50 = !DIEnumerator(name: "emscripten", value: 34)
!51 = !DIEnumerator(name: "uefi", value: 35)
!52 = !DIEnumerator(name: "other", value: 36)
!53 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.target.WindowsVersion", scope: !13, file: !13, line: 89, baseType: !54, size: 32, align: 32, elements: !55)
!54 = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned)
!55 = !{!56, !57, !58, !59, !60, !61, !62, !63, !64, !65, !66, !67, !68, !69, !70, !71, !72}
!56 = !DIEnumerator(name: "nt4", value: 67108864)
!57 = !DIEnumerator(name: "win2k", value: 83886080)
!58 = !DIEnumerator(name: "xp", value: 83951616)
!59 = !DIEnumerator(name: "ws2003", value: 84017152)
!60 = !DIEnumerator(name: "vista", value: 100663296)
!61 = !DIEnumerator(name: "win7", value: 100728832)
!62 = !DIEnumerator(name: "win8", value: 100794368)
!63 = !DIEnumerator(name: "win8_1", value: 100859904)
!64 = !DIEnumerator(name: "win10", value: 167772160)
!65 = !DIEnumerator(name: "win10_th2", value: 167772161)
!66 = !DIEnumerator(name: "win10_rs1", value: 167772162)
!67 = !DIEnumerator(name: "win10_rs2", value: 167772163)
!68 = !DIEnumerator(name: "win10_rs3", value: 167772164)
!69 = !DIEnumerator(name: "win10_rs4", value: 167772165)
!70 = !DIEnumerator(name: "win10_rs5", value: 167772166)
!71 = !DIEnumerator(name: "win10_19h1", value: 167772167)
!72 = !DIEnumerator(name: "win10_20h1", value: 167772168)
!73 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "@TagType(std.target.VersionRange)", scope: !13, file: !13, line: 192, baseType: !7, size: 8, align: 8, elements: !74)
!74 = !{!75, !76, !77, !78}
!75 = !DIEnumerator(name: "none", value: 0)
!76 = !DIEnumerator(name: "semver", value: 1)
!77 = !DIEnumerator(name: "linux", value: 2)
!78 = !DIEnumerator(name: "windows", value: 3)
!79 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.target.Arch", scope: !13, file: !13, line: 666, baseType: !14, size: 8, align: 8, elements: !80)
!80 = !{!81, !82, !83, !84, !85, !86, !87, !88, !89, !90, !91, !92, !93, !94, !95, !96, !97, !98, !99, !100, !101, !102, !103, !104, !105, !106, !107, !108, !109, !110, !111, !112, !113, !114, !115, !116, !117, !118, !119, !120, !121, !122, !123, !124, !125, !126, !127, !128, !129, !130, !131, !132}
!81 = !DIEnumerator(name: "arm", value: 0)
!82 = !DIEnumerator(name: "armeb", value: 1)
!83 = !DIEnumerator(name: "aarch64", value: 2)
!84 = !DIEnumerator(name: "aarch64_be", value: 3)
!85 = !DIEnumerator(name: "aarch64_32", value: 4)
!86 = !DIEnumerator(name: "arc", value: 5)
!87 = !DIEnumerator(name: "avr", value: 6)
!88 = !DIEnumerator(name: "bpfel", value: 7)
!89 = !DIEnumerator(name: "bpfeb", value: 8)
!90 = !DIEnumerator(name: "hexagon", value: 9)
!91 = !DIEnumerator(name: "mips", value: 10)
!92 = !DIEnumerator(name: "mipsel", value: 11)
!93 = !DIEnumerator(name: "mips64", value: 12)
!94 = !DIEnumerator(name: "mips64el", value: 13)
!95 = !DIEnumerator(name: "msp430", value: 14)
!96 = !DIEnumerator(name: "powerpc", value: 15)
!97 = !DIEnumerator(name: "powerpc64", value: 16)
!98 = !DIEnumerator(name: "powerpc64le", value: 17)
!99 = !DIEnumerator(name: "r600", value: 18)
!100 = !DIEnumerator(name: "amdgcn", value: 19)
!101 = !DIEnumerator(name: "riscv32", value: 20)
!102 = !DIEnumerator(name: "riscv64", value: 21)
!103 = !DIEnumerator(name: "sparc", value: 22)
!104 = !DIEnumerator(name: "sparcv9", value: 23)
!105 = !DIEnumerator(name: "sparcel", value: 24)
!106 = !DIEnumerator(name: "s390x", value: 25)
!107 = !DIEnumerator(name: "tce", value: 26)
!108 = !DIEnumerator(name: "tcele", value: 27)
!109 = !DIEnumerator(name: "thumb", value: 28)
!110 = !DIEnumerator(name: "thumbeb", value: 29)
!111 = !DIEnumerator(name: "i386", value: 30)
!112 = !DIEnumerator(name: "x86_64", value: 31)
!113 = !DIEnumerator(name: "xcore", value: 32)
!114 = !DIEnumerator(name: "nvptx", value: 33)
!115 = !DIEnumerator(name: "nvptx64", value: 34)
!116 = !DIEnumerator(name: "le32", value: 35)
!117 = !DIEnumerator(name: "le64", value: 36)
!118 = !DIEnumerator(name: "amdil", value: 37)
!119 = !DIEnumerator(name: "amdil64", value: 38)
!120 = !DIEnumerator(name: "hsail", value: 39)
!121 = !DIEnumerator(name: "hsail64", value: 40)
!122 = !DIEnumerator(name: "spir", value: 41)
!123 = !DIEnumerator(name: "spir64", value: 42)
!124 = !DIEnumerator(name: "kalimba", value: 43)
!125 = !DIEnumerator(name: "shave", value: 44)
!126 = !DIEnumerator(name: "lanai", value: 45)
!127 = !DIEnumerator(name: "wasm32", value: 46)
!128 = !DIEnumerator(name: "wasm64", value: 47)
!129 = !DIEnumerator(name: "renderscript32", value: 48)
!130 = !DIEnumerator(name: "renderscript64", value: 49)
!131 = !DIEnumerator(name: "ve", value: 50)
!132 = !DIEnumerator(name: "spu_2", value: 51)
!133 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.target.Abi", scope: !13, file: !13, line: 402, baseType: !134, size: 8, align: 8, elements: !135)
!134 = !DIBasicType(name: "u5", size: 8, encoding: DW_ATE_unsigned)
!135 = !{!75, !136, !137, !138, !139, !140, !141, !142, !143, !144, !145, !146, !147, !148, !149, !150, !151, !152, !153, !154}
!136 = !DIEnumerator(name: "gnu", value: 1)
!137 = !DIEnumerator(name: "gnuabin32", value: 2)
!138 = !DIEnumerator(name: "gnuabi64", value: 3)
!139 = !DIEnumerator(name: "gnueabi", value: 4)
!140 = !DIEnumerator(name: "gnueabihf", value: 5)
!141 = !DIEnumerator(name: "gnux32", value: 6)
!142 = !DIEnumerator(name: "code16", value: 7)
!143 = !DIEnumerator(name: "eabi", value: 8)
!144 = !DIEnumerator(name: "eabihf", value: 9)
!145 = !DIEnumerator(name: "android", value: 10)
!146 = !DIEnumerator(name: "musl", value: 11)
!147 = !DIEnumerator(name: "musleabi", value: 12)
!148 = !DIEnumerator(name: "musleabihf", value: 13)
!149 = !DIEnumerator(name: "msvc", value: 14)
!150 = !DIEnumerator(name: "itanium", value: 15)
!151 = !DIEnumerator(name: "cygnus", value: 16)
!152 = !DIEnumerator(name: "coreclr", value: 17)
!153 = !DIEnumerator(name: "simulator", value: 18)
!154 = !DIEnumerator(name: "macabi", value: 19)
!155 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.builtin.Mode", scope: !6, file: !6, line: 144, baseType: !7, size: 8, align: 8, elements: !156)
!156 = !{!157, !158, !159, !160}
!157 = !DIEnumerator(name: "Debug", value: 0)
!158 = !DIEnumerator(name: "ReleaseSafe", value: 1)
!159 = !DIEnumerator(name: "ReleaseFast", value: 2)
!160 = !DIEnumerator(name: "ReleaseSmall", value: 3)
!161 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.io.Mode", scope: !162, file: !162, line: 20, baseType: !163, size: 8, align: 8, elements: !164)
!162 = !DIFile(filename: "io.zig", directory: "/home/lemonboy/code/zig/lib/std")
!163 = !DIBasicType(name: "u1", size: 8, encoding: DW_ATE_unsigned)
!164 = !{!165, !166}
!165 = !DIEnumerator(name: "blocking", value: 0)
!166 = !DIEnumerator(name: "evented", value: 1)
!167 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "@TagType(ParamType)", scope: !168, file: !168, line: 13, baseType: !7, size: 8, align: 8, elements: !169)
!168 = !DIFile(filename: "foo.zig", directory: "/tmp")
!169 = !{!170, !171, !172}
!170 = !DIEnumerator(name: "boolean", value: 0)
!171 = !DIEnumerator(name: "buffer", value: 1)
!172 = !DIEnumerator(name: "one_of", value: 2)
!173 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "@TagType(Expression)", scope: !168, file: !168, line: 25, baseType: !163, size: 8, align: 8, elements: !174)
!174 = !{!175, !176}
!175 = !DIEnumerator(name: "literal_boolean", value: 0)
!176 = !DIEnumerator(name: "literal_enum_value", value: 1)
!177 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "@TagType(ExpressionResult)", scope: !168, file: !168, line: 34, baseType: !7, size: 8, align: 8, elements: !178)
!178 = !{!179, !180, !181}
!179 = !DIEnumerator(name: "temp_buffer", value: 0)
!180 = !DIEnumerator(name: "literal_boolean", value: 1)
!181 = !DIEnumerator(name: "literal_enum_value", value: 2)
!182 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.target.x86.Feature", scope: !183, file: !183, line: 10, baseType: !184, size: 8, align: 8, elements: !185)
!183 = !DIFile(filename: "x86.zig", directory: "/home/lemonboy/code/zig/lib/std/target")
!184 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned_char)
!185 = !{!186, !187, !188, !189, !190, !191, !192, !193, !194, !195, !196, !197, !198, !199, !200, !201, !202, !203, !204, !205, !206, !207, !208, !209, !210, !211, !212, !213, !214, !215, !216, !217, !218, !219, !220, !221, !222, !223, !224, !225, !226, !227, !228, !229, !230, !231, !232, !233, !234, !235, !236, !237, !238, !239, !240, !241, !242, !243, !244, !245, !246, !247, !248, !249, !250, !251, !252, !253, !254, !255, !256, !257, !258, !259, !260, !261, !262, !263, !264, !265, !266, !267, !268, !269, !270, !271, !272, !273, !274, !275, !276, !277, !278, !279, !280, !281, !282, !283, !284, !285, !286, !287, !288, !289, !290, !291, !292, !293, !294, !295, !296, !297, !298, !299, !300, !301, !302, !303, !304, !305, !306, !307, !308, !309, !310, !311, !312, !313, !314, !315, !316, !317, !318, !319}
!186 = !DIEnumerator(name: "3dnow", value: 0)
!187 = !DIEnumerator(name: "3dnowa", value: 1)
!188 = !DIEnumerator(name: "64bit", value: 2)
!189 = !DIEnumerator(name: "adx", value: 3)
!190 = !DIEnumerator(name: "aes", value: 4)
!191 = !DIEnumerator(name: "amx_bf16", value: 5)
!192 = !DIEnumerator(name: "amx_int8", value: 6)
!193 = !DIEnumerator(name: "amx_tile", value: 7)
!194 = !DIEnumerator(name: "avx", value: 8)
!195 = !DIEnumerator(name: "avx2", value: 9)
!196 = !DIEnumerator(name: "avx512bf16", value: 10)
!197 = !DIEnumerator(name: "avx512bitalg", value: 11)
!198 = !DIEnumerator(name: "avx512bw", value: 12)
!199 = !DIEnumerator(name: "avx512cd", value: 13)
!200 = !DIEnumerator(name: "avx512dq", value: 14)
!201 = !DIEnumerator(name: "avx512er", value: 15)
!202 = !DIEnumerator(name: "avx512f", value: 16)
!203 = !DIEnumerator(name: "avx512ifma", value: 17)
!204 = !DIEnumerator(name: "avx512pf", value: 18)
!205 = !DIEnumerator(name: "avx512vbmi", value: 19)
!206 = !DIEnumerator(name: "avx512vbmi2", value: 20)
!207 = !DIEnumerator(name: "avx512vl", value: 21)
!208 = !DIEnumerator(name: "avx512vnni", value: 22)
!209 = !DIEnumerator(name: "avx512vp2intersect", value: 23)
!210 = !DIEnumerator(name: "avx512vpopcntdq", value: 24)
!211 = !DIEnumerator(name: "bmi", value: 25)
!212 = !DIEnumerator(name: "bmi2", value: 26)
!213 = !DIEnumerator(name: "branchfusion", value: 27)
!214 = !DIEnumerator(name: "cldemote", value: 28)
!215 = !DIEnumerator(name: "clflushopt", value: 29)
!216 = !DIEnumerator(name: "clwb", value: 30)
!217 = !DIEnumerator(name: "clzero", value: 31)
!218 = !DIEnumerator(name: "cmov", value: 32)
!219 = !DIEnumerator(name: "cx16", value: 33)
!220 = !DIEnumerator(name: "cx8", value: 34)
!221 = !DIEnumerator(name: "enqcmd", value: 35)
!222 = !DIEnumerator(name: "ermsb", value: 36)
!223 = !DIEnumerator(name: "f16c", value: 37)
!224 = !DIEnumerator(name: "false_deps_lzcnt_tzcnt", value: 38)
!225 = !DIEnumerator(name: "false_deps_popcnt", value: 39)
!226 = !DIEnumerator(name: "fast_11bytenop", value: 40)
!227 = !DIEnumerator(name: "fast_15bytenop", value: 41)
!228 = !DIEnumerator(name: "fast_7bytenop", value: 42)
!229 = !DIEnumerator(name: "fast_bextr", value: 43)
!230 = !DIEnumerator(name: "fast_gather", value: 44)
!231 = !DIEnumerator(name: "fast_hops", value: 45)
!232 = !DIEnumerator(name: "fast_lzcnt", value: 46)
!233 = !DIEnumerator(name: "fast_scalar_fsqrt", value: 47)
!234 = !DIEnumerator(name: "fast_scalar_shift_masks", value: 48)
!235 = !DIEnumerator(name: "fast_shld_rotate", value: 49)
!236 = !DIEnumerator(name: "fast_variable_shuffle", value: 50)
!237 = !DIEnumerator(name: "fast_vector_fsqrt", value: 51)
!238 = !DIEnumerator(name: "fast_vector_shift_masks", value: 52)
!239 = !DIEnumerator(name: "fma", value: 53)
!240 = !DIEnumerator(name: "fma4", value: 54)
!241 = !DIEnumerator(name: "fsgsbase", value: 55)
!242 = !DIEnumerator(name: "fxsr", value: 56)
!243 = !DIEnumerator(name: "gfni", value: 57)
!244 = !DIEnumerator(name: "idivl_to_divb", value: 58)
!245 = !DIEnumerator(name: "idivq_to_divl", value: 59)
!246 = !DIEnumerator(name: "invpcid", value: 60)
!247 = !DIEnumerator(name: "lea_sp", value: 61)
!248 = !DIEnumerator(name: "lea_uses_ag", value: 62)
!249 = !DIEnumerator(name: "lvi_cfi", value: 63)
!250 = !DIEnumerator(name: "lvi_load_hardening", value: 64)
!251 = !DIEnumerator(name: "lwp", value: 65)
!252 = !DIEnumerator(name: "lzcnt", value: 66)
!253 = !DIEnumerator(name: "macrofusion", value: 67)
!254 = !DIEnumerator(name: "merge_to_threeway_branch", value: 68)
!255 = !DIEnumerator(name: "mmx", value: 69)
!256 = !DIEnumerator(name: "movbe", value: 70)
!257 = !DIEnumerator(name: "movdir64b", value: 71)
!258 = !DIEnumerator(name: "movdiri", value: 72)
!259 = !DIEnumerator(name: "mpx", value: 73)
!260 = !DIEnumerator(name: "mwaitx", value: 74)
!261 = !DIEnumerator(name: "nopl", value: 75)
!262 = !DIEnumerator(name: "pad_short_functions", value: 76)
!263 = !DIEnumerator(name: "pclmul", value: 77)
!264 = !DIEnumerator(name: "pconfig", value: 78)
!265 = !DIEnumerator(name: "pku", value: 79)
!266 = !DIEnumerator(name: "popcnt", value: 80)
!267 = !DIEnumerator(name: "prefer_128_bit", value: 81)
!268 = !DIEnumerator(name: "prefer_256_bit", value: 82)
!269 = !DIEnumerator(name: "prefer_mask_registers", value: 83)
!270 = !DIEnumerator(name: "prefetchwt1", value: 84)
!271 = !DIEnumerator(name: "prfchw", value: 85)
!272 = !DIEnumerator(name: "ptwrite", value: 86)
!273 = !DIEnumerator(name: "rdpid", value: 87)
!274 = !DIEnumerator(name: "rdrnd", value: 88)
!275 = !DIEnumerator(name: "rdseed", value: 89)
!276 = !DIEnumerator(name: "retpoline", value: 90)
!277 = !DIEnumerator(name: "retpoline_external_thunk", value: 91)
!278 = !DIEnumerator(name: "retpoline_indirect_branches", value: 92)
!279 = !DIEnumerator(name: "retpoline_indirect_calls", value: 93)
!280 = !DIEnumerator(name: "rtm", value: 94)
!281 = !DIEnumerator(name: "sahf", value: 95)
!282 = !DIEnumerator(name: "serialize", value: 96)
!283 = !DIEnumerator(name: "seses", value: 97)
!284 = !DIEnumerator(name: "sgx", value: 98)
!285 = !DIEnumerator(name: "sha", value: 99)
!286 = !DIEnumerator(name: "shstk", value: 100)
!287 = !DIEnumerator(name: "slow_3ops_lea", value: 101)
!288 = !DIEnumerator(name: "slow_incdec", value: 102)
!289 = !DIEnumerator(name: "slow_lea", value: 103)
!290 = !DIEnumerator(name: "slow_pmaddwd", value: 104)
!291 = !DIEnumerator(name: "slow_pmulld", value: 105)
!292 = !DIEnumerator(name: "slow_shld", value: 106)
!293 = !DIEnumerator(name: "slow_two_mem_ops", value: 107)
!294 = !DIEnumerator(name: "slow_unaligned_mem_16", value: 108)
!295 = !DIEnumerator(name: "slow_unaligned_mem_32", value: 109)
!296 = !DIEnumerator(name: "soft_float", value: 110)
!297 = !DIEnumerator(name: "sse", value: 111)
!298 = !DIEnumerator(name: "sse_unaligned_mem", value: 112)
!299 = !DIEnumerator(name: "sse2", value: 113)
!300 = !DIEnumerator(name: "sse3", value: 114)
!301 = !DIEnumerator(name: "sse4_1", value: 115)
!302 = !DIEnumerator(name: "sse4_2", value: 116)
!303 = !DIEnumerator(name: "sse4a", value: 117)
!304 = !DIEnumerator(name: "ssse3", value: 118)
!305 = !DIEnumerator(name: "tbm", value: 119)
!306 = !DIEnumerator(name: "tsxldtrk", value: 120)
!307 = !DIEnumerator(name: "use_aa", value: 121)
!308 = !DIEnumerator(name: "use_glm_div_sqrt_costs", value: 122)
!309 = !DIEnumerator(name: "vaes", value: 123)
!310 = !DIEnumerator(name: "vpclmulqdq", value: 124)
!311 = !DIEnumerator(name: "vzeroupper", value: 125)
!312 = !DIEnumerator(name: "waitpkg", value: 126)
!313 = !DIEnumerator(name: "wbnoinvd", value: 127)
!314 = !DIEnumerator(name: "x87", value: 128)
!315 = !DIEnumerator(name: "xop", value: 129)
!316 = !DIEnumerator(name: "xsave", value: 130)
!317 = !DIEnumerator(name: "xsavec", value: 131)
!318 = !DIEnumerator(name: "xsaveopt", value: 132)
!319 = !DIEnumerator(name: "xsaves", value: 133)
!320 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "anyerror", baseType: !321, size: 16, align: 16, elements: !322)
!321 = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned)
!322 = !{!323, !324, !325, !326, !327, !328, !329, !330, !331, !332, !333, !334, !335, !336, !337, !338, !339, !340}
!323 = !DIEnumerator(name: "(none)", value: 0)
!324 = !DIEnumerator(name: "DiskQuota", value: 1)
!325 = !DIEnumerator(name: "FileTooBig", value: 2)
!326 = !DIEnumerator(name: "InputOutput", value: 3)
!327 = !DIEnumerator(name: "NoSpaceLeft", value: 4)
!328 = !DIEnumerator(name: "AccessDenied", value: 5)
!329 = !DIEnumerator(name: "BrokenPipe", value: 6)
!330 = !DIEnumerator(name: "SystemResources", value: 7)
!331 = !DIEnumerator(name: "OperationAborted", value: 8)
!332 = !DIEnumerator(name: "NotOpenForWriting", value: 9)
!333 = !DIEnumerator(name: "WouldBlock", value: 10)
!334 = !DIEnumerator(name: "Unexpected", value: 11)
!335 = !DIEnumerator(name: "Utf8InvalidStartByte", value: 12)
!336 = !DIEnumerator(name: "TruncatedInput", value: 13)
!337 = !DIEnumerator(name: "Utf8ExpectedContinuation", value: 14)
!338 = !DIEnumerator(name: "Utf8OverlongEncoding", value: 15)
!339 = !DIEnumerator(name: "Utf8EncodesSurrogateHalf", value: 16)
!340 = !DIEnumerator(name: "Utf8CodepointTooLarge", value: 17)
!341 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.fmt.Alignment", scope: !342, file: !342, line: 18, baseType: !7, size: 8, align: 8, elements: !343)
!342 = !DIFile(filename: "fmt.zig", directory: "/home/lemonboy/code/zig/lib/std")
!343 = !{!344, !345, !346}
!344 = !DIEnumerator(name: "Left", value: 0)
!345 = !DIEnumerator(name: "Center", value: 1)
!346 = !DIEnumerator(name: "Right", value: 2)
!347 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.os.bits.linux.x86_64.SYS", scope: !348, file: !348, line: 24, baseType: !349, size: 64, align: 64, elements: !350)
!348 = !DIFile(filename: "x86_64.zig", directory: "/home/lemonboy/code/zig/lib/std/os/bits/linux")
!349 = !DIBasicType(name: "usize", size: 64, encoding: DW_ATE_unsigned)
!350 = !{!351, !352, !353, !354, !355, !356, !357, !358, !359, !360, !361, !362, !363, !364, !365, !366, !367, !368, !369, !370, !371, !372, !373, !374, !375, !376, !377, !378, !379, !380, !381, !382, !383, !384, !385, !386, !387, !388, !389, !390, !391, !392, !393, !394, !395, !396, !397, !398, !399, !400, !401, !402, !403, !404, !405, !406, !407, !408, !409, !410, !411, !412, !413, !414, !415, !416, !417, !418, !419, !420, !421, !422, !423, !424, !425, !426, !427, !428, !429, !430, !431, !432, !433, !434, !435, !436, !437, !438, !439, !440, !441, !442, !443, !444, !445, !446, !447, !448, !449, !450, !451, !452, !453, !454, !455, !456, !457, !458, !459, !460, !461, !462, !463, !464, !465, !466, !467, !468, !469, !470, !471, !472, !473, !474, !475, !476, !477, !478, !479, !480, !481, !482, !483, !484, !485, !486, !487, !488, !489, !490, !491, !492, !493, !494, !495, !496, !497, !498, !499, !500, !501, !502, !503, !504, !505, !506, !507, !508, !509, !510, !511, !512, !513, !514, !515, !516, !517, !518, !519, !520, !521, !522, !523, !524, !525, !526, !527, !528, !529, !530, !531, !532, !533, !534, !535, !536, !537, !538, !539, !540, !541, !542, !543, !544, !545, !546, !547, !548, !549, !550, !551, !552, !553, !554, !555, !556, !557, !558, !559, !560, !561, !562, !563, !564, !565, !566, !567, !568, !569, !570, !571, !572, !573, !574, !575, !576, !577, !578, !579, !580, !581, !582, !583, !584, !585, !586, !587, !588, !589, !590, !591, !592, !593, !594, !595, !596, !597, !598, !599, !600, !601, !602, !603, !604, !605, !606, !607, !608, !609, !610, !611, !612, !613, !614, !615, !616, !617, !618, !619, !620, !621, !622, !623, !624, !625, !626, !627, !628, !629, !630, !631, !632, !633, !634, !635, !636, !637, !638, !639, !640, !641, !642, !643, !644, !645, !646, !647, !648, !649, !650, !651, !652, !653, !654, !655, !656, !657, !658, !659, !660, !661, !662, !663, !664, !665, !666, !667, !668, !669, !670, !671, !672, !673, !674, !675, !676, !677, !678, !679, !680, !681, !682, !683, !684, !685, !686, !687, !688, !689, !690, !691, !692, !693, !694, !695, !696, !697, !698, !699, !700}
!351 = !DIEnumerator(name: "read", value: 0)
!352 = !DIEnumerator(name: "write", value: 1)
!353 = !DIEnumerator(name: "open", value: 2)
!354 = !DIEnumerator(name: "close", value: 3)
!355 = !DIEnumerator(name: "stat", value: 4)
!356 = !DIEnumerator(name: "fstat", value: 5)
!357 = !DIEnumerator(name: "lstat", value: 6)
!358 = !DIEnumerator(name: "poll", value: 7)
!359 = !DIEnumerator(name: "lseek", value: 8)
!360 = !DIEnumerator(name: "mmap", value: 9)
!361 = !DIEnumerator(name: "mprotect", value: 10)
!362 = !DIEnumerator(name: "munmap", value: 11)
!363 = !DIEnumerator(name: "brk", value: 12)
!364 = !DIEnumerator(name: "rt_sigaction", value: 13)
!365 = !DIEnumerator(name: "rt_sigprocmask", value: 14)
!366 = !DIEnumerator(name: "rt_sigreturn", value: 15)
!367 = !DIEnumerator(name: "ioctl", value: 16)
!368 = !DIEnumerator(name: "pread", value: 17)
!369 = !DIEnumerator(name: "pwrite", value: 18)
!370 = !DIEnumerator(name: "readv", value: 19)
!371 = !DIEnumerator(name: "writev", value: 20)
!372 = !DIEnumerator(name: "access", value: 21)
!373 = !DIEnumerator(name: "pipe", value: 22)
!374 = !DIEnumerator(name: "select", value: 23)
!375 = !DIEnumerator(name: "sched_yield", value: 24)
!376 = !DIEnumerator(name: "mremap", value: 25)
!377 = !DIEnumerator(name: "msync", value: 26)
!378 = !DIEnumerator(name: "mincore", value: 27)
!379 = !DIEnumerator(name: "madvise", value: 28)
!380 = !DIEnumerator(name: "shmget", value: 29)
!381 = !DIEnumerator(name: "shmat", value: 30)
!382 = !DIEnumerator(name: "shmctl", value: 31)
!383 = !DIEnumerator(name: "dup", value: 32)
!384 = !DIEnumerator(name: "dup2", value: 33)
!385 = !DIEnumerator(name: "pause", value: 34)
!386 = !DIEnumerator(name: "nanosleep", value: 35)
!387 = !DIEnumerator(name: "getitimer", value: 36)
!388 = !DIEnumerator(name: "alarm", value: 37)
!389 = !DIEnumerator(name: "setitimer", value: 38)
!390 = !DIEnumerator(name: "getpid", value: 39)
!391 = !DIEnumerator(name: "sendfile", value: 40)
!392 = !DIEnumerator(name: "socket", value: 41)
!393 = !DIEnumerator(name: "connect", value: 42)
!394 = !DIEnumerator(name: "accept", value: 43)
!395 = !DIEnumerator(name: "sendto", value: 44)
!396 = !DIEnumerator(name: "recvfrom", value: 45)
!397 = !DIEnumerator(name: "sendmsg", value: 46)
!398 = !DIEnumerator(name: "recvmsg", value: 47)
!399 = !DIEnumerator(name: "shutdown", value: 48)
!400 = !DIEnumerator(name: "bind", value: 49)
!401 = !DIEnumerator(name: "listen", value: 50)
!402 = !DIEnumerator(name: "getsockname", value: 51)
!403 = !DIEnumerator(name: "getpeername", value: 52)
!404 = !DIEnumerator(name: "socketpair", value: 53)
!405 = !DIEnumerator(name: "setsockopt", value: 54)
!406 = !DIEnumerator(name: "getsockopt", value: 55)
!407 = !DIEnumerator(name: "clone", value: 56)
!408 = !DIEnumerator(name: "fork", value: 57)
!409 = !DIEnumerator(name: "vfork", value: 58)
!410 = !DIEnumerator(name: "execve", value: 59)
!411 = !DIEnumerator(name: "exit", value: 60)
!412 = !DIEnumerator(name: "wait4", value: 61)
!413 = !DIEnumerator(name: "kill", value: 62)
!414 = !DIEnumerator(name: "uname", value: 63)
!415 = !DIEnumerator(name: "semget", value: 64)
!416 = !DIEnumerator(name: "semop", value: 65)
!417 = !DIEnumerator(name: "semctl", value: 66)
!418 = !DIEnumerator(name: "shmdt", value: 67)
!419 = !DIEnumerator(name: "msgget", value: 68)
!420 = !DIEnumerator(name: "msgsnd", value: 69)
!421 = !DIEnumerator(name: "msgrcv", value: 70)
!422 = !DIEnumerator(name: "msgctl", value: 71)
!423 = !DIEnumerator(name: "fcntl", value: 72)
!424 = !DIEnumerator(name: "flock", value: 73)
!425 = !DIEnumerator(name: "fsync", value: 74)
!426 = !DIEnumerator(name: "fdatasync", value: 75)
!427 = !DIEnumerator(name: "truncate", value: 76)
!428 = !DIEnumerator(name: "ftruncate", value: 77)
!429 = !DIEnumerator(name: "getdents", value: 78)
!430 = !DIEnumerator(name: "getcwd", value: 79)
!431 = !DIEnumerator(name: "chdir", value: 80)
!432 = !DIEnumerator(name: "fchdir", value: 81)
!433 = !DIEnumerator(name: "rename", value: 82)
!434 = !DIEnumerator(name: "mkdir", value: 83)
!435 = !DIEnumerator(name: "rmdir", value: 84)
!436 = !DIEnumerator(name: "creat", value: 85)
!437 = !DIEnumerator(name: "link", value: 86)
!438 = !DIEnumerator(name: "unlink", value: 87)
!439 = !DIEnumerator(name: "symlink", value: 88)
!440 = !DIEnumerator(name: "readlink", value: 89)
!441 = !DIEnumerator(name: "chmod", value: 90)
!442 = !DIEnumerator(name: "fchmod", value: 91)
!443 = !DIEnumerator(name: "chown", value: 92)
!444 = !DIEnumerator(name: "fchown", value: 93)
!445 = !DIEnumerator(name: "lchown", value: 94)
!446 = !DIEnumerator(name: "umask", value: 95)
!447 = !DIEnumerator(name: "gettimeofday", value: 96)
!448 = !DIEnumerator(name: "getrlimit", value: 97)
!449 = !DIEnumerator(name: "getrusage", value: 98)
!450 = !DIEnumerator(name: "sysinfo", value: 99)
!451 = !DIEnumerator(name: "times", value: 100)
!452 = !DIEnumerator(name: "ptrace", value: 101)
!453 = !DIEnumerator(name: "getuid", value: 102)
!454 = !DIEnumerator(name: "syslog", value: 103)
!455 = !DIEnumerator(name: "getgid", value: 104)
!456 = !DIEnumerator(name: "setuid", value: 105)
!457 = !DIEnumerator(name: "setgid", value: 106)
!458 = !DIEnumerator(name: "geteuid", value: 107)
!459 = !DIEnumerator(name: "getegid", value: 108)
!460 = !DIEnumerator(name: "setpgid", value: 109)
!461 = !DIEnumerator(name: "getppid", value: 110)
!462 = !DIEnumerator(name: "getpgrp", value: 111)
!463 = !DIEnumerator(name: "setsid", value: 112)
!464 = !DIEnumerator(name: "setreuid", value: 113)
!465 = !DIEnumerator(name: "setregid", value: 114)
!466 = !DIEnumerator(name: "getgroups", value: 115)
!467 = !DIEnumerator(name: "setgroups", value: 116)
!468 = !DIEnumerator(name: "setresuid", value: 117)
!469 = !DIEnumerator(name: "getresuid", value: 118)
!470 = !DIEnumerator(name: "setresgid", value: 119)
!471 = !DIEnumerator(name: "getresgid", value: 120)
!472 = !DIEnumerator(name: "getpgid", value: 121)
!473 = !DIEnumerator(name: "setfsuid", value: 122)
!474 = !DIEnumerator(name: "setfsgid", value: 123)
!475 = !DIEnumerator(name: "getsid", value: 124)
!476 = !DIEnumerator(name: "capget", value: 125)
!477 = !DIEnumerator(name: "capset", value: 126)
!478 = !DIEnumerator(name: "rt_sigpending", value: 127)
!479 = !DIEnumerator(name: "rt_sigtimedwait", value: 128)
!480 = !DIEnumerator(name: "rt_sigqueueinfo", value: 129)
!481 = !DIEnumerator(name: "rt_sigsuspend", value: 130)
!482 = !DIEnumerator(name: "sigaltstack", value: 131)
!483 = !DIEnumerator(name: "utime", value: 132)
!484 = !DIEnumerator(name: "mknod", value: 133)
!485 = !DIEnumerator(name: "uselib", value: 134)
!486 = !DIEnumerator(name: "personality", value: 135)
!487 = !DIEnumerator(name: "ustat", value: 136)
!488 = !DIEnumerator(name: "statfs", value: 137)
!489 = !DIEnumerator(name: "fstatfs", value: 138)
!490 = !DIEnumerator(name: "sysfs", value: 139)
!491 = !DIEnumerator(name: "getpriority", value: 140)
!492 = !DIEnumerator(name: "setpriority", value: 141)
!493 = !DIEnumerator(name: "sched_setparam", value: 142)
!494 = !DIEnumerator(name: "sched_getparam", value: 143)
!495 = !DIEnumerator(name: "sched_setscheduler", value: 144)
!496 = !DIEnumerator(name: "sched_getscheduler", value: 145)
!497 = !DIEnumerator(name: "sched_get_priority_max", value: 146)
!498 = !DIEnumerator(name: "sched_get_priority_min", value: 147)
!499 = !DIEnumerator(name: "sched_rr_get_interval", value: 148)
!500 = !DIEnumerator(name: "mlock", value: 149)
!501 = !DIEnumerator(name: "munlock", value: 150)
!502 = !DIEnumerator(name: "mlockall", value: 151)
!503 = !DIEnumerator(name: "munlockall", value: 152)
!504 = !DIEnumerator(name: "vhangup", value: 153)
!505 = !DIEnumerator(name: "modify_ldt", value: 154)
!506 = !DIEnumerator(name: "pivot_root", value: 155)
!507 = !DIEnumerator(name: "_sysctl", value: 156)
!508 = !DIEnumerator(name: "prctl", value: 157)
!509 = !DIEnumerator(name: "arch_prctl", value: 158)
!510 = !DIEnumerator(name: "adjtimex", value: 159)
!511 = !DIEnumerator(name: "setrlimit", value: 160)
!512 = !DIEnumerator(name: "chroot", value: 161)
!513 = !DIEnumerator(name: "sync", value: 162)
!514 = !DIEnumerator(name: "acct", value: 163)
!515 = !DIEnumerator(name: "settimeofday", value: 164)
!516 = !DIEnumerator(name: "mount", value: 165)
!517 = !DIEnumerator(name: "umount2", value: 166)
!518 = !DIEnumerator(name: "swapon", value: 167)
!519 = !DIEnumerator(name: "swapoff", value: 168)
!520 = !DIEnumerator(name: "reboot", value: 169)
!521 = !DIEnumerator(name: "sethostname", value: 170)
!522 = !DIEnumerator(name: "setdomainname", value: 171)
!523 = !DIEnumerator(name: "iopl", value: 172)
!524 = !DIEnumerator(name: "ioperm", value: 173)
!525 = !DIEnumerator(name: "create_module", value: 174)
!526 = !DIEnumerator(name: "init_module", value: 175)
!527 = !DIEnumerator(name: "delete_module", value: 176)
!528 = !DIEnumerator(name: "get_kernel_syms", value: 177)
!529 = !DIEnumerator(name: "query_module", value: 178)
!530 = !DIEnumerator(name: "quotactl", value: 179)
!531 = !DIEnumerator(name: "nfsservctl", value: 180)
!532 = !DIEnumerator(name: "getpmsg", value: 181)
!533 = !DIEnumerator(name: "putpmsg", value: 182)
!534 = !DIEnumerator(name: "afs_syscall", value: 183)
!535 = !DIEnumerator(name: "tuxcall", value: 184)
!536 = !DIEnumerator(name: "security", value: 185)
!537 = !DIEnumerator(name: "gettid", value: 186)
!538 = !DIEnumerator(name: "readahead", value: 187)
!539 = !DIEnumerator(name: "setxattr", value: 188)
!540 = !DIEnumerator(name: "lsetxattr", value: 189)
!541 = !DIEnumerator(name: "fsetxattr", value: 190)
!542 = !DIEnumerator(name: "getxattr", value: 191)
!543 = !DIEnumerator(name: "lgetxattr", value: 192)
!544 = !DIEnumerator(name: "fgetxattr", value: 193)
!545 = !DIEnumerator(name: "listxattr", value: 194)
!546 = !DIEnumerator(name: "llistxattr", value: 195)
!547 = !DIEnumerator(name: "flistxattr", value: 196)
!548 = !DIEnumerator(name: "removexattr", value: 197)
!549 = !DIEnumerator(name: "lremovexattr", value: 198)
!550 = !DIEnumerator(name: "fremovexattr", value: 199)
!551 = !DIEnumerator(name: "tkill", value: 200)
!552 = !DIEnumerator(name: "time", value: 201)
!553 = !DIEnumerator(name: "futex", value: 202)
!554 = !DIEnumerator(name: "sched_setaffinity", value: 203)
!555 = !DIEnumerator(name: "sched_getaffinity", value: 204)
!556 = !DIEnumerator(name: "set_thread_area", value: 205)
!557 = !DIEnumerator(name: "io_setup", value: 206)
!558 = !DIEnumerator(name: "io_destroy", value: 207)
!559 = !DIEnumerator(name: "io_getevents", value: 208)
!560 = !DIEnumerator(name: "io_submit", value: 209)
!561 = !DIEnumerator(name: "io_cancel", value: 210)
!562 = !DIEnumerator(name: "get_thread_area", value: 211)
!563 = !DIEnumerator(name: "lookup_dcookie", value: 212)
!564 = !DIEnumerator(name: "epoll_create", value: 213)
!565 = !DIEnumerator(name: "epoll_ctl_old", value: 214)
!566 = !DIEnumerator(name: "epoll_wait_old", value: 215)
!567 = !DIEnumerator(name: "remap_file_pages", value: 216)
!568 = !DIEnumerator(name: "getdents64", value: 217)
!569 = !DIEnumerator(name: "set_tid_address", value: 218)
!570 = !DIEnumerator(name: "restart_syscall", value: 219)
!571 = !DIEnumerator(name: "semtimedop", value: 220)
!572 = !DIEnumerator(name: "fadvise64", value: 221)
!573 = !DIEnumerator(name: "timer_create", value: 222)
!574 = !DIEnumerator(name: "timer_settime", value: 223)
!575 = !DIEnumerator(name: "timer_gettime", value: 224)
!576 = !DIEnumerator(name: "timer_getoverrun", value: 225)
!577 = !DIEnumerator(name: "timer_delete", value: 226)
!578 = !DIEnumerator(name: "clock_settime", value: 227)
!579 = !DIEnumerator(name: "clock_gettime", value: 228)
!580 = !DIEnumerator(name: "clock_getres", value: 229)
!581 = !DIEnumerator(name: "clock_nanosleep", value: 230)
!582 = !DIEnumerator(name: "exit_group", value: 231)
!583 = !DIEnumerator(name: "epoll_wait", value: 232)
!584 = !DIEnumerator(name: "epoll_ctl", value: 233)
!585 = !DIEnumerator(name: "tgkill", value: 234)
!586 = !DIEnumerator(name: "utimes", value: 235)
!587 = !DIEnumerator(name: "vserver", value: 236)
!588 = !DIEnumerator(name: "mbind", value: 237)
!589 = !DIEnumerator(name: "set_mempolicy", value: 238)
!590 = !DIEnumerator(name: "get_mempolicy", value: 239)
!591 = !DIEnumerator(name: "mq_open", value: 240)
!592 = !DIEnumerator(name: "mq_unlink", value: 241)
!593 = !DIEnumerator(name: "mq_timedsend", value: 242)
!594 = !DIEnumerator(name: "mq_timedreceive", value: 243)
!595 = !DIEnumerator(name: "mq_notify", value: 244)
!596 = !DIEnumerator(name: "mq_getsetattr", value: 245)
!597 = !DIEnumerator(name: "kexec_load", value: 246)
!598 = !DIEnumerator(name: "waitid", value: 247)
!599 = !DIEnumerator(name: "add_key", value: 248)
!600 = !DIEnumerator(name: "request_key", value: 249)
!601 = !DIEnumerator(name: "keyctl", value: 250)
!602 = !DIEnumerator(name: "ioprio_set", value: 251)
!603 = !DIEnumerator(name: "ioprio_get", value: 252)
!604 = !DIEnumerator(name: "inotify_init", value: 253)
!605 = !DIEnumerator(name: "inotify_add_watch", value: 254)
!606 = !DIEnumerator(name: "inotify_rm_watch", value: 255)
!607 = !DIEnumerator(name: "migrate_pages", value: 256)
!608 = !DIEnumerator(name: "openat", value: 257)
!609 = !DIEnumerator(name: "mkdirat", value: 258)
!610 = !DIEnumerator(name: "mknodat", value: 259)
!611 = !DIEnumerator(name: "fchownat", value: 260)
!612 = !DIEnumerator(name: "futimesat", value: 261)
!613 = !DIEnumerator(name: "newfstatat", value: 262)
!614 = !DIEnumerator(name: "fstatat", value: 262)
!615 = !DIEnumerator(name: "unlinkat", value: 263)
!616 = !DIEnumerator(name: "renameat", value: 264)
!617 = !DIEnumerator(name: "linkat", value: 265)
!618 = !DIEnumerator(name: "symlinkat", value: 266)
!619 = !DIEnumerator(name: "readlinkat", value: 267)
!620 = !DIEnumerator(name: "fchmodat", value: 268)
!621 = !DIEnumerator(name: "faccessat", value: 269)
!622 = !DIEnumerator(name: "pselect6", value: 270)
!623 = !DIEnumerator(name: "ppoll", value: 271)
!624 = !DIEnumerator(name: "unshare", value: 272)
!625 = !DIEnumerator(name: "set_robust_list", value: 273)
!626 = !DIEnumerator(name: "get_robust_list", value: 274)
!627 = !DIEnumerator(name: "splice", value: 275)
!628 = !DIEnumerator(name: "tee", value: 276)
!629 = !DIEnumerator(name: "sync_file_range", value: 277)
!630 = !DIEnumerator(name: "vmsplice", value: 278)
!631 = !DIEnumerator(name: "move_pages", value: 279)
!632 = !DIEnumerator(name: "utimensat", value: 280)
!633 = !DIEnumerator(name: "epoll_pwait", value: 281)
!634 = !DIEnumerator(name: "signalfd", value: 282)
!635 = !DIEnumerator(name: "timerfd_create", value: 283)
!636 = !DIEnumerator(name: "eventfd", value: 284)
!637 = !DIEnumerator(name: "fallocate", value: 285)
!638 = !DIEnumerator(name: "timerfd_settime", value: 286)
!639 = !DIEnumerator(name: "timerfd_gettime", value: 287)
!640 = !DIEnumerator(name: "accept4", value: 288)
!641 = !DIEnumerator(name: "signalfd4", value: 289)
!642 = !DIEnumerator(name: "eventfd2", value: 290)
!643 = !DIEnumerator(name: "epoll_create1", value: 291)
!644 = !DIEnumerator(name: "dup3", value: 292)
!645 = !DIEnumerator(name: "pipe2", value: 293)
!646 = !DIEnumerator(name: "inotify_init1", value: 294)
!647 = !DIEnumerator(name: "preadv", value: 295)
!648 = !DIEnumerator(name: "pwritev", value: 296)
!649 = !DIEnumerator(name: "rt_tgsigqueueinfo", value: 297)
!650 = !DIEnumerator(name: "perf_event_open", value: 298)
!651 = !DIEnumerator(name: "recvmmsg", value: 299)
!652 = !DIEnumerator(name: "fanotify_init", value: 300)
!653 = !DIEnumerator(name: "fanotify_mark", value: 301)
!654 = !DIEnumerator(name: "prlimit64", value: 302)
!655 = !DIEnumerator(name: "name_to_handle_at", value: 303)
!656 = !DIEnumerator(name: "open_by_handle_at", value: 304)
!657 = !DIEnumerator(name: "clock_adjtime", value: 305)
!658 = !DIEnumerator(name: "syncfs", value: 306)
!659 = !DIEnumerator(name: "sendmmsg", value: 307)
!660 = !DIEnumerator(name: "setns", value: 308)
!661 = !DIEnumerator(name: "getcpu", value: 309)
!662 = !DIEnumerator(name: "process_vm_readv", value: 310)
!663 = !DIEnumerator(name: "process_vm_writev", value: 311)
!664 = !DIEnumerator(name: "kcmp", value: 312)
!665 = !DIEnumerator(name: "finit_module", value: 313)
!666 = !DIEnumerator(name: "sched_setattr", value: 314)
!667 = !DIEnumerator(name: "sched_getattr", value: 315)
!668 = !DIEnumerator(name: "renameat2", value: 316)
!669 = !DIEnumerator(name: "seccomp", value: 317)
!670 = !DIEnumerator(name: "getrandom", value: 318)
!671 = !DIEnumerator(name: "memfd_create", value: 319)
!672 = !DIEnumerator(name: "kexec_file_load", value: 320)
!673 = !DIEnumerator(name: "bpf", value: 321)
!674 = !DIEnumerator(name: "execveat", value: 322)
!675 = !DIEnumerator(name: "userfaultfd", value: 323)
!676 = !DIEnumerator(name: "membarrier", value: 324)
!677 = !DIEnumerator(name: "mlock2", value: 325)
!678 = !DIEnumerator(name: "copy_file_range", value: 326)
!679 = !DIEnumerator(name: "preadv2", value: 327)
!680 = !DIEnumerator(name: "pwritev2", value: 328)
!681 = !DIEnumerator(name: "pkey_mprotect", value: 329)
!682 = !DIEnumerator(name: "pkey_alloc", value: 330)
!683 = !DIEnumerator(name: "pkey_free", value: 331)
!684 = !DIEnumerator(name: "statx", value: 332)
!685 = !DIEnumerator(name: "io_pgetevents", value: 333)
!686 = !DIEnumerator(name: "rseq", value: 334)
!687 = !DIEnumerator(name: "pidfd_send_signal", value: 424)
!688 = !DIEnumerator(name: "io_uring_setup", value: 425)
!689 = !DIEnumerator(name: "io_uring_enter", value: 426)
!690 = !DIEnumerator(name: "io_uring_register", value: 427)
!691 = !DIEnumerator(name: "open_tree", value: 428)
!692 = !DIEnumerator(name: "move_mount", value: 429)
!693 = !DIEnumerator(name: "fsopen", value: 430)
!694 = !DIEnumerator(name: "fsconfig", value: 431)
!695 = !DIEnumerator(name: "fsmount", value: 432)
!696 = !DIEnumerator(name: "fspick", value: 433)
!697 = !DIEnumerator(name: "pidfd_open", value: 434)
!698 = !DIEnumerator(name: "clone3", value: 435)
!699 = !DIEnumerator(name: "openat2", value: 437)
!700 = !DIEnumerator(name: "pidfd_getfd", value: 438)
  %0 = alloca %"struct:96:29", align 8
  %old.sroa.2.0.sroa_cast = bitcast i8* %old.sroa.2 to i1*
  store i1 true, i1* %old.sroa.2.0.sroa_cast, align 8
  %result.sroa.0.0..sroa_cast = bitcast %"struct:96:29"* %0 to i64*
  store i64 or (i64 shl (i64 zext (i56 trunc (i64 lshr (i64 ptrtoint ([20 x i8]* @0 to i64), i64 8) to i56) to i64), i64 8), i64 zext (i8 ptrtoint ([20 x i8]* @0 to i8) to i64)), i64* %result.sroa.0.0..sroa_cast, align 8
  ; This is where the `len` parameter is smashed
  %result.sroa.6.0..sroa_idx21 = getelementptr inbounds %"struct:96:29", %"struct:96:29"* %0, i64 0, i32 0, i32 1
  %result.sroa.6.0..sroa_cast = bitcast i64* %result.sroa.6.0..sroa_idx21 to i1*
  store i1 true, i1* %result.sroa.6.0..sroa_cast, align 8

  ; ..snip..

  %7 = bitcast %"struct:96:29"* %0 to %"[]u8"*
  call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(32) %4, i8 0, i64 32, i1 false) #7
  ; This is where things go south, the ptr part of the slice is fine while the length becomes 1
  %8 = call fastcc i16 @std.fmt.formatType(%"[]u8"* %7, %std.fmt.FormatOptions* %options.i.i.i,   %"std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write)"* %stderr.i) #7

Having someone from the LLVM team confirm this hypotesis and have a look would be helpful.

LemonBoy avatar Dec 07 '20 11:12 LemonBoy

0.9.0 milestone, haha, ouch.

LemonBoy are you saying that this is an LLVM bug, not a Zig compiler bug?

ghost avatar Dec 08 '20 01:12 ghost

0.9.0 milestone, haha, ouch.

LemonBoy are you saying that this is an LLVM bug, not a Zig compiler bug?

It really sounds like one, you can (hopefully) work around it by making is_weak a u8.

LemonBoy avatar Dec 08 '20 08:12 LemonBoy

You're right, my project is "fixed" by changing that field from a bool to a u8. It doesn't give me a lot of confidence though.

Do you think the problem is specific to boolean struct fields getting returned through (possibly multiple layers of) result locations?

ghost avatar Dec 08 '20 17:12 ghost

Do you think the problem is specific to boolean struct fields getting returned through (possibly multiple layers of) result locations?

Hard to tell, the problem disappears if you touch any part of it. You've managed to line-up all the pieces in perfect order to let the over-eager optimization pass kick in.

LemonBoy avatar Dec 08 '20 18:12 LemonBoy

Hard to tell, the problem disappears if you touch any part of it. You've managed to line-up all the pieces in perfect order to let the over-eager optimization pass kick in.

hidethepain(1)

ghost avatar Dec 08 '20 19:12 ghost

Good news (?), I've managed to pin-point the bad code generation to an unfortunate interaction between the inliner pass and the SROA one. The bad news is that I don't have enough time to dig into the pass implementation, it's better to punt this bug to the LLVM developers.

Here's a nice not-so-reduced test case, I've already run it trough opt -inline.

You can observe the bug by running:

opt-11 -sroa <.ll file> | lli-11 # The output is corrupted
lli-11 <.ll file>                # The output is fine

LemonBoy avatar Dec 23 '20 12:12 LemonBoy

I managed to shrink the test case down to ~200LoC (from ~7k), this is now ready to be reported upstream (@andrewrk can you open a ticket for this?).

LLVM IR source:

; ModuleID = '/tmp/foo.inl.ll'
source_filename = "foo"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%CallArg = type { %Expression }
%Expression = type { %EnumLiteral, i1 }
%EnumLiteral = type { %"[]u8" }
%"[]u8" = type { i8*, i64 }
%ExpressionResult = type { %TempRef, i2 }
%TempRef = type { i64, i1 }
%"struct:78:50" = type { %"[]u8" }
%"struct:132:52" = type { %"[]u8" }

@0 = internal unnamed_addr constant [20 x i8] c"what happened to me\00", align 1
@1 = internal unnamed_addr constant %CallArg { %Expression { %EnumLiteral { %"[]u8" { i8* getelementptr inbounds ([20 x i8], [20 x i8]* @0, i64 0, i64 0), i64 19 } }, i1 true } }, align 8

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #0

; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) #1

; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare { i64, i1 } @llvm.ssub.with.overflow.i64(i64, i64) #1

define internal fastcc void @main() unnamed_addr {
Entry:
  %v.i = alloca %EnumLiteral, align 8
  %result.i = alloca %ExpressionResult, align 8
  %w.i = alloca %"[]u8", align 8
  %0 = alloca %"struct:78:50", align 8
  %arg = alloca %CallArg, align 8
  %result = alloca %ExpressionResult, align 8
  %w = alloca %"[]u8", align 8
  %1 = alloca %"struct:132:52", align 8
  %derp = alloca %ExpressionResult, align 8
  %2 = bitcast %CallArg* %arg to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* bitcast (%CallArg* @1 to i8*), i64 24, i1 false)
  %3 = getelementptr inbounds %CallArg, %CallArg* %arg, i32 0, i32 0
  %4 = getelementptr inbounds %Expression, %Expression* %3, i32 0, i32 1
  %5 = load i1, i1* %4, align 1
  switch i1 %5, label %SwitchElse3.i [
    i1 true, label %SwitchProng1.i
  ]

SwitchProng1.i:                                   ; preds = %Entry
  %6 = getelementptr inbounds %Expression, %Expression* %3, i32 0, i32 0
  %7 = bitcast %EnumLiteral* %6 to i8*
  %8 = bitcast %EnumLiteral* %v.i to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %8, i8* %7, i64 16, i1 false)
  %9 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result.i, i32 0, i32 1
  store i2 -2, i2* %9, align 1
  %10 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result.i, i32 0, i32 0
  %11 = bitcast %TempRef* %10 to %"[]u8"*
  %12 = getelementptr inbounds %EnumLiteral, %EnumLiteral* %v.i, i32 0, i32 0
  %13 = bitcast %"[]u8"* %12 to i8*
  %14 = bitcast %"[]u8"* %11 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %14, i8* %13, i64 16, i1 false)
  br label %SwitchProng2.i

SwitchProng2.i:                                   ; preds = %SwitchProng1.i
  %15 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result.i, i32 0, i32 0
  %16 = bitcast %TempRef* %15 to %"[]u8"*
  %17 = bitcast %"[]u8"* %16 to i8*
  %18 = bitcast %"[]u8"* %w.i to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %18, i8* %17, i64 16, i1 false)
  %19 = getelementptr inbounds %"struct:78:50", %"struct:78:50"* %0, i32 0, i32 0
  %20 = bitcast %"[]u8"* %w.i to i8*
  %21 = bitcast %"[]u8"* %19 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %21, i8* %20, i64 16, i1 false)
  %22 = getelementptr inbounds %"struct:78:50", %"struct:78:50"* %0, i32 0, i32 0
  call fastcc void @std.os.write(i32 1, %"[]u8"* %22)
  br label %ErrRetContinue.i.i.i

ErrRetContinue.i.i.i:                             ; preds = %SwitchProng2.i
  br label %f.exit.i.i

f.exit.i.i:                                       ; preds = %ErrRetContinue.i.i.i
  br label %UnwrapErrError.i.i

UnwrapErrError.i.i:                               ; preds = %f.exit.i.i
  br label %print.18.exit.i

print.18.exit.i:                                  ; preds = %UnwrapErrError.i.i
  br label %SwitchEnd.i

SwitchEnd.i:                                      ; preds = %print.18.exit.i
  %23 = bitcast %ExpressionResult* %result.i to i8*
  %24 = bitcast %ExpressionResult* %result to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %24, i8* %23, i64 24, i1 false)
  br label %genExpression.exit

SwitchElse3.i:                                    ; preds = %Entry
  ret void

genExpression.exit:                               ; preds = %SwitchEnd.i
  %25 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result, i32 0, i32 1
  %26 = load i2, i2* %25, align 1
  switch i2 %26, label %SwitchElse [
    i2 -2, label %SwitchProng
  ]

SwitchElse:                                       ; preds = %genExpression.exit
  ret void

SwitchProng:                                      ; preds = %genExpression.exit
  %27 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %result, i32 0, i32 0
  %28 = bitcast %TempRef* %27 to %"[]u8"*
  %29 = bitcast %"[]u8"* %28 to i8*
  %30 = bitcast %"[]u8"* %w to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %30, i8* %29, i64 16, i1 false)
  %31 = getelementptr inbounds %"struct:132:52", %"struct:132:52"* %1, i32 0, i32 0
  %32 = bitcast %"[]u8"* %w to i8*
  %33 = bitcast %"[]u8"* %31 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %33, i8* %32, i64 16, i1 false)
  %34 = getelementptr inbounds %"struct:132:52", %"struct:132:52"* %1, i32 0, i32 0
  call fastcc void @std.os.write(i32 1, %"[]u8"* %34)
  ret void

SwitchProng1.i3:                                  ; No predecessors!
  %35 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %derp, i32 0, i32 0
  %36 = getelementptr inbounds %TempRef, %TempRef* %35, i32 0, i32 1
  store i1 false, i1* %36, align 1
  ret void

SwitchProng2.i4:                                  ; No predecessors!
  %37 = bitcast %ExpressionResult* %result to i8*
  %38 = bitcast %ExpressionResult* %derp to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %38, i8* %37, i64 24, i1 false)
  ret void
}

define internal fastcc void @std.os.write(i32 %0, %"[]u8"* %1) unnamed_addr {
Entry:
  %result.i8 = alloca i64, align 8
  %y.i = alloca i64, align 8
  %number.i.i = alloca i64, align 8
  %arg2.i.i = alloca i64, align 8
  %arg3.i.i = alloca i64, align 8
  %buf.i = alloca i8*, align 8
  %count.i = alloca i64, align 8
  %adjusted_len = alloca i64, align 8
  %2 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 1
  %3 = load i64, i64* %2, align 8
  store i64 %3, i64* %y.i, align 8
  br label %Else.i10

Else.i10:                                         ; preds = %Entry
  %4 = load i64, i64* %y.i, align 8
  store i64 %4, i64* %result.i8, align 8
  %5 = load i64, i64* %result.i8, align 8
  br label %std.math.min.exit

std.math.min.exit:                                ; preds = %Else.i10
  store i64 %5, i64* %adjusted_len, align 8
  br label %WhileCond

WhileCond:                                        ; preds = %std.math.min.exit
  br label %WhileBody

WhileBody:                                        ; preds = %WhileCond
  %6 = getelementptr inbounds %"[]u8", %"[]u8"* %1, i32 0, i32 0
  %7 = load i8*, i8** %6, align 8
  %8 = load i64, i64* %adjusted_len, align 8
  store i8* %7, i8** %buf.i, align 8
  store i64 %8, i64* %count.i, align 8
  %9 = load i8*, i8** %buf.i, align 8
  %10 = ptrtoint i8* %9 to i64
  %11 = load i64, i64* %count.i, align 8
  store i64 1, i64* %number.i.i, align 8
  store i64 %10, i64* %arg2.i.i, align 8
  store i64 %11, i64* %arg3.i.i, align 8
  %12 = load i64, i64* %number.i.i, align 8
  %13 = load i64, i64* %arg2.i.i, align 8
  %14 = load i64, i64* %arg3.i.i, align 8
  %15 = call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 %12, i64 undef, i64 %13, i64 %14)
  ret void
}

attributes #0 = { argmemonly nofree nosync nounwind willreturn }
attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }

The different behaviour can be observed by running

opt-11 -sroa <.ll file> | lli-11 # The output is corrupted
lli-11 <.ll file>                # The output is fine

LemonBoy avatar Jan 11 '21 21:01 LemonBoy

(@andrewrk can you open a ticket for this?).

Sure thing. Upstream bug report

andrewrk avatar Jan 11 '21 23:01 andrewrk

I managed to shrink the test case down to ~200LoC (from ~7k), this is now ready to be reported upstream (@andrewrk can you open a ticket for this?).

LLVM IR source:

<...>

This is either over-reduced, or the original IR is already broken, because alive2 says that the transformation is valid:

$ /repositories/alive2/build-Clang-release/alive-tv input.ll output.ll 

----------------------------------------
@1 = constant 24 bytes, align 8
@0 = constant 20 bytes, align 1

define void @main() {
#init:
  %__constexpr_1 = gep inbounds * @0, 20 x i64 0, 1 x i64 0
  %__copy_0 = {*, i64} { %__constexpr_1, 19 }
  %__copy_1 = {{*, i64}} { %__copy_0 }
  %__copy_2 = {{{*, i64}}, i1, i56} { %__copy_1, 1, [padding] }
  %__copy_3 = {{{{*, i64}}, i1, i56}} { %__copy_2 }
  store [20 x i8] { 119, 104, 97, 116, 32, 104, 97, 112, 112, 101, 110, 101, 100, 32, 116, 111, 32, 109, 101, 0 }, * @0, align 1
  store {{{{*, i64}}, i1, i56}} %__copy_3, * @1, align 8
  br label %Entry

%Entry:
  %v.i = alloca i64 16, align 8
  %result.i = alloca i64 24, align 8
  %w.i = alloca i64 16, align 8
  %0 = alloca i64 16, align 8
  %arg = alloca i64 24, align 8
  %result = alloca i64 24, align 8
  %w = alloca i64 16, align 8
  %1 = alloca i64 16, align 8
  %derp = alloca i64 24, align 8
  %2 = bitcast * %arg to *
  %__constexpr_0 = bitcast * @1 to *
  memcpy * %2 align 1, * %__constexpr_0 align 1, i64 24
  %3 = gep inbounds * %arg, 24 x i32 0, 1 x i64 0
  %4 = gep inbounds * %3, 24 x i32 0, 1 x i64 16
  %5 = load i1, * %4, align 1
  switch i1 %5, label %SwitchElse3.i [
    i1 1, label %SwitchProng1.i
  ]

%SwitchProng1.i:
  %10 = gep inbounds * %3, 24 x i32 0, 1 x i64 0
  %11 = bitcast * %10 to *
  %12 = bitcast * %v.i to *
  memcpy * %12 align 1, * %11 align 1, i64 16
  %13 = gep inbounds * %result.i, 24 x i32 0, 1 x i64 16
  store i2 2, * %13, align 1
  %14 = gep inbounds * %result.i, 24 x i32 0, 1 x i64 0
  %15 = bitcast * %14 to *
  %16 = gep inbounds * %v.i, 16 x i32 0, 1 x i64 0
  %17 = bitcast * %16 to *
  %18 = bitcast * %15 to *
  memcpy * %18 align 1, * %17 align 1, i64 16
  br label %SwitchProng2.i

%SwitchProng2.i:
  %19 = gep inbounds * %result.i, 24 x i32 0, 1 x i64 0
  %20 = bitcast * %19 to *
  %21 = bitcast * %20 to *
  %22 = bitcast * %w.i to *
  memcpy * %22 align 1, * %21 align 1, i64 16
  %23 = gep inbounds * %0, 16 x i32 0, 1 x i64 0
  %24 = bitcast * %w.i to *
  %25 = bitcast * %23 to *
  memcpy * %25 align 1, * %24 align 1, i64 16
  %26 = gep inbounds * %0, 16 x i32 0, 1 x i64 0
  call void @std.os.write(i32 1, * %26)
  br label %ErrRetContinue.i.i.i

%ErrRetContinue.i.i.i:
  br label %f.exit.i.i

%f.exit.i.i:
  br label %UnwrapErrError.i.i

%UnwrapErrError.i.i:
  br label %print.18.exit.i

%print.18.exit.i:
  br label %SwitchEnd.i

%SwitchEnd.i:
  %27 = bitcast * %result.i to *
  %28 = bitcast * %result to *
  memcpy * %28 align 1, * %27 align 1, i64 24
  br label %genExpression.exit

%genExpression.exit:
  %29 = gep inbounds * %result, 24 x i32 0, 1 x i64 16
  %30 = load i2, * %29, align 1
  switch i2 %30, label %SwitchElse [
    i2 2, label %SwitchProng
  ]

%SwitchElse:
  ret void

%SwitchProng:
  %31 = gep inbounds * %result, 24 x i32 0, 1 x i64 0
  %32 = bitcast * %31 to *
  %33 = bitcast * %32 to *
  %34 = bitcast * %w to *
  memcpy * %34 align 1, * %33 align 1, i64 16
  %35 = gep inbounds * %1, 16 x i32 0, 1 x i64 0
  %36 = bitcast * %w to *
  %37 = bitcast * %35 to *
  memcpy * %37 align 1, * %36 align 1, i64 16
  %38 = gep inbounds * %1, 16 x i32 0, 1 x i64 0
  call void @std.os.write(i32 1, * %38)
  ret void

%SwitchElse3.i:
  ret void
}
=>
@1 = constant 24 bytes, align 8
@0 = constant 20 bytes, align 1

define void @main() {
#init:
  %__constexpr_8 = gep inbounds * @0, 20 x i64 0, 1 x i64 0
  %__copy_0 = {*, i64} { %__constexpr_8, 19 }
  %__copy_1 = {{*, i64}} { %__copy_0 }
  %__copy_2 = {{{*, i64}}, i1, i56} { %__copy_1, 1, [padding] }
  %__copy_3 = {{{{*, i64}}, i1, i56}} { %__copy_2 }
  store [20 x i8] { 119, 104, 97, 116, 32, 104, 97, 112, 112, 101, 110, 101, 100, 32, 116, 111, 32, 109, 101, 0 }, * @0, align 1
  store {{{{*, i64}}, i1, i56}} %__copy_3, * @1, align 8
  br label %Entry

%Entry:
  %v.i.sroa.2 = alloca i64 1, align 8
  %v.i.sroa.3 = alloca i64 7, align 1
  %result.i.sroa.4 = alloca i64 7, align 1
  %result.i.sroa.7 = alloca i64 7, align 1
  %w.i.sroa.2 = alloca i64 1, align 8
  %w.i.sroa.3 = alloca i64 7, align 1
  %0 = alloca i64 16, align 8
  %arg.sroa.0.sroa.3 = alloca i64 7, align 1
  %arg.sroa.3 = alloca i64 7, align 1
  %result.sroa.4 = alloca i64 7, align 1
  %result.sroa.6 = alloca i64 7, align 1
  %w.sroa.2 = alloca i64 1, align 8
  %w.sroa.3 = alloca i64 7, align 1
  %1 = alloca i64 16, align 8
  %derp.sroa.2.sroa.0 = alloca i64 7, align 1
  %derp.sroa.2.sroa.1 = alloca i64 1, align 1
  %derp.sroa.2.sroa.2 = alloca i64 7, align 1
  %__constexpr_0 = bitcast * @1 to *
  %arg.sroa.0.sroa.0.0.copyload = load i64, * %__constexpr_0, align 1
  %__constexpr_2 = gep inbounds * @1, 24 x i64 0, 1 x i64 0, 1 x i64 0, 1 x i64 0, 1 x i64 8
  %__constexpr_1 = bitcast * %__constexpr_2 to *
  %arg.sroa.0.sroa.2.0.copyload = load i8, * %__constexpr_1, align 1
  %arg.sroa.0.sroa.3.0..sroa_idx = gep inbounds * %arg.sroa.0.sroa.3, 7 x i64 0, 1 x i64 0
  %__constexpr_4 = bitcast * @1 to *
  %__constexpr_3 = gep inbounds * %__constexpr_4, 1 x i64 9
  memcpy * %arg.sroa.0.sroa.3.0..sroa_idx align 1, * %__constexpr_3 align 1, i64 7
  %__constexpr_5 = gep inbounds * @1, 24 x i64 0, 1 x i64 0, 1 x i64 16
  %arg.sroa.2.0.copyload = load i1, * %__constexpr_5, align 1
  %arg.sroa.3.0..sroa_idx = gep inbounds * %arg.sroa.3, 7 x i64 0, 1 x i64 0
  %__constexpr_7 = bitcast * @1 to *
  %__constexpr_6 = gep inbounds * %__constexpr_7, 1 x i64 17
  memcpy * %arg.sroa.3.0..sroa_idx align 1, * %__constexpr_6 align 1, i64 7
  switch i1 %arg.sroa.2.0.copyload, label %SwitchElse3.i [
    i1 1, label %SwitchProng1.i
  ]

%SwitchProng1.i:
  store i8 %arg.sroa.0.sroa.2.0.copyload, * %v.i.sroa.2, align 8
  %arg.sroa.0.sroa.3.9.v.i.sroa.3.0..sroa_idx.sroa_idx = gep inbounds * %v.i.sroa.3, 7 x i64 0, 1 x i64 0
  %arg.sroa.0.sroa.3.9..sroa_idx = gep inbounds * %arg.sroa.0.sroa.3, 7 x i64 0, 1 x i64 0
  memcpy * %arg.sroa.0.sroa.3.9.v.i.sroa.3.0..sroa_idx.sroa_idx align 1, * %arg.sroa.0.sroa.3.9..sroa_idx align 1, i64 7
  %v.i.sroa.2.0..sroa_cast = bitcast * %v.i.sroa.2 to *
  %v.i.sroa.2.0.v.i.sroa.2.8.result.i.sroa.3.0.copyload = load i1, * %v.i.sroa.2.0..sroa_cast, align 8
  %v.i.sroa.3.9.result.i.sroa.4.0..sroa_idx.sroa_idx = gep inbounds * %result.i.sroa.4, 7 x i64 0, 1 x i64 0
  %v.i.sroa.3.9..sroa_idx = gep inbounds * %v.i.sroa.3, 7 x i64 0, 1 x i64 0
  memcpy * %v.i.sroa.3.9.result.i.sroa.4.0..sroa_idx.sroa_idx align 1, * %v.i.sroa.3.9..sroa_idx align 1, i64 7
  br label %SwitchProng2.i

%SwitchProng2.i:
  %w.i.sroa.2.0..sroa_cast22 = bitcast * %w.i.sroa.2 to *
  store i1 %v.i.sroa.2.0.v.i.sroa.2.8.result.i.sroa.3.0.copyload, * %w.i.sroa.2.0..sroa_cast22, align 8
  %w.i.sroa.3.9.result.i.sroa.4.0..sroa_idx21.sroa_idx = gep inbounds * %result.i.sroa.4, 7 x i64 0, 1 x i64 0
  %w.i.sroa.3.9..sroa_idx = gep inbounds * %w.i.sroa.3, 7 x i64 0, 1 x i64 0
  memcpy * %w.i.sroa.3.9..sroa_idx align 1, * %w.i.sroa.3.9.result.i.sroa.4.0..sroa_idx21.sroa_idx align 1, i64 7
  %w.i.sroa.0.0..sroa_cast = bitcast * %0 to *
  store i64 %arg.sroa.0.sroa.0.0.copyload, * %w.i.sroa.0.0..sroa_cast, align 1
  %w.i.sroa.2.0..sroa_idx = gep inbounds * %0, 16 x i64 0, 1 x i64 0, 1 x i64 8
  %w.i.sroa.2.0..sroa_cast = bitcast * %w.i.sroa.2.0..sroa_idx to *
  %w.i.sroa.2.0.w.i.sroa.2.0.copyload = load i8, * %w.i.sroa.2, align 8
  store i8 %w.i.sroa.2.0.w.i.sroa.2.0.copyload, * %w.i.sroa.2.0..sroa_cast, align 1
  %w.i.sroa.3.0..sroa_raw_cast = bitcast * %0 to *
  %w.i.sroa.3.0..sroa_raw_idx = gep inbounds * %w.i.sroa.3.0..sroa_raw_cast, 1 x i64 9
  %w.i.sroa.3.0..sroa_idx = gep inbounds * %w.i.sroa.3, 7 x i64 0, 1 x i64 0
  memcpy * %w.i.sroa.3.0..sroa_raw_idx align 1, * %w.i.sroa.3.0..sroa_idx align 1, i64 7
  %2 = gep inbounds * %0, 16 x i32 0, 1 x i64 0
  call void @std.os.write(i32 1, * %2)
  br label %ErrRetContinue.i.i.i

%ErrRetContinue.i.i.i:
  br label %f.exit.i.i

%f.exit.i.i:
  br label %UnwrapErrError.i.i

%UnwrapErrError.i.i:
  br label %print.18.exit.i

%print.18.exit.i:
  br label %SwitchEnd.i

%SwitchEnd.i:
  %result.i.sroa.4.9.result.sroa.4.0..sroa_idx.sroa_idx = gep inbounds * %result.sroa.4, 7 x i64 0, 1 x i64 0
  %result.i.sroa.4.9..sroa_idx = gep inbounds * %result.i.sroa.4, 7 x i64 0, 1 x i64 0
  memcpy * %result.i.sroa.4.9.result.sroa.4.0..sroa_idx.sroa_idx align 1, * %result.i.sroa.4.9..sroa_idx align 1, i64 7
  %result.i.sroa.7.17.result.sroa.6.0..sroa_idx.sroa_idx = gep inbounds * %result.sroa.6, 7 x i64 0, 1 x i64 0
  %result.i.sroa.7.17..sroa_idx = gep inbounds * %result.i.sroa.7, 7 x i64 0, 1 x i64 0
  memcpy * %result.i.sroa.7.17.result.sroa.6.0..sroa_idx.sroa_idx align 1, * %result.i.sroa.7.17..sroa_idx align 1, i64 7
  br label %genExpression.exit

%genExpression.exit:
  switch i2 2, label %SwitchElse [
    i2 2, label %SwitchProng
  ]

%SwitchElse:
  ret void

%SwitchProng:
  %w.sroa.2.0..sroa_cast10 = bitcast * %w.sroa.2 to *
  store i1 %v.i.sroa.2.0.v.i.sroa.2.8.result.i.sroa.3.0.copyload, * %w.sroa.2.0..sroa_cast10, align 8
  %w.sroa.3.9.result.sroa.4.0..sroa_idx8.sroa_idx = gep inbounds * %result.sroa.4, 7 x i64 0, 1 x i64 0
  %w.sroa.3.9..sroa_idx = gep inbounds * %w.sroa.3, 7 x i64 0, 1 x i64 0
  memcpy * %w.sroa.3.9..sroa_idx align 1, * %w.sroa.3.9.result.sroa.4.0..sroa_idx8.sroa_idx align 1, i64 7
  %w.sroa.0.0..sroa_cast = bitcast * %1 to *
  store i64 %arg.sroa.0.sroa.0.0.copyload, * %w.sroa.0.0..sroa_cast, align 1
  %w.sroa.2.0..sroa_idx = gep inbounds * %1, 16 x i64 0, 1 x i64 0, 1 x i64 8
  %w.sroa.2.0..sroa_cast = bitcast * %w.sroa.2.0..sroa_idx to *
  %w.sroa.2.0.w.sroa.2.0.copyload = load i8, * %w.sroa.2, align 8
  store i8 %w.sroa.2.0.w.sroa.2.0.copyload, * %w.sroa.2.0..sroa_cast, align 1
  %w.sroa.3.0..sroa_raw_cast = bitcast * %1 to *
  %w.sroa.3.0..sroa_raw_idx = gep inbounds * %w.sroa.3.0..sroa_raw_cast, 1 x i64 9
  %w.sroa.3.0..sroa_idx = gep inbounds * %w.sroa.3, 7 x i64 0, 1 x i64 0
  memcpy * %w.sroa.3.0..sroa_raw_idx align 1, * %w.sroa.3.0..sroa_idx align 1, i64 7
  %3 = gep inbounds * %1, 16 x i32 0, 1 x i64 0
  call void @std.os.write(i32 1, * %3)
  ret void

%SwitchElse3.i:
  ret void
}
Transformation seems to be correct!

ERROR: Unsupported instruction:   %15 = call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 %12, i64 undef, i64 %13, i64 %14)
ERROR: Could not translate 'std.os.write' to Alive IR
Summary:
  1 correct transformations
  0 incorrect transformations
  1 Alive2 errors

Good news (?), I've managed to pin-point the bad code generation to an unfortunate interaction between the inliner pass and the SROA one. The bad news is that I don't have enough time to dig into the pass implementation, it's better to punt this bug to the LLVM developers.

Here's a nice not-so-reduced test case, I've already run it trough opt -inline.

You can observe the bug by running:

opt-11 -sroa <.ll file> | lli-11 # The output is corrupted
lli-11 <.ll file>                # The output is fine

It is hard to say whether the original input also exibits the same problems, it's pretty big :) With increased timeout limits, alive2 still doesn't pinpoint any miscompiles in it, which usually means that there aren't any, because usually it comes up with them real fast. full-log.txt

LebedevRI avatar Jan 11 '21 23:01 LebedevRI

Just for completeness, if i disable poison/undef input in alive2, it starts complaining about @std.os.unexpectedErrno:

----------------------------------------
@stderr_mutex = global 1 bytes, align 1
@63 = constant 16 bytes, align 8
@99 = constant 40 bytes, align 8
@101 = constant 16 bytes, align 8
@102 = constant 16 bytes, align 8
@103 = constant 16 bytes, align 8
@104 = constant 16 bytes, align 8
@105 = constant 16 bytes, align 8
@106 = constant 16 bytes, align 8
@86 = constant 40 bytes, align 8
@87 = constant 16 bytes, align 8
@19 = constant 16 bytes, align 8
@100 = constant 22 bytes, align 1
@84 = constant 49 bytes, align 1
@18 = constant 18 bytes, align 1

define i16 @std.os.unexpectedErrno(i64 %0) {
#init:
  %__copy_0 = {{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} { { undef, 0, [padding] }, { undef, 0, [padding] }, 2, { 32, undef } }
  %__copy_3 = {{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} { { undef, 0, [padding] }, { undef, 0, [padding] }, 2, { 32, undef } }
  store [22 x i8] { 117, 110, 101, 120, 112, 101, 99, 116, 101, 100, 32, 101, 114, 114, 110, 111, 58, 32, 123, 125, 10, 0 }, * @100, align 1
  store {i64, i1, i56} { undef, 0, [padding] }, * @102, align 8
  store {i64, i1, i56} { undef, 0, [padding] }, * @103, align 8
  store {i64, i1, i56} { undef, 0, [padding] }, * @104, align 8
  store {i64, i1, i56} { undef, 0, [padding] }, * @105, align 8
  store [18 x i8] { 100, 101, 97, 100, 108, 111, 99, 107, 32, 100, 101, 116, 101, 99, 116, 101, 100, 0 }, * @18, align 1
  store {{*}, i1, i56} { undef, 0, [padding] }, * @63, align 8
  store [49 x i8] { 85, 110, 97, 98, 108, 101, 32, 116, 111, 32, 100, 117, 109, 112, 32, 115, 116, 97, 99, 107, 32, 116, 114, 97, 99, 101, 58, 32, 100, 101, 98, 117, 103, 32, 105, 110, 102, 111, 32, 115, 116, 114, 105, 112, 112, 101, 100, 10, 0 }, * @84, align 1
  store {{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} %__copy_3, * @86, align 8
  store {{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} %__copy_0, * @99, align 8
  br label %Entry

%Entry:
  %result.i.i1.i1 = alloca i64 2, align 2
  %options.i.i.i2 = alloca i64 40, align 8
  %1 = alloca i64 2, align 2
  %result.i.i3 = alloca i64 2, align 2
  %2 = alloca i64 4, align 4
  %result.i.i.i4 = alloca i64 4, align 4
  %3 = alloca i64 4, align 4
  %stderr.i5 = alloca i64 4, align 4
  %4 = alloca i64 2, align 2
  %result.i.i.i.i.i.i = alloca i64 2, align 2
  %int_value.i.i.i.i.i.i = alloca i64 8, align 8
  %5 = alloca i64 8, align 8
  %6 = alloca i64 40, align 8
  %7 = alloca i64 4, align 4
  %value.i.i.i.i.i.i = alloca i64 8, align 8
  %result.i.i.i.i.i = alloca i64 2, align 2
  %8 = alloca i64 8, align 8
  %9 = alloca i64 40, align 8
  %10 = alloca i64 4, align 4
  %value.i.i.i.i.i = alloca i64 8, align 8
  %result.i.i.i.i = alloca i64 2, align 2
  %11 = alloca i64 8, align 8
  %12 = alloca i64 40, align 8
  %13 = alloca i64 4, align 4
  %value.i.i.i.i = alloca i64 8, align 8
  %max_depth.i.i.i.i = alloca i64 8, align 8
  %result.i.i1.i = alloca i64 2, align 2
  %options.i.i.i = alloca i64 40, align 8
  %14 = alloca i64 2, align 2
  %15 = alloca i64 8, align 8
  %16 = alloca i64 40, align 8
  %17 = alloca i64 4, align 4
  %18 = alloca i64 2, align 2
  %19 = alloca i64 2, align 2
  %result.i.i = alloca i64 2, align 2
  %20 = alloca i64 4, align 4
  %21 = alloca i64 8, align 8
  %self.i.i.i = alloca i64 8, align 8
  %22 = alloca i64 16, align 8
  %self.i.i = alloca i64 8, align 8
  %result.i.i.i = alloca i64 4, align 4
  %held.i = alloca i64 8, align 8
  %23 = alloca i64 4, align 4
  %stderr.i = alloca i64 4, align 4
  %24 = alloca i64 8, align 8
  %25 = alloca i64 2, align 2
  %result = alloca i64 2, align 2
  %26 = alloca i64 8, align 8
  %err = alloca i64 8, align 8
  store i64 %0, * %err, align 8
  %27 = load i64, * %err, align 8
  %28 = gep inbounds * %26, 8 x i32 0, 1 x i64 0
  store i64 %27, * %28, align 8
  store * @stderr_mutex, * %self.i.i, align 8
  %36 = load *, * %self.i.i, align 8
  store * %36, * %self.i.i.i, align 8
  %38 = load *, * %self.i.i.i, align 8
  %39 = gep inbounds * %38, 1 x i32 0, 1 x i64 0
  %40 = load i1, * %39, align 1
  br i1 %40, label %Then.i.i.i, label %Else.i.i.i

%Else.i.i.i:
  %41 = load *, * %self.i.i.i, align 8
  %42 = gep inbounds * %41, 1 x i32 0, 1 x i64 0
  store i1 1, * %42, align 1
  %43 = gep inbounds * %22, 16 x i32 0, 1 x i64 8
  store i1 1, * %43, align 1
  %44 = gep inbounds * %22, 16 x i32 0, 1 x i64 0
  %45 = gep inbounds * %44, 8 x i32 0, 1 x i64 0
  %46 = load *, * %self.i.i.i, align 8
  store * %46, * %45, align 8
  %47 = gep inbounds * %22, 16 x i32 0, 1 x i64 8
  store i1 1, * %47, align 1
  %48 = gep inbounds * %22, 16 x i32 0, 1 x i64 0
  %49 = bitcast * %44 to *
  %50 = bitcast * %48 to *
  memcpy * %50 align 8, * %49 align 8, i64 8
  br label %std.mutex.Dummy.tryAcquire.exit.i.i

%Then.i.i.i:
  %52 = bitcast * %22 to *
  %__constexpr_0 = bitcast * @63 to *
  memcpy * %52 align 8, * %__constexpr_0 align 8, i64 16
  br label %std.mutex.Dummy.tryAcquire.exit.i.i

%std.mutex.Dummy.tryAcquire.exit.i.i:
  %54 = gep inbounds * %22, 16 x i32 0, 1 x i64 8
  %55 = load i1, * %54, align 1
  br i1 %55, label %std.mutex.Dummy.acquire.exit.i, label %OptionalNull.i.i

%std.mutex.Dummy.acquire.exit.i:
  %56 = gep inbounds * %22, 16 x i32 0, 1 x i64 0
  %57 = bitcast * %56 to *
  %58 = bitcast * %held.i to *
  memcpy * %58 align 8, * %57 align 8, i64 8
  %61 = gep inbounds * %23, 4 x i32 0, 1 x i64 0
  store i32 2, * %result.i.i.i, align 4
  %63 = load i32, * %result.i.i.i, align 4
  store i32 %63, * %61, align 4
  %65 = gep inbounds * %stderr.i, 4 x i32 0, 1 x i64 0
  %66 = bitcast * %23 to *
  %67 = bitcast * %65 to *
  memcpy * %67 align 4, * %66 align 4, i64 4
  %68 = bitcast * %26 to *
  %69 = bitcast * %24 to *
  memcpy * %69 align 8, * %68 align 8, i64 8
  %73 = bitcast * %stderr.i to *
  %74 = bitcast * %20 to *
  memcpy * %74 align 4, * %73 align 4, i64 4
  %75 = bitcast * %26 to *
  %76 = bitcast * %21 to *
  memcpy * %76 align 8, * %75 align 8, i64 8
  %85 = bitcast * %options.i.i.i to *
  %__constexpr_1 = bitcast * @99 to *
  memcpy * %85 align 8, * %__constexpr_1 align 8, i64 40
  %86 = call i16 @std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll(nonnull align(4) * %stderr.i, nonnull align(8) * @101)
  store i16 %86, * %14, align 2
  %87 = icmp ne i16 %86, 0
  br i1 %87, label %ErrRetReturn.i.i.i, label %ErrRetContinue.i.i.i

%ErrRetReturn.i.i.i:
  %88 = load i16, * %14, align 2
  store i16 %88, * %result.i.i1.i, align 2
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i

%ErrRetContinue.i.i.i:
  %97 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 0
  %98 = bitcast * %97 to *
  %__constexpr_2 = bitcast * @102 to *
  memcpy * %98 align 8, * %__constexpr_2 align 8, i64 16
  %99 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 16
  %100 = bitcast * %99 to *
  %__constexpr_3 = bitcast * @103 to *
  memcpy * %100 align 8, * %__constexpr_3 align 8, i64 16
  %101 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 32
  store i2 2, * %101, align 1
  %102 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 33
  store i8 32, * %102, align 1
  %103 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 16
  %104 = bitcast * %103 to *
  %__constexpr_4 = bitcast * @104 to *
  memcpy * %104 align 8, * %__constexpr_4 align 8, i64 16
  %105 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 0
  %106 = bitcast * %105 to *
  %__constexpr_5 = bitcast * @105 to *
  memcpy * %106 align 8, * %__constexpr_5 align 8, i64 16
  %107 = gep inbounds * %26, 8 x i32 0, 1 x i64 0
  %108 = load i64, * %107, align 8
  store i64 %108, * %15, align 8
  %109 = bitcast * %options.i.i.i to *
  %110 = bitcast * %16 to *
  memcpy * %110 align 8, * %109 align 8, i64 40
  %111 = bitcast * %stderr.i to *
  %112 = bitcast * %17 to *
  memcpy * %112 align 4, * %111 align 4, i64 4
  store i64 %108, * %value.i.i.i.i, align 8
  store i64 3, * %max_depth.i.i.i.i, align 8
  %119 = load i64, * %value.i.i.i.i, align 8
  store i64 %119, * %11, align 8
  %120 = bitcast * %options.i.i.i to *
  %121 = bitcast * %12 to *
  memcpy * %121 align 8, * %120 align 8, i64 40
  %122 = bitcast * %stderr.i to *
  %123 = bitcast * %13 to *
  memcpy * %123 align 4, * %122 align 4, i64 4
  store i64 %119, * %value.i.i.i.i.i, align 8
  %129 = load i64, * %value.i.i.i.i.i, align 8
  store i64 %129, * %8, align 8
  %130 = bitcast * %options.i.i.i to *
  %131 = bitcast * %9 to *
  memcpy * %131 align 8, * %130 align 8, i64 40
  %132 = bitcast * %stderr.i to *
  %133 = bitcast * %10 to *
  memcpy * %133 align 4, * %132 align 4, i64 4
  store i64 %129, * %value.i.i.i.i.i.i, align 8
  %140 = load i64, * %value.i.i.i.i.i.i, align 8
  store i64 %140, * %int_value.i.i.i.i.i.i, align 8
  %141 = load i64, * %int_value.i.i.i.i.i.i, align 8
  store i64 %141, * %5, align 8
  %142 = bitcast * %options.i.i.i to *
  %143 = bitcast * %6 to *
  memcpy * %143 align 8, * %142 align 8, i64 40
  %144 = bitcast * %stderr.i to *
  %145 = bitcast * %7 to *
  memcpy * %145 align 4, * %144 align 4, i64 4
  %146 = call i16 @std.fmt.formatInt(i64 %141, i8 10, i1 0, nonnull align(8) * %options.i.i.i, nonnull align(4) * %stderr.i)
  store i16 %146, * %result.i.i.i.i.i.i, align 2
  %147 = load i16, * %result.i.i.i.i.i.i, align 2
  store i16 %147, * %result.i.i.i.i.i, align 2
  %154 = load i16, * %result.i.i.i.i.i, align 2
  store i16 %154, * %result.i.i.i.i, align 2
  %160 = load i16, * %result.i.i.i.i, align 2
  store i16 %160, * %18, align 2
  %167 = icmp ne i16 %160, 0
  br i1 %167, label %ErrRetReturn2.i.i.i, label %ErrRetContinue3.i.i.i

%ErrRetReturn2.i.i.i:
  %168 = load i16, * %18, align 2
  store i16 %168, * %result.i.i1.i, align 2
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i

%ErrRetContinue3.i.i.i:
  %177 = call i16 @std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll(nonnull align(4) * %stderr.i, nonnull align(8) * @106)
  store i16 %177, * %19, align 2
  %178 = icmp ne i16 %177, 0
  br i1 %178, label %ErrRetReturn4.i.i.i, label %ErrRetContinue5.i.i.i

%ErrRetReturn4.i.i.i:
  %179 = load i16, * %19, align 2
  store i16 %179, * %result.i.i1.i, align 2
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i

%ErrRetContinue5.i.i.i:
  store i16 0, * %result.i.i1.i, align 2
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i

%std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i:
  %196 = phi i16 [ %88, %ErrRetReturn.i.i.i ], [ %168, %ErrRetReturn2.i.i.i ], [ %179, %ErrRetReturn4.i.i.i ], [ 0, %ErrRetContinue5.i.i.i ]
  store i16 %196, * %result.i.i, align 2
  %197 = load i16, * %result.i.i, align 2
  store i16 %197, * %25, align 2
  %201 = icmp ne i16 %197, 0
  br i1 %201, label %UnwrapErrError.i, label %UnwrapErrOk.i

%UnwrapErrError.i:
  %202 = gep inbounds * %held.i, 8 x i32 0, 1 x i64 0
  %203 = load *, * %202, align 8
  %204 = gep inbounds * %203, 1 x i32 0, 1 x i64 0
  store i1 0, * %204, align 1
  br label %std.debug.print.exit

%UnwrapErrOk.i:
  %210 = gep inbounds * %held.i, 8 x i32 0, 1 x i64 0
  %211 = load *, * %210, align 8
  %212 = gep inbounds * %211, 1 x i32 0, 1 x i64 0
  store i1 0, * %212, align 1
  br label %std.debug.print.exit

%std.debug.print.exit:
  %221 = gep inbounds * %3, 4 x i32 0, 1 x i64 0
  store i32 2, * %result.i.i.i4, align 4
  %223 = load i32, * %result.i.i.i4, align 4
  store i32 %223, * %221, align 4
  %225 = gep inbounds * %stderr.i5, 4 x i32 0, 1 x i64 0
  %226 = bitcast * %3 to *
  %227 = bitcast * %225 to *
  memcpy * %227 align 4, * %226 align 4, i64 4
  %230 = bitcast * %stderr.i5 to *
  %231 = bitcast * %2 to *
  memcpy * %231 align 4, * %230 align 4, i64 4
  %235 = bitcast * %options.i.i.i2 to *
  %__constexpr_6 = bitcast * @86 to *
  memcpy * %235 align 8, * %__constexpr_6 align 8, i64 40
  %236 = call i16 @std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll(nonnull align(4) * %stderr.i5, nonnull align(8) * @87)
  store i16 %236, * %1, align 2
  %237 = icmp ne i16 %236, 0
  br i1 %237, label %ErrRetReturn.i.i.i6, label %ErrRetContinue.i.i.i7

%ErrRetReturn.i.i.i6:
  %238 = load i16, * %1, align 2
  store i16 %238, * %result.i.i1.i1, align 2
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.9.exit.i

%ErrRetContinue.i.i.i7:
  store i16 0, * %result.i.i1.i1, align 2
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.9.exit.i

%std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.9.exit.i:
  %245 = phi i16 [ %238, %ErrRetReturn.i.i.i6 ], [ 0, %ErrRetContinue.i.i.i7 ]
  store i16 %245, * %result.i.i3, align 2
  %246 = load i16, * %result.i.i3, align 2
  store i16 %246, * %4, align 2
  %249 = icmp ne i16 %246, 0
  br i1 %249, label %UnwrapErrError.i8, label %UnwrapErrOk.i9

%UnwrapErrError.i8:
  br label %std.debug.dumpCurrentStackTrace.exit

%UnwrapErrOk.i9:
  br label %std.debug.dumpCurrentStackTrace.exit

%std.debug.dumpCurrentStackTrace.exit:
  store i16 11, * %result, align 2
  %256 = load i16, * %result, align 2
  ret i16 %256

%OptionalNull.i.i:
  call void @std.builtin.default_panic(nonnull align(8) * @19, align(8) * null) noreturn
  assume i1 0
}
=>
@stderr_mutex = global 1 bytes, align 1
@63 = constant 16 bytes, align 8
@99 = constant 40 bytes, align 8
@101 = constant 16 bytes, align 8
@102 = constant 16 bytes, align 8
@103 = constant 16 bytes, align 8
@104 = constant 16 bytes, align 8
@105 = constant 16 bytes, align 8
@106 = constant 16 bytes, align 8
@86 = constant 40 bytes, align 8
@87 = constant 16 bytes, align 8
@19 = constant 16 bytes, align 8
@100 = constant 22 bytes, align 1
@84 = constant 49 bytes, align 1
@18 = constant 18 bytes, align 1

define i16 @std.os.unexpectedErrno(i64 %0) {
#init:
  %__copy_0 = {{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} { { undef, 0, [padding] }, { undef, 0, [padding] }, 2, { 32, undef } }
  %__copy_3 = {{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} { { undef, 0, [padding] }, { undef, 0, [padding] }, 2, { 32, undef } }
  store [22 x i8] { 117, 110, 101, 120, 112, 101, 99, 116, 101, 100, 32, 101, 114, 114, 110, 111, 58, 32, 123, 125, 10, 0 }, * @100, align 1
  store {i64, i1, i56} { undef, 0, [padding] }, * @102, align 8
  store {i64, i1, i56} { undef, 0, [padding] }, * @103, align 8
  store {i64, i1, i56} { undef, 0, [padding] }, * @104, align 8
  store {i64, i1, i56} { undef, 0, [padding] }, * @105, align 8
  store [18 x i8] { 100, 101, 97, 100, 108, 111, 99, 107, 32, 100, 101, 116, 101, 99, 116, 101, 100, 0 }, * @18, align 1
  store {{*}, i1, i56} { undef, 0, [padding] }, * @63, align 8
  store [49 x i8] { 85, 110, 97, 98, 108, 101, 32, 116, 111, 32, 100, 117, 109, 112, 32, 115, 116, 97, 99, 107, 32, 116, 114, 97, 99, 101, 58, 32, 100, 101, 98, 117, 103, 32, 105, 110, 102, 111, 32, 115, 116, 114, 105, 112, 112, 101, 100, 10, 0 }, * @84, align 1
  store {{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} %__copy_3, * @86, align 8
  store {{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} %__copy_0, * @99, align 8
  br label %Entry

%Entry:
  %options.i.i.i2 = alloca i64 40, align 8
  %stderr.i5 = alloca i64 4, align 4
  %1 = alloca i64 40, align 8
  %2 = alloca i64 40, align 8
  %3 = alloca i64 40, align 8
  %options.i.i.i = alloca i64 40, align 8
  %4 = alloca i64 40, align 8
  %.sroa.6 = alloca i64 7, align 1
  %stderr.i = alloca i64 4, align 4
  %6 = gep inbounds * @stderr_mutex, 1 x i32 0, 1 x i64 0
  %7 = load i1, * %6, align 1
  br i1 %7, label %Then.i.i.i, label %Else.i.i.i

%Else.i.i.i:
  %8 = gep inbounds * @stderr_mutex, 1 x i32 0, 1 x i64 0
  store i1 1, * %8, align 1
  br label %std.mutex.Dummy.tryAcquire.exit.i.i

%Then.i.i.i:
  %__constexpr_0 = gep inbounds * @63, 16 x i64 0, 1 x i64 0, 1 x i64 0
  %.sroa.06.0.copyload = load *, * %__constexpr_0, align 8
  %__constexpr_1 = gep inbounds * @63, 16 x i64 0, 1 x i64 8
  %.sroa.3.0.copyload = load i1, * %__constexpr_1, align 8
  %.sroa.6.0..sroa_idx = gep inbounds * %.sroa.6, 7 x i64 0, 1 x i64 0
  %__constexpr_3 = bitcast * @63 to *
  %__constexpr_2 = gep inbounds * %__constexpr_3, 1 x i64 9
  memcpy * %.sroa.6.0..sroa_idx align 1, * %__constexpr_2 align 1, i64 7
  br label %std.mutex.Dummy.tryAcquire.exit.i.i

%std.mutex.Dummy.tryAcquire.exit.i.i:
  %.sroa.06.0 = phi * [ %.sroa.06.0.copyload, %Then.i.i.i ], [ @stderr_mutex, %Else.i.i.i ]
  %.sroa.3.0 = phi i1 [ %.sroa.3.0.copyload, %Then.i.i.i ], [ 1, %Else.i.i.i ]
  br i1 %.sroa.3.0, label %std.mutex.Dummy.acquire.exit.i, label %OptionalNull.i.i

%std.mutex.Dummy.acquire.exit.i:
  %.sroa.04.0..sroa_idx = gep inbounds * %stderr.i, 4 x i64 0, 1 x i64 0, 1 x i64 0
  store i32 2, * %.sroa.04.0..sroa_idx, align 4
  %.sroa.010.0..sroa_idx = gep inbounds * %stderr.i, 4 x i64 0, 1 x i64 0, 1 x i64 0
  %.sroa.010.0.copyload = load i32, * %.sroa.010.0..sroa_idx, align 4
  %10 = bitcast * %options.i.i.i to *
  %__constexpr_4 = bitcast * @99 to *
  memcpy * %10 align 8, * %__constexpr_4 align 8, i64 40
  %11 = call i16 @std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll(nonnull align(4) * %stderr.i, nonnull align(8) * @101)
  %12 = icmp ne i16 %11, 0
  br i1 %12, label %ErrRetReturn.i.i.i, label %ErrRetContinue.i.i.i

%ErrRetReturn.i.i.i:
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i

%ErrRetContinue.i.i.i:
  %14 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 0
  %15 = bitcast * %14 to *
  %__constexpr_5 = bitcast * @102 to *
  memcpy * %15 align 8, * %__constexpr_5 align 8, i64 16
  %16 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 16
  %17 = bitcast * %16 to *
  %__constexpr_6 = bitcast * @103 to *
  memcpy * %17 align 8, * %__constexpr_6 align 8, i64 16
  %18 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 32
  store i2 2, * %18, align 1
  %19 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 33
  store i8 32, * %19, align 1
  %20 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 16
  %21 = bitcast * %20 to *
  %__constexpr_7 = bitcast * @104 to *
  memcpy * %21 align 8, * %__constexpr_7 align 8, i64 16
  %22 = gep inbounds * %options.i.i.i, 40 x i32 0, 1 x i64 0
  %23 = bitcast * %22 to *
  %__constexpr_8 = bitcast * @105 to *
  memcpy * %23 align 8, * %__constexpr_8 align 8, i64 16
  %24 = bitcast * %options.i.i.i to *
  %25 = bitcast * %4 to *
  memcpy * %25 align 8, * %24 align 8, i64 40
  %.sroa.012.0..sroa_idx = gep inbounds * %stderr.i, 4 x i64 0, 1 x i64 0, 1 x i64 0
  %.sroa.012.0.copyload = load i32, * %.sroa.012.0..sroa_idx, align 4
  %26 = bitcast * %options.i.i.i to *
  %27 = bitcast * %3 to *
  memcpy * %27 align 8, * %26 align 8, i64 40
  %.sroa.014.0..sroa_idx = gep inbounds * %stderr.i, 4 x i64 0, 1 x i64 0, 1 x i64 0
  %.sroa.014.0.copyload = load i32, * %.sroa.014.0..sroa_idx, align 4
  %28 = bitcast * %options.i.i.i to *
  %29 = bitcast * %2 to *
  memcpy * %29 align 8, * %28 align 8, i64 40
  %.sroa.015.0..sroa_idx = gep inbounds * %stderr.i, 4 x i64 0, 1 x i64 0, 1 x i64 0
  %.sroa.015.0.copyload = load i32, * %.sroa.015.0..sroa_idx, align 4
  %30 = bitcast * %options.i.i.i to *
  %31 = bitcast * %1 to *
  memcpy * %31 align 8, * %30 align 8, i64 40
  %.sroa.016.0..sroa_idx = gep inbounds * %stderr.i, 4 x i64 0, 1 x i64 0, 1 x i64 0
  %.sroa.016.0.copyload = load i32, * %.sroa.016.0..sroa_idx, align 4
  %32 = call i16 @std.fmt.formatInt(i64 %0, i8 10, i1 0, nonnull align(8) * %options.i.i.i, nonnull align(4) * %stderr.i)
  %33 = icmp ne i16 %32, 0
  br i1 %33, label %ErrRetReturn2.i.i.i, label %ErrRetContinue3.i.i.i

%ErrRetReturn2.i.i.i:
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i

%ErrRetContinue3.i.i.i:
  %35 = call i16 @std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll(nonnull align(4) * %stderr.i, nonnull align(8) * @106)
  %36 = icmp ne i16 %35, 0
  br i1 %36, label %ErrRetReturn4.i.i.i, label %ErrRetContinue5.i.i.i

%ErrRetReturn4.i.i.i:
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i

%ErrRetContinue5.i.i.i:
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i

%std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.15.exit.i:
  %39 = phi i16 [ %11, %ErrRetReturn.i.i.i ], [ %32, %ErrRetReturn2.i.i.i ], [ %35, %ErrRetReturn4.i.i.i ], [ 0, %ErrRetContinue5.i.i.i ]
  %40 = icmp ne i16 %39, 0
  br i1 %40, label %UnwrapErrError.i, label %UnwrapErrOk.i

%UnwrapErrError.i:
  %41 = gep inbounds * %.sroa.06.0, 1 x i32 0, 1 x i64 0
  store i1 0, * %41, align 1
  br label %std.debug.print.exit

%UnwrapErrOk.i:
  %43 = gep inbounds * %.sroa.06.0, 1 x i32 0, 1 x i64 0
  store i1 0, * %43, align 1
  br label %std.debug.print.exit

%std.debug.print.exit:
  %.sroa.017.0..sroa_idx = gep inbounds * %stderr.i5, 4 x i64 0, 1 x i64 0, 1 x i64 0
  store i32 2, * %.sroa.017.0..sroa_idx, align 4
  %.sroa.018.0..sroa_idx = gep inbounds * %stderr.i5, 4 x i64 0, 1 x i64 0, 1 x i64 0
  %.sroa.018.0.copyload = load i32, * %.sroa.018.0..sroa_idx, align 4
  %46 = bitcast * %options.i.i.i2 to *
  %__constexpr_9 = bitcast * @86 to *
  memcpy * %46 align 8, * %__constexpr_9 align 8, i64 40
  %47 = call i16 @std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).writeAll(nonnull align(4) * %stderr.i5, nonnull align(8) * @87)
  %48 = icmp ne i16 %47, 0
  br i1 %48, label %ErrRetReturn.i.i.i6, label %ErrRetContinue.i.i.i7

%ErrRetReturn.i.i.i6:
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.9.exit.i

%ErrRetContinue.i.i.i7:
  br label %std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.9.exit.i

%std.io.writer.Writer(std.fs.file.File,std.os.WriteError,std.fs.file.File.write).print.9.exit.i:
  %49 = phi i16 [ %47, %ErrRetReturn.i.i.i6 ], [ 0, %ErrRetContinue.i.i.i7 ]
  %50 = icmp ne i16 %49, 0
  br i1 %50, label %UnwrapErrError.i8, label %UnwrapErrOk.i9

%UnwrapErrError.i8:
  br label %std.debug.dumpCurrentStackTrace.exit

%UnwrapErrOk.i9:
  br label %std.debug.dumpCurrentStackTrace.exit

%std.debug.dumpCurrentStackTrace.exit:
  ret i16 11

%OptionalNull.i.i:
  call void @std.builtin.default_panic(nonnull align(8) * @19, align(8) * null) noreturn
  assume i1 0
}
Transformation doesn't verify!
ERROR: Mismatch in memory

Example:
i64 %0 = any

Source:
{{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} %__copy_0 = { { any, #x0 (0), poison }, { any, #x0 (0), poison }, #x2 (2, -2), { #x20 (32), < any, any, any, any, any, any > } }
{{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} %__copy_3 = { { any, #x0 (0), poison }, { any, #x0 (0), poison }, #x2 (2, -2), { #x20 (32), < any, any, any, any, any, any > } }
* %result.i.i1.i1 = pointer(local, block_id=64, offset=0)
* %options.i.i.i2 = pointer(local, block_id=65, offset=0)
* %1 = pointer(local, block_id=66, offset=0)
* %result.i.i3 = pointer(local, block_id=67, offset=0)
* %2 = pointer(local, block_id=68, offset=0)
* %result.i.i.i4 = pointer(local, block_id=69, offset=0)
* %3 = pointer(local, block_id=70, offset=0)
* %stderr.i5 = pointer(local, block_id=71, offset=0)
* %4 = pointer(local, block_id=72, offset=0)
* %result.i.i.i.i.i.i = pointer(local, block_id=73, offset=0)
* %int_value.i.i.i.i.i.i = pointer(local, block_id=74, offset=0)
* %5 = pointer(local, block_id=75, offset=0)
* %6 = pointer(local, block_id=76, offset=0)
* %7 = pointer(local, block_id=77, offset=0)
* %value.i.i.i.i.i.i = pointer(local, block_id=78, offset=0)
* %result.i.i.i.i.i = pointer(local, block_id=79, offset=0)
* %8 = pointer(local, block_id=80, offset=0)
* %9 = pointer(local, block_id=81, offset=0)
* %10 = pointer(local, block_id=82, offset=0)
* %value.i.i.i.i.i = pointer(local, block_id=83, offset=0)
* %result.i.i.i.i = pointer(local, block_id=84, offset=0)
* %11 = pointer(local, block_id=85, offset=0)
* %12 = pointer(local, block_id=86, offset=0)
* %13 = pointer(local, block_id=87, offset=0)
* %value.i.i.i.i = pointer(local, block_id=88, offset=0)
* %max_depth.i.i.i.i = pointer(local, block_id=89, offset=0)
* %result.i.i1.i = pointer(local, block_id=90, offset=0)
* %options.i.i.i = pointer(local, block_id=91, offset=0)
* %14 = pointer(local, block_id=92, offset=0)
* %15 = pointer(local, block_id=93, offset=0)
* %16 = pointer(local, block_id=94, offset=0)
* %17 = pointer(local, block_id=95, offset=0)
* %18 = pointer(local, block_id=96, offset=0)
* %19 = pointer(local, block_id=97, offset=0)
* %result.i.i = pointer(local, block_id=98, offset=0)
* %20 = pointer(local, block_id=99, offset=0)
* %21 = pointer(local, block_id=100, offset=0)
* %self.i.i.i = pointer(local, block_id=101, offset=0)
* %22 = pointer(local, block_id=102, offset=0)
* %self.i.i = pointer(local, block_id=103, offset=0)
* %result.i.i.i = pointer(local, block_id=104, offset=0)
* %held.i = pointer(local, block_id=105, offset=0)
* %23 = pointer(local, block_id=106, offset=0)
* %stderr.i = pointer(local, block_id=107, offset=0)
* %24 = pointer(local, block_id=108, offset=0)
* %25 = pointer(local, block_id=109, offset=0)
* %result = pointer(local, block_id=110, offset=0)
* %26 = pointer(local, block_id=111, offset=0)
* %err = pointer(local, block_id=112, offset=0)
i64 %27 = any
* %28 = pointer(local, block_id=111, offset=0)
* %36 = pointer(non-local, block_id=15, offset=0)
* %38 = pointer(non-local, block_id=15, offset=0)
* %39 = pointer(non-local, block_id=15, offset=0)
i1 %40 = #x0 (0)
* %41 = pointer(non-local, block_id=15, offset=0)
* %42 = pointer(non-local, block_id=15, offset=0)
* %43 = pointer(local, block_id=102, offset=8)
* %44 = pointer(local, block_id=102, offset=0)
* %45 = pointer(local, block_id=102, offset=0)
* %46 = pointer(non-local, block_id=15, offset=0)
* %47 = pointer(local, block_id=102, offset=8)
* %48 = pointer(local, block_id=102, offset=0)
* %49 = pointer(local, block_id=102, offset=0)
* %50 = pointer(local, block_id=102, offset=0)
* %52 = pointer(local, block_id=102, offset=0)
* %__constexpr_0 = pointer(non-local, block_id=1, offset=0)
* %54 = pointer(local, block_id=102, offset=8)
i1 %55 = #x1 (1)
* %56 = pointer(local, block_id=102, offset=0)
* %57 = pointer(local, block_id=102, offset=0)
* %58 = pointer(local, block_id=105, offset=0)
* %61 = pointer(local, block_id=106, offset=0)
i32 %63 = #x00000002 (2)
* %65 = pointer(local, block_id=107, offset=0)
* %66 = pointer(local, block_id=106, offset=0)
* %67 = pointer(local, block_id=107, offset=0)
* %68 = pointer(local, block_id=111, offset=0)
* %69 = pointer(local, block_id=108, offset=0)
* %73 = pointer(local, block_id=107, offset=0)
* %74 = pointer(local, block_id=99, offset=0)
* %75 = pointer(local, block_id=111, offset=0)
* %76 = pointer(local, block_id=100, offset=0)
* %85 = pointer(local, block_id=91, offset=0)
* %__constexpr_1 = pointer(non-local, block_id=2, offset=0)
i16 %86 = #x0000 (0)
i1 %87 = #x0 (0)
i16 %88 = #x0000 (0)
* %97 = pointer(local, block_id=91, offset=0)
* %98 = pointer(local, block_id=91, offset=0)
* %__constexpr_2 = pointer(non-local, block_id=4, offset=0)
* %99 = pointer(local, block_id=91, offset=16)
* %100 = pointer(local, block_id=91, offset=16)
* %__constexpr_3 = pointer(non-local, block_id=5, offset=0)
* %101 = pointer(local, block_id=91, offset=32)
* %102 = pointer(local, block_id=91, offset=33)
* %103 = pointer(local, block_id=91, offset=16)
* %104 = pointer(local, block_id=91, offset=16)
* %__constexpr_4 = pointer(non-local, block_id=6, offset=0)
* %105 = pointer(local, block_id=91, offset=0)
* %106 = pointer(local, block_id=91, offset=0)
* %__constexpr_5 = pointer(non-local, block_id=7, offset=0)
* %107 = pointer(local, block_id=111, offset=0)
i64 %108 = any
* %109 = pointer(local, block_id=91, offset=0)
* %110 = pointer(local, block_id=94, offset=0)
* %111 = pointer(local, block_id=107, offset=0)
* %112 = pointer(local, block_id=95, offset=0)
i64 %119 = any
* %120 = pointer(local, block_id=91, offset=0)
* %121 = pointer(local, block_id=86, offset=0)
* %122 = pointer(local, block_id=107, offset=0)
* %123 = pointer(local, block_id=87, offset=0)
i64 %129 = any
* %130 = pointer(local, block_id=91, offset=0)
* %131 = pointer(local, block_id=81, offset=0)
* %132 = pointer(local, block_id=107, offset=0)
* %133 = pointer(local, block_id=82, offset=0)
i64 %140 = any
i64 %141 = any
* %142 = pointer(local, block_id=91, offset=0)
* %143 = pointer(local, block_id=76, offset=0)
* %144 = pointer(local, block_id=107, offset=0)
* %145 = pointer(local, block_id=77, offset=0)
i16 %146 = #x0000 (0)
i16 %147 = #x0000 (0)
i16 %154 = #x0000 (0)
i16 %160 = #x0000 (0)
i1 %167 = #x0 (0)
i16 %168 = #x0000 (0)
i16 %177 = #x0000 (0)
i1 %178 = #x0 (0)
i16 %179 = #x0000 (0)
i16 %196 = #x0000 (0)
i16 %197 = #x0000 (0)
i1 %201 = #x0 (0)
* %202 = pointer(local, block_id=105, offset=0)
* %203 = pointer(non-local, block_id=15, offset=0)
* %204 = pointer(non-local, block_id=15, offset=0)
* %210 = pointer(local, block_id=105, offset=0)
* %211 = pointer(non-local, block_id=15, offset=0)
* %212 = pointer(non-local, block_id=15, offset=0)
* %221 = pointer(local, block_id=70, offset=0)
i32 %223 = #x00000002 (2)
* %225 = pointer(local, block_id=71, offset=0)
* %226 = pointer(local, block_id=70, offset=0)
* %227 = pointer(local, block_id=71, offset=0)
* %230 = pointer(local, block_id=71, offset=0)
* %231 = pointer(local, block_id=68, offset=0)
* %235 = pointer(local, block_id=65, offset=0)
* %__constexpr_6 = pointer(non-local, block_id=9, offset=0)
i16 %236 = #xffff (65535, -1)
i1 %237 = #x1 (1)
i16 %238 = #xffff (65535, -1)
i16 %245 = #xffff (65535, -1)
i16 %246 = #xffff (65535, -1)
i1 %249 = #x1 (1)
i16 %256 = #x000b (11)

SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 >       size: 0 align: 1        alloc type: 0
Block 1 >       size: 16        align: 8        alloc type: 0
Block 2 >       size: 40        align: 8        alloc type: 0
Block 3 >       size: 16        align: 8        alloc type: 0
Block 4 >       size: 16        align: 8        alloc type: 0
Block 5 >       size: 16        align: 8        alloc type: 0
Block 6 >       size: 16        align: 8        alloc type: 0
Block 7 >       size: 16        align: 8        alloc type: 0
Block 8 >       size: 16        align: 8        alloc type: 0
Block 9 >       size: 40        align: 8        alloc type: 0
Block 10 >      size: 16        align: 8        alloc type: 0
Block 11 >      size: 16        align: 8        alloc type: 0
Block 12 >      size: 22        align: 1        alloc type: 0
Block 13 >      size: 49        align: 1        alloc type: 0
Block 14 >      size: 18        align: 1        alloc type: 0
Block 15 >      size: 1 align: 1        alloc type: 0
Block 16 >      size: 22        align: 8        alloc type: 2

LOCAL BLOCKS:
Block 64 >      size: 2 align: 2        alloc type: 1
Block 65 >      size: 40        align: 8        alloc type: 1
Block 66 >      size: 2 align: 2        alloc type: 1
Block 67 >      size: 2 align: 2        alloc type: 1
Block 68 >      size: 4 align: 4        alloc type: 1
Block 69 >      size: 4 align: 4        alloc type: 1
Block 70 >      size: 4 align: 4        alloc type: 1
Block 71 >      size: 4 align: 4        alloc type: 1
Block 72 >      size: 2 align: 2        alloc type: 1
Block 73 >      size: 2 align: 2        alloc type: 1
Block 74 >      size: 8 align: 8        alloc type: 1
Block 75 >      size: 8 align: 8        alloc type: 1
Block 76 >      size: 40        align: 8        alloc type: 1
Block 77 >      size: 4 align: 4        alloc type: 1
Block 78 >      size: 8 align: 8        alloc type: 1
Block 79 >      size: 2 align: 2        alloc type: 1
Block 80 >      size: 8 align: 8        alloc type: 1
Block 81 >      size: 40        align: 8        alloc type: 1
Block 82 >      size: 4 align: 4        alloc type: 1
Block 83 >      size: 8 align: 8        alloc type: 1
Block 84 >      size: 2 align: 2        alloc type: 1
Block 85 >      size: 8 align: 8        alloc type: 1
Block 86 >      size: 40        align: 8        alloc type: 1
Block 87 >      size: 4 align: 4        alloc type: 1
Block 88 >      size: 8 align: 8        alloc type: 1
Block 89 >      size: 8 align: 8        alloc type: 1
Block 90 >      size: 2 align: 2        alloc type: 1
Block 91 >      size: 40        align: 8        alloc type: 1
Block 92 >      size: 2 align: 2        alloc type: 1
Block 93 >      size: 8 align: 8        alloc type: 1
Block 94 >      size: 40        align: 8        alloc type: 1
Block 95 >      size: 4 align: 4        alloc type: 1
Block 96 >      size: 2 align: 2        alloc type: 1
Block 97 >      size: 2 align: 2        alloc type: 1
Block 98 >      size: 2 align: 2        alloc type: 1
Block 99 >      size: 4 align: 4        alloc type: 1
Block 100 >     size: 8 align: 8        alloc type: 1
Block 101 >     size: 8 align: 8        alloc type: 1
Block 102 >     size: 16        align: 8        alloc type: 1
Block 103 >     size: 8 align: 8        alloc type: 1
Block 104 >     size: 4 align: 4        alloc type: 1
Block 105 >     size: 8 align: 8        alloc type: 1
Block 106 >     size: 4 align: 4        alloc type: 1
Block 107 >     size: 4 align: 4        alloc type: 1
Block 108 >     size: 8 align: 8        alloc type: 1
Block 109 >     size: 2 align: 2        alloc type: 1
Block 110 >     size: 2 align: 2        alloc type: 1
Block 111 >     size: 8 align: 8        alloc type: 1
Block 112 >     size: 8 align: 8        alloc type: 1

Target:
{{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} %__copy_0 = { { #x0000000000000000 (0), #x0 (0), poison }, { any, #x0 (0), poison }, #x2 (2, -2), { #x20 (32), < any, any, any, any, any, any > } }
{{i64, i1, i56}, {i64, i1, i56}, i2, {i8, [6 x i8]}} %__copy_3 = { { #x0000000000000000 (0), #x0 (0), poison }, { any, #x0 (0), poison }, #x2 (2, -2), { #x20 (32), < any, any, any, any, any, any > } }
* %options.i.i.i2 = pointer(local, block_id=64, offset=0)
* %stderr.i5 = pointer(local, block_id=65, offset=0)
* %1 = pointer(local, block_id=66, offset=0)
* %2 = pointer(local, block_id=67, offset=0)
* %3 = pointer(local, block_id=68, offset=0)
* %options.i.i.i = pointer(local, block_id=69, offset=0)
* %4 = pointer(local, block_id=70, offset=0)
* %.sroa.6 = pointer(local, block_id=71, offset=0)
* %stderr.i = pointer(local, block_id=72, offset=0)
* %6 = pointer(non-local, block_id=15, offset=0)
i1 %7 = #x0 (0)
* %8 = pointer(non-local, block_id=15, offset=0)
* %__constexpr_0 = pointer(non-local, block_id=1, offset=0)
* %.sroa.06.0.copyload = any
* %__constexpr_1 = pointer(non-local, block_id=1, offset=8)
i1 %.sroa.3.0.copyload = #x0 (0)
* %.sroa.6.0..sroa_idx = pointer(local, block_id=71, offset=0)
* %__constexpr_3 = pointer(non-local, block_id=1, offset=0)
* %__constexpr_2 = pointer(non-local, block_id=1, offset=9)
* %.sroa.06.0 = pointer(non-local, block_id=15, offset=0)
i1 %.sroa.3.0 = #x1 (1)
* %.sroa.04.0..sroa_idx = pointer(local, block_id=72, offset=0)
* %.sroa.010.0..sroa_idx = pointer(local, block_id=72, offset=0)
i32 %.sroa.010.0.copyload = #x00000002 (2)
* %10 = pointer(local, block_id=69, offset=0)
* %__constexpr_4 = pointer(non-local, block_id=2, offset=0)
i16 %11 = #x0000 (0)
i1 %12 = #x0 (0)
* %14 = pointer(local, block_id=69, offset=0)
* %15 = pointer(local, block_id=69, offset=0)
* %__constexpr_5 = pointer(non-local, block_id=4, offset=0)
* %16 = pointer(local, block_id=69, offset=16)
* %17 = pointer(local, block_id=69, offset=16)
* %__constexpr_6 = pointer(non-local, block_id=5, offset=0)
* %18 = pointer(local, block_id=69, offset=32)
* %19 = pointer(local, block_id=69, offset=33)
* %20 = pointer(local, block_id=69, offset=16)
* %21 = pointer(local, block_id=69, offset=16)
* %__constexpr_7 = pointer(non-local, block_id=6, offset=0)
* %22 = pointer(local, block_id=69, offset=0)
* %23 = pointer(local, block_id=69, offset=0)
* %__constexpr_8 = pointer(non-local, block_id=7, offset=0)
* %24 = pointer(local, block_id=69, offset=0)
* %25 = pointer(local, block_id=70, offset=0)
* %.sroa.012.0..sroa_idx = pointer(local, block_id=72, offset=0)
i32 %.sroa.012.0.copyload = #x00000002 (2)
* %26 = pointer(local, block_id=69, offset=0)
* %27 = pointer(local, block_id=68, offset=0)
* %.sroa.014.0..sroa_idx = pointer(local, block_id=72, offset=0)
i32 %.sroa.014.0.copyload = #x00000002 (2)
* %28 = pointer(local, block_id=69, offset=0)
* %29 = pointer(local, block_id=67, offset=0)
* %.sroa.015.0..sroa_idx = pointer(local, block_id=72, offset=0)
i32 %.sroa.015.0.copyload = #x00000002 (2)
* %30 = pointer(local, block_id=69, offset=0)
* %31 = pointer(local, block_id=66, offset=0)
* %.sroa.016.0..sroa_idx = pointer(local, block_id=72, offset=0)
i32 %.sroa.016.0.copyload = #x00000002 (2)
i16 %32 = #x0000 (0)
i1 %33 = #x0 (0)
i16 %35 = #x0000 (0)
i1 %36 = #x0 (0)
i16 %39 = #x0000 (0)
i1 %40 = #x0 (0)
* %41 = pointer(non-local, block_id=15, offset=0)
* %43 = pointer(non-local, block_id=15, offset=0)
* %.sroa.017.0..sroa_idx = pointer(local, block_id=65, offset=0)
* %.sroa.018.0..sroa_idx = pointer(local, block_id=65, offset=0)
i32 %.sroa.018.0.copyload = #x00000002 (2)
* %46 = pointer(local, block_id=64, offset=0)
* %__constexpr_9 = pointer(non-local, block_id=9, offset=0)
i16 %47 = #xffff (65535, -1)
i1 %48 = #x1 (1)
i16 %49 = #xffff (65535, -1)
i1 %50 = #x1 (1)

TARGET MEMORY STATE
===================
LOCAL BLOCKS:
Block 64 >      size: 40        align: 8        alloc type: 1
Block 65 >      size: 4 align: 4        alloc type: 1
Block 66 >      size: 40        align: 8        alloc type: 1
Block 67 >      size: 40        align: 8        alloc type: 1
Block 68 >      size: 40        align: 8        alloc type: 1
Block 69 >      size: 40        align: 8        alloc type: 1
Block 70 >      size: 40        align: 8        alloc type: 1
Block 71 >      size: 7 align: 1        alloc type: 1
Block 72 >      size: 4 align: 4        alloc type: 1

Mismatch in pointer(non-local, block_id=1, offset=0)
Source value: null, byte offset=0
Target value: pointer(local, block_id=96, offset=0), byte offset=0

But i'm not sure if that is the problem you're seeing (cc @nunoplopes)

LebedevRI avatar Jan 11 '21 23:01 LebedevRI

Thank you LemonBoy for your work on tracking this down!

ghost avatar Jan 12 '21 00:01 ghost

This is either over-reduced, or the original IR is already broken, because alive2 says that the transformation is valid:

That's weird, running it with lli prints two different strings when the sroa is enabled/disabled. The transform looks ok, alive2 confirms that and so does the lack of assertions being triggered in LLVM, but the problem is only noticeable at runtime: instead of printing what happened to me you only get a w, for some reason the optimized code stomps over the length field for the string slice. Changing %TempRef = type { i64, i1 } into %TempRef = type { i64, i8 } makes the problem disappear, it seems to me that the presence of a non-byte-sized field there confuses the pass (or simply hides the error).

LemonBoy avatar Jan 12 '21 08:01 LemonBoy

You need to be careful when reducing test cases to avoid introducing UB. If that happens, anything goes 😀 I'll have a look at the report to see if I spot smth.

nunoplopes avatar Jan 12 '21 09:01 nunoplopes

Ok, I've checked the report posted by @LebedevRI: it's a bug in Alive2 😎 Alive2 isn't doing the right thing for global constants initialized with undef pointers. I changed those to poison and the report goes away. So Alive2 can't find any bug in the repro (the big one). It means one of 3 things:

  • The miscompilation happens in one of the functions with inline asm; Alive2 skips those ATM
  • The input has UB and therefore LLVM is free to print whatever. We have alive-exec which can run an LLVM IR function and tell you if it runs into UB. But it's very limited for now: functions can't have arguments and can't call other functions. So not very useful here.
  • Or Alive2 misses the bug. Possible as the input has loops.

So I send the ball back to you guys: it's not clear it's a bug in LLVM. It might just be UB on your side. Someone has to dig in.

nunoplopes avatar Jan 12 '21 11:01 nunoplopes

@nunoplopes thank you for taking a look!

LebedevRI avatar Jan 12 '21 12:01 LebedevRI

Ok, I tracked this down as I was wondering if it was a bug in Alive2 or not. There's no bug in LLVM or Alive2. It's a bug in Zig!

TL;DR: You copy a structure with type { i8*, i64 } to a temporary with type { i64, i1 }. The string size gets truncated to 1, hence you only see 1 character being printed when using SROA.

Reduced test case:

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%CallArg = type { %"[]u8" }
%"[]u8" = type { i8*, i64 }
%ExpressionResult = type { i64, i1 }

@0 = internal unnamed_addr constant [20 x i8] c"what happened to me\00", align 1
@1 = internal unnamed_addr constant %CallArg { %"[]u8" { i8* getelementptr inbounds ([20 x i8], [20 x i8]* @0, i64 0, i64 0), i64 19 } }, align 8

declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #0

define void @main() {
  %v.i = alloca %"[]u8", align 8
  %w.i = alloca %"[]u8", align 8
  %result = alloca %ExpressionResult, align 8
  %derp = alloca %ExpressionResult, align 8

  ; copy @1 -> %v.1  ([]u8 -> []u8)
  %x3 = getelementptr inbounds %CallArg, %CallArg* @1, i32 0, i32 0
  %x7 = bitcast %"[]u8"* %x3 to i8*
  %x8 = bitcast %"[]u8"* %v.i to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %x8, i8* %x7, i64 16, i1 false)

  ; copy %v.1 -> %result   ([]u8 -> ExpressionResult) BUG!
  %x14 = bitcast %ExpressionResult* %result to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %x14, i8* %x8, i64 16, i1 false)

  ; copy %result -> %w.i
  %x18 = bitcast %"[]u8"* %w.i to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %x18, i8* %x14, i64 16, i1 false)

  ; output %w.i
  call void @std.os.write(i32 1, %"[]u8"* %w.i)
  ret void

SwitchProng1.i3:                                  ; No predecessors!
  %x35 = getelementptr inbounds %ExpressionResult, %ExpressionResult* %derp, i32 0, i32 1
  store i1 false, i1* %x35, align 1
  ret void

SwitchProng2.i4:                                  ; No predecessors!
  %x37 = bitcast %ExpressionResult* %result to i8*
  %x38 = bitcast %ExpressionResult* %derp to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %x38, i8* %x37, i64 24, i1 false)
  ret void
}

define void @std.os.write(i32 %x0, %"[]u8"* %x1) {
  ; size
  %x2 = getelementptr inbounds %"[]u8", %"[]u8"* %x1, i32 0, i32 1
  %x3 = load i64, i64* %x2, align 8

  ; ptr
  %x6 = getelementptr inbounds %"[]u8", %"[]u8"* %x1, i32 0, i32 0
  %x7 = load i8*, i8** %x6, align 8
  %x10 = ptrtoint i8* %x7 to i64

  %x15 = call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 1, i64 0, i64 %x10, i64 %x3)
  ret void
}

nunoplopes avatar Jan 13 '21 15:01 nunoplopes

It's a bug in Zig!

:scream:

Thank you for pinpointing the problem, the tagged enum representation in the IR assumes there's always enough padding after { i64, i1 } so that it has the same shape in memory as { i8*, i64 }, this also explains why the SROA made the problem surface.

it's a bug in Alive2

Talk about killing two birds with one stone! :D

LemonBoy avatar Jan 13 '21 15:01 LemonBoy

This bug left me thinking.. It's debatable whether there's a bug in SROA or not. For load/store instructions, we (LLVM's LangRef) explicitly rules out reading/writing padding bits. But there's no similar wording for memcpy. I guess we need to patch either the documentation or SROA.

nunoplopes avatar Jan 13 '21 20:01 nunoplopes

This is no longer happening. Could it be possible to have a small test which covers this case to add it to the behavior tests?

davidgmbb avatar Aug 25 '22 19:08 davidgmbb