Files
c3c/test/test_suite2/errors/error_regression_2.c3t
2022-11-17 23:44:54 +01:00

871 lines
32 KiB
C

// #target: macos-x64
module test;
import std;
import libc;
struct Doc { Head *head; }
struct Head { char[]* title; }
struct Summary
{
char[]* title;
bool ok;
}
fn void Summary.print(Summary *s, CFile out)
{
// We don't have a native printf in C3 yet, so use libc,
// which is not all that nice for the strings but...
char[] title = s.title ? *s.title : "missing";
libc::fprintf(out, "Summary({ .title = %.*s, .ok = %s})", (int)title.len, title.ptr, s.ok ? (char*)"true" : (char*)"false");
}
fn bool contains(char[] haystack, char[] needle)
{
usz len = haystack.len;
usz needle_len = needle.len;
if (len < needle_len) return false;
if (!needle_len) return true;
len -= needle_len - 1;
for (usz i = 0; i < len; i++)
{
if (libc::memcmp(&haystack[i], needle.ptr, needle_len) == 0)
{
return true;
}
}
return false;
}
macro dupe(value)
{
$typeof(&value) temp = malloc($sizeof(value));
if (!temp) return ReadError.OUT_OF_MEMORY!;
*temp = value;
return temp;
}
fault ReadError
{
BAD_READ,
OUT_OF_MEMORY
}
fn Doc! readDoc(char[] url)
{
if (contains(url, "fail")) return ReadError.BAD_READ!;
if (contains(url, "head-missing")) return { .head = null };
if (contains(url, "title-missing")) return { dupe(Head { .title = null })? };
if (contains(url, "title-empty")) return { dupe(Head { .title = dupe((char[])"")? })? };
// Not particularly elegant due to missing string functions.
int len = libc::snprintf(null, 0, "Title of %.*s", (int)url.len, url.ptr);
char* str = malloc(len + 1);
if (!str) return ReadError.OUT_OF_MEMORY!;
libc::snprintf(str, len + 1, "Title of %.*s", (int)url.len, url.ptr);
return { dupe(Head { .title = dupe(str[..len - 1])? })? };
}
fn Summary buildSummary(Doc doc)
{
return Summary {
.title = doc.head ? doc.head.title : null,
.ok = true,
};
}
fn Summary readAndBuildSummary(char[] url)
{
return buildSummary(readDoc(url)) ?? Summary { .title = null, .ok = false };
/*
// or
Summary summary = buildSummary(readDoc(url));
if (catch summary) return Summary { .title = null, .ok = false };
return summary;
// or
Summary summary = buildSummary(readDoc(url));
if (try summary) return summary;
return Summary { .title = null, .ok = false };
*/
}
fault TitleResult
{
TITLE_MISSING
}
fn bool! isTitleNonEmpty(Doc doc)
{
if (!doc.head) return TitleResult.TITLE_MISSING!;
char[]* head = doc.head.title;
if (!head) return TitleResult.TITLE_MISSING!;
return (*head).len > 0;
}
fn bool! readWhetherTitleNonEmpty(char[] url)
{
return isTitleNonEmpty(readDoc(url));
}
fn char* bool_to_string(bool b)
{
return b ? "true" : "false";
}
fn char* nameFromError(anyerr e)
{
switch (e)
{
case TitleResult.TITLE_MISSING:
return "no title";
case ReadError.BAD_READ:
return "bad read";
case ReadError.OUT_OF_MEMORY:
return "out of memory";
default:
return "unknown error";
}
}
fn void main()
{
const char[][] URLS = { "good", "title-empty", "title-missing", "head-missing", "fail" };
foreach (char[] url : URLS)
{
// Yes, it's pretty onerous to print strings for the moment in C3
libc::printf(`Checking "https://%.*s/":` "\n", (int)url.len, url.ptr);
Summary summary = readAndBuildSummary(url);
libc::printf(" Summary: ");
summary.print(libc::stdout());
libc::printf("\n");
char[] title_sure = summary.title ? *summary.title : "";
libc::printf(" Title: %.*s\n", (int)title_sure.len, title_sure.ptr);
bool! has_title = readWhetherTitleNonEmpty(url);
// This looks a bit less than elegant, but as you see it's mostly due to having to
// use printf here.
libc::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? nameFromError(catch(has_title)), (has_title ?? false) ? (char*)"true" : (char*)"false");
}
}
/* #expect: test.ll
define void @test_Summary_print(ptr %0, ptr %1) #0 {
entry:
%title = alloca %"char[]", align 8
%2 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 0
%3 = load ptr, ptr %2, align 8
%ptrbool = icmp ne ptr %3, null
br i1 %ptrbool, label %cond.lhs, label %cond.rhs
cond.lhs: ; preds = %entry
%4 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 0
%5 = load ptr, ptr %4, align 8
%6 = load %"char[]", ptr %5, align 8
br label %cond.phi
cond.rhs: ; preds = %entry
br label %cond.phi
cond.phi: ; preds = %cond.rhs, %cond.lhs
%val = phi %"char[]" [ %6, %cond.lhs ], [ { ptr @.str.28, i64 7 }, %cond.rhs ]
store %"char[]" %val, ptr %title, align 8
%7 = getelementptr inbounds %"char[]", ptr %title, i32 0, i32 1
%8 = load i64, ptr %7, align 8
%uisitrunc = trunc i64 %8 to i32
%9 = getelementptr inbounds %"char[]", ptr %title, i32 0, i32 0
%10 = load ptr, ptr %9, align 8
%11 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 1
%12 = load i8, ptr %11, align 8
%13 = trunc i8 %12 to i1
%ternary = select i1 %13, ptr @.str.30, ptr @.str.31
%14 = call i32 (ptr, ptr, ...) @fprintf(ptr %1, ptr @.str.29, i32 %uisitrunc, ptr %10, ptr %ternary)
ret void
}
; Function Attrs: nounwind
define zeroext i8 @test_contains(ptr %0, i64 %1, ptr %2, i64 %3) #0 {
entry:
%haystack = alloca %"char[]", align 8
%needle = alloca %"char[]", align 8
%len = alloca i64, align 8
%needle_len = alloca i64, align 8
%i = alloca i64, align 8
%4 = getelementptr inbounds { ptr, i64 }, ptr %haystack, i32 0, i32 0
store ptr %0, ptr %4, align 8
%5 = getelementptr inbounds { ptr, i64 }, ptr %haystack, i32 0, i32 1
store i64 %1, ptr %5, align 8
%6 = getelementptr inbounds { ptr, i64 }, ptr %needle, i32 0, i32 0
store ptr %2, ptr %6, align 8
%7 = getelementptr inbounds { ptr, i64 }, ptr %needle, i32 0, i32 1
store i64 %3, ptr %7, align 8
%8 = getelementptr inbounds %"char[]", ptr %haystack, i32 0, i32 1
%9 = load i64, ptr %8, align 8
store i64 %9, ptr %len, align 8
%10 = getelementptr inbounds %"char[]", ptr %needle, i32 0, i32 1
%11 = load i64, ptr %10, align 8
store i64 %11, ptr %needle_len, align 8
%12 = load i64, ptr %len, align 8
%13 = load i64, ptr %needle_len, align 8
%lt = icmp ult i64 %12, %13
br i1 %lt, label %if.then, label %if.exit
if.then: ; preds = %entry
ret i8 0
if.exit: ; preds = %entry
%14 = load i64, ptr %needle_len, align 8
%not = icmp eq i64 %14, 0
br i1 %not, label %if.then1, label %if.exit2
if.then1: ; preds = %if.exit
ret i8 1
if.exit2: ; preds = %if.exit
%15 = load i64, ptr %len, align 8
%16 = load i64, ptr %needle_len, align 8
%sub = sub i64 %16, 1
%sub3 = sub i64 %15, %sub
store i64 %sub3, ptr %len, align 8
store i64 0, ptr %i, align 8
br label %loop.cond
loop.cond: ; preds = %if.exit6, %if.exit2
%17 = load i64, ptr %i, align 8
%18 = load i64, ptr %len, align 8
%lt4 = icmp ult i64 %17, %18
br i1 %lt4, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%19 = getelementptr inbounds %"char[]", ptr %haystack, i32 0, i32 0
%20 = load ptr, ptr %19, align 8
%21 = load i64, ptr %i, align 8
%ptroffset = getelementptr inbounds i8, ptr %20, i64 %21
%22 = getelementptr inbounds %"char[]", ptr %needle, i32 0, i32 0
%23 = load ptr, ptr %22, align 8
%24 = load i64, ptr %needle_len, align 8
%25 = call i32 @memcmp(ptr %ptroffset, ptr %23, i64 %24)
%eq = icmp eq i32 %25, 0
br i1 %eq, label %if.then5, label %if.exit6
if.then5: ; preds = %loop.body
ret i8 1
if.exit6: ; preds = %loop.body
%26 = load i64, ptr %i, align 8
%add = add i64 %26, 1
store i64 %add, ptr %i, align 8
br label %loop.cond
loop.exit: ; preds = %loop.cond
ret i8 0
}
; Function Attrs: nounwind
define i64 @test_readDoc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%url = alloca %"char[]", align 8
%reterr = alloca i64, align 8
%literal = alloca %Doc, align 8
%reterr8 = alloca i64, align 8
%literal9 = alloca %Doc, align 8
%error_var = alloca i64, align 8
%value = alloca %Head, align 8
%literal10 = alloca %Head, align 8
%temp = alloca ptr, align 8
%reterr17 = alloca i64, align 8
%literal18 = alloca %Doc, align 8
%error_var19 = alloca i64, align 8
%value20 = alloca %Head, align 8
%literal21 = alloca %Head, align 8
%error_var22 = alloca i64, align 8
%value23 = alloca %"char[]", align 8
%temp24 = alloca ptr, align 8
%temp30 = alloca ptr, align 8
%len = alloca i32, align 4
%str = alloca ptr, align 8
%reterr43 = alloca i64, align 8
%literal44 = alloca %Doc, align 8
%error_var45 = alloca i64, align 8
%value46 = alloca %Head, align 8
%literal47 = alloca %Head, align 8
%error_var48 = alloca i64, align 8
%value49 = alloca %"char[]", align 8
%temp50 = alloca ptr, align 8
%temp56 = alloca ptr, align 8
%3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0
store ptr %1, ptr %3, align 8
%4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1
store i64 %2, ptr %4, align 8
%5 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%lo = load ptr, ptr %5, align 8
%6 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%hi = load i64, ptr %6, align 8
%7 = call i8 @test_contains(ptr %lo, i64 %hi, ptr @.str, i64 4)
%8 = trunc i8 %7 to i1
br i1 %8, label %if.then, label %if.exit
if.then: ; preds = %entry
ret i64 ptrtoint (ptr @"test_ReadError$BAD_READ" to i64)
if.exit: ; preds = %entry
%9 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%lo1 = load ptr, ptr %9, align 8
%10 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%hi2 = load i64, ptr %10, align 8
%11 = call i8 @test_contains(ptr %lo1, i64 %hi2, ptr @.str.3, i64 12)
%12 = trunc i8 %11 to i1
br i1 %12, label %if.then3, label %if.exit4
if.then3: ; preds = %if.exit
%13 = getelementptr inbounds %Doc, ptr %literal, i32 0, i32 0
store ptr null, ptr %13, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 8, i1 false)
ret i64 0
if.exit4: ; preds = %if.exit
%14 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%lo5 = load ptr, ptr %14, align 8
%15 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%hi6 = load i64, ptr %15, align 8
%16 = call i8 @test_contains(ptr %lo5, i64 %hi6, ptr @.str.4, i64 13)
%17 = trunc i8 %16 to i1
br i1 %17, label %if.then7, label %if.exit13
if.then7: ; preds = %if.exit4
%18 = getelementptr inbounds %Doc, ptr %literal9, i32 0, i32 0
%19 = getelementptr inbounds %Head, ptr %literal10, i32 0, i32 0
store ptr null, ptr %19, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value, ptr align 8 %literal10, i32 8, i1 false)
%20 = call ptr @std_core_mem_malloc(i64 8) #2
store ptr %20, ptr %temp, align 8
%21 = load ptr, ptr %temp, align 8
%not = icmp eq ptr %21, null
br i1 %not, label %if.then11, label %if.exit12
if.then11: ; preds = %if.then7
store i64 ptrtoint (ptr @"test_ReadError$OUT_OF_MEMORY" to i64), ptr %error_var, align 8
br label %guard_block
if.exit12: ; preds = %if.then7
%22 = load ptr, ptr %temp, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %22, ptr align 8 %value, i32 8, i1 false)
br label %noerr_block
guard_block: ; preds = %if.then11
%23 = load i64, ptr %error_var, align 8
ret i64 %23
noerr_block: ; preds = %if.exit12
%24 = load ptr, ptr %temp, align 8
store ptr %24, ptr %18, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal9, i32 8, i1 false)
ret i64 0
if.exit13: ; preds = %if.exit4
%25 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%lo14 = load ptr, ptr %25, align 8
%26 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%hi15 = load i64, ptr %26, align 8
%27 = call i8 @test_contains(ptr %lo14, i64 %hi15, ptr @.str.5, i64 11)
%28 = trunc i8 %27 to i1
br i1 %28, label %if.then16, label %if.exit36
if.then16: ; preds = %if.exit13
%29 = getelementptr inbounds %Doc, ptr %literal18, i32 0, i32 0
store ptr null, ptr %literal21, align 8
%30 = getelementptr inbounds %Head, ptr %literal21, i32 0, i32 0
store %"char[]" zeroinitializer, ptr %value23, align 8
%31 = call ptr @std_core_mem_malloc(i64 16) #2
store ptr %31, ptr %temp24, align 8
%32 = load ptr, ptr %temp24, align 8
%not25 = icmp eq ptr %32, null
br i1 %not25, label %if.then26, label %if.exit27
if.then26: ; preds = %if.then16
store i64 ptrtoint (ptr @"test_ReadError$OUT_OF_MEMORY" to i64), ptr %error_var22, align 8
br label %guard_block28
if.exit27: ; preds = %if.then16
%33 = load ptr, ptr %temp24, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %33, ptr align 8 %value23, i32 16, i1 false)
br label %noerr_block29
guard_block28: ; preds = %if.then26
%34 = load i64, ptr %error_var22, align 8
ret i64 %34
noerr_block29: ; preds = %if.exit27
%35 = load ptr, ptr %temp24, align 8
store ptr %35, ptr %30, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value20, ptr align 8 %literal21, i32 8, i1 false)
%36 = call ptr @std_core_mem_malloc(i64 8) #2
store ptr %36, ptr %temp30, align 8
%37 = load ptr, ptr %temp30, align 8
%not31 = icmp eq ptr %37, null
br i1 %not31, label %if.then32, label %if.exit33
if.then32: ; preds = %noerr_block29
store i64 ptrtoint (ptr @"test_ReadError$OUT_OF_MEMORY" to i64), ptr %error_var19, align 8
br label %guard_block34
if.exit33: ; preds = %noerr_block29
%38 = load ptr, ptr %temp30, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %38, ptr align 8 %value20, i32 8, i1 false)
br label %noerr_block35
guard_block34: ; preds = %if.then32
%39 = load i64, ptr %error_var19, align 8
ret i64 %39
noerr_block35: ; preds = %if.exit33
%40 = load ptr, ptr %temp30, align 8
store ptr %40, ptr %29, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal18, i32 8, i1 false)
ret i64 0
if.exit36: ; preds = %if.exit13
%41 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%42 = load i64, ptr %41, align 8
%uisitrunc = trunc i64 %42 to i32
%43 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%44 = load ptr, ptr %43, align 8
%45 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.7, i32 %uisitrunc, ptr %44)
store i32 %45, ptr %len, align 4
%46 = load i32, ptr %len, align 4
%siuiext = sext i32 %46 to i64
%add = add i64 %siuiext, 1
%47 = call ptr @std_core_mem_malloc(i64 %add) #2
store ptr %47, ptr %str, align 8
%48 = load ptr, ptr %str, align 8
%not37 = icmp eq ptr %48, null
br i1 %not37, label %if.then38, label %if.exit39
if.then38: ; preds = %if.exit36
ret i64 ptrtoint (ptr @"test_ReadError$OUT_OF_MEMORY" to i64)
if.exit39: ; preds = %if.exit36
%49 = load ptr, ptr %str, align 8
%50 = load i32, ptr %len, align 4
%siuiext40 = sext i32 %50 to i64
%add41 = add i64 %siuiext40, 1
%51 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%52 = load i64, ptr %51, align 8
%uisitrunc42 = trunc i64 %52 to i32
%53 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%54 = load ptr, ptr %53, align 8
%55 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %49, i64 %add41, ptr @.str.8, i32 %uisitrunc42, ptr %54)
%56 = getelementptr inbounds %Doc, ptr %literal44, i32 0, i32 0
store ptr null, ptr %literal47, align 8
%57 = getelementptr inbounds %Head, ptr %literal47, i32 0, i32 0
%58 = load ptr, ptr %str, align 8
%59 = load i32, ptr %len, align 4
%sub = sub i32 %59, 1
%sisiext = sext i32 %sub to i64
%60 = add i64 %sisiext, 1
%size = sub i64 %60, 0
%ptroffset = getelementptr inbounds i8, ptr %58, i64 0
%61 = insertvalue %"char[]" undef, ptr %ptroffset, 0
%62 = insertvalue %"char[]" %61, i64 %size, 1
store %"char[]" %62, ptr %value49, align 8
%63 = call ptr @std_core_mem_malloc(i64 16) #2
store ptr %63, ptr %temp50, align 8
%64 = load ptr, ptr %temp50, align 8
%not51 = icmp eq ptr %64, null
br i1 %not51, label %if.then52, label %if.exit53
if.then52: ; preds = %if.exit39
store i64 ptrtoint (ptr @"test_ReadError$OUT_OF_MEMORY" to i64), ptr %error_var48, align 8
br label %guard_block54
if.exit53: ; preds = %if.exit39
%65 = load ptr, ptr %temp50, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %65, ptr align 8 %value49, i32 16, i1 false)
br label %noerr_block55
guard_block54: ; preds = %if.then52
%66 = load i64, ptr %error_var48, align 8
ret i64 %66
noerr_block55: ; preds = %if.exit53
%67 = load ptr, ptr %temp50, align 8
store ptr %67, ptr %57, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value46, ptr align 8 %literal47, i32 8, i1 false)
%68 = call ptr @std_core_mem_malloc(i64 8) #2
store ptr %68, ptr %temp56, align 8
%69 = load ptr, ptr %temp56, align 8
%not57 = icmp eq ptr %69, null
br i1 %not57, label %if.then58, label %if.exit59
if.then58: ; preds = %noerr_block55
store i64 ptrtoint (ptr @"test_ReadError$OUT_OF_MEMORY" to i64), ptr %error_var45, align 8
br label %guard_block60
if.exit59: ; preds = %noerr_block55
%70 = load ptr, ptr %temp56, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %70, ptr align 8 %value46, i32 8, i1 false)
br label %noerr_block61
guard_block60: ; preds = %if.then58
%71 = load i64, ptr %error_var45, align 8
ret i64 %71
noerr_block61: ; preds = %if.exit59
%72 = load ptr, ptr %temp56, align 8
store ptr %72, ptr %56, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal44, i32 8, i1 false)
ret i64 0
}
; Function Attrs: nounwind
define { ptr, i8 } @test_buildSummary(ptr %0) #0 {
entry:
%doc = alloca %Doc, align 8
%literal = alloca %Summary, align 8
%1 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0
store ptr %0, ptr %1, align 8
%2 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0
store ptr null, ptr %2, align 8
%3 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1
store i8 0, ptr %3, align 8
%4 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0
%5 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0
%6 = load ptr, ptr %5, align 8
%ptrbool = icmp ne ptr %6, null
br i1 %ptrbool, label %cond.lhs, label %cond.rhs
cond.lhs: ; preds = %entry
%7 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0
%8 = load ptr, ptr %7, align 8
%9 = getelementptr inbounds %Head, ptr %8, i32 0, i32 0
%10 = load ptr, ptr %9, align 8
br label %cond.phi
cond.rhs: ; preds = %entry
br label %cond.phi
cond.phi: ; preds = %cond.rhs, %cond.lhs
%val = phi ptr [ %10, %cond.lhs ], [ null, %cond.rhs ]
store ptr %val, ptr %4, align 8
%11 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1
store i8 1, ptr %11, align 8
%12 = load { ptr, i8 }, ptr %literal, align 8
ret { ptr, i8 } %12
}
; Function Attrs: nounwind
define { ptr, i8 } @test_readAndBuildSummary(ptr %0, i64 %1) #0 {
entry:
%url = alloca %"char[]", align 8
%retparam = alloca %Doc, align 8
%result = alloca %Summary, align 8
%literal = alloca %Summary, align 8
%taddr = alloca %Summary, align 8
%2 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0
store ptr %0, ptr %2, align 8
%3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1
store i64 %1, ptr %3, align 8
%4 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%lo = load ptr, ptr %4, align 8
%5 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%hi = load i64, ptr %5, align 8
%6 = call i64 @test_readDoc(ptr %retparam, ptr %lo, i64 %hi)
%not_err = icmp eq i64 %6, 0
br i1 %not_err, label %after_check, label %else_block
after_check: ; preds = %entry
%7 = getelementptr inbounds %Doc, ptr %retparam, i32 0, i32 0
%8 = load ptr, ptr %7, align 8
%9 = call { ptr, i8 } @test_buildSummary(ptr %8)
store { ptr, i8 } %9, ptr %result, align 8
%10 = load %Summary, ptr %result, align 8
br label %phi_block
else_block: ; preds = %entry
%11 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 0
store ptr null, ptr %11, align 8
%12 = getelementptr inbounds %Summary, ptr %literal, i32 0, i32 1
store i8 0, ptr %12, align 8
%13 = load %Summary, ptr %literal, align 8
br label %phi_block
phi_block: ; preds = %else_block, %after_check
%val = phi %Summary [ %10, %after_check ], [ %13, %else_block ]
store %Summary %val, ptr %taddr, align 8
%14 = load { ptr, i8 }, ptr %taddr, align 8
ret { ptr, i8 } %14
}
; Function Attrs: nounwind
define i64 @test_isTitleNonEmpty(ptr %0, ptr %1) #0 {
entry:
%doc = alloca %Doc, align 8
%head = alloca ptr, align 8
%reterr = alloca i64, align 8
%2 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0
store ptr %1, ptr %2, align 8
%3 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0
%4 = load ptr, ptr %3, align 8
%not = icmp eq ptr %4, null
br i1 %not, label %if.then, label %if.exit
if.then: ; preds = %entry
ret i64 ptrtoint (ptr @"test_TitleResult$TITLE_MISSING" to i64)
if.exit: ; preds = %entry
%5 = getelementptr inbounds %Doc, ptr %doc, i32 0, i32 0
%6 = load ptr, ptr %5, align 8
%7 = getelementptr inbounds %Head, ptr %6, i32 0, i32 0
%8 = load ptr, ptr %7, align 8
store ptr %8, ptr %head, align 8
%9 = load ptr, ptr %head, align 8
%not1 = icmp eq ptr %9, null
br i1 %not1, label %if.then2, label %if.exit3
if.then2: ; preds = %if.exit
ret i64 ptrtoint (ptr @"test_TitleResult$TITLE_MISSING" to i64)
if.exit3: ; preds = %if.exit
%10 = load ptr, ptr %head, align 8
%11 = getelementptr inbounds %"char[]", ptr %10, i32 0, i32 1
%12 = load i64, ptr %11, align 8
%lt = icmp ult i64 0, %12
%13 = zext i1 %lt to i8
store i8 %13, ptr %0, align 1
ret i64 0
}
; Function Attrs: nounwind
define i64 @test_readWhetherTitleNonEmpty(ptr %0, ptr %1, i64 %2) #0 {
entry:
%url = alloca %"char[]", align 8
%reterr = alloca i64, align 8
%retparam = alloca i8, align 1
%retparam1 = alloca %Doc, align 8
%3 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0
store ptr %1, ptr %3, align 8
%4 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1
store i64 %2, ptr %4, align 8
%5 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%lo = load ptr, ptr %5, align 8
%6 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%hi = load i64, ptr %6, align 8
%7 = call i64 @test_readDoc(ptr %retparam1, ptr %lo, i64 %hi)
%not_err = icmp eq i64 %7, 0
br i1 %not_err, label %after_check, label %assign_optional
assign_optional: ; preds = %entry
store i64 %7, ptr %reterr, align 8
br label %err_retblock
after_check: ; preds = %entry
%8 = getelementptr inbounds %Doc, ptr %retparam1, i32 0, i32 0
%9 = load ptr, ptr %8, align 8
%10 = call i64 @test_isTitleNonEmpty(ptr %retparam, ptr %9)
%not_err2 = icmp eq i64 %10, 0
br i1 %not_err2, label %after_check4, label %assign_optional3
assign_optional3: ; preds = %after_check
store i64 %10, ptr %reterr, align 8
br label %err_retblock
after_check4: ; preds = %after_check
%11 = load i8, ptr %retparam, align 1
store i8 %11, ptr %0, align 1
ret i64 0
err_retblock: ; preds = %assign_optional3, %assign_optional
%12 = load i64, ptr %reterr, align 8
ret i64 %12
}
; Function Attrs: nounwind
define ptr @test_bool_to_string(i8 zeroext %0) #0 {
entry:
%1 = trunc i8 %0 to i1
%ternary = select i1 %1, %"char[]" { ptr @.str.9, i64 4 }, %"char[]" { ptr @.str.10, i64 5 }
%2 = extractvalue %"char[]" %ternary, 0
ret ptr %2
}
; Function Attrs: nounwind
define ptr @test_nameFromError(i64 %0) #0 {
entry:
%switch = alloca i64, align 8
store i64 %0, ptr %switch, align 8
br label %switch.entry
switch.entry: ; preds = %entry
%1 = load i64, ptr %switch, align 8
%eq = icmp eq i64 ptrtoint (ptr @"test_TitleResult$TITLE_MISSING" to i64), %1
br i1 %eq, label %switch.case, label %next_if
switch.case: ; preds = %switch.entry
ret ptr @.str.11
next_if: ; preds = %switch.entry
%eq1 = icmp eq i64 ptrtoint (ptr @"test_ReadError$BAD_READ" to i64), %1
br i1 %eq1, label %switch.case2, label %next_if3
switch.case2: ; preds = %next_if
ret ptr @.str.12
next_if3: ; preds = %next_if
%eq4 = icmp eq i64 ptrtoint (ptr @"test_ReadError$OUT_OF_MEMORY" to i64), %1
br i1 %eq4, label %switch.case5, label %next_if6
switch.case5: ; preds = %next_if3
ret ptr @.str.13
next_if6: ; preds = %next_if3
br label %switch.default
switch.default: ; preds = %next_if6
ret ptr @.str.14
}
; Function Attrs: nounwind
define void @test_main() #0 {
entry:
%URLS = alloca %"char[][]", align 8
%literal = alloca [5 x %"char[]"], align 16
%.anon = alloca i64, align 8
%.anon1 = alloca i64, align 8
%url = alloca %"char[]", align 8
%summary = alloca %Summary, align 8
%result = alloca %Summary, align 8
%title_sure = alloca %"char[]", align 8
%has_title = alloca i8, align 1
%has_title.f = alloca i64, align 8
%retparam = alloca i8, align 1
%0 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 0
store %"char[]" { ptr @.str.15, i64 4 }, ptr %0, align 8
%1 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 1
store %"char[]" { ptr @.str.16, i64 11 }, ptr %1, align 8
%2 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 2
store %"char[]" { ptr @.str.17, i64 13 }, ptr %2, align 8
%3 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 3
store %"char[]" { ptr @.str.18, i64 12 }, ptr %3, align 8
%4 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 4
store %"char[]" { ptr @.str.19, i64 4 }, ptr %4, align 8
%5 = insertvalue %"char[][]" undef, ptr %literal, 0
%6 = insertvalue %"char[][]" %5, i64 5, 1
store %"char[][]" %6, ptr %URLS, align 8
%7 = getelementptr inbounds %"char[][]", ptr %URLS, i32 0, i32 1
%8 = load i64, ptr %7, align 8
store i64 %8, ptr %.anon, align 8
store i64 0, ptr %.anon1, align 8
br label %loop.cond
loop.cond: ; preds = %phi_block12, %entry
%9 = load i64, ptr %.anon1, align 8
%10 = load i64, ptr %.anon, align 8
%lt = icmp ult i64 %9, %10
br i1 %lt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond
%11 = getelementptr inbounds %"char[][]", ptr %URLS, i32 0, i32 0
%12 = load ptr, ptr %11, align 8
%13 = load i64, ptr %.anon1, align 8
%ptroffset = getelementptr inbounds %"char[]", ptr %12, i64 %13
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %url, ptr align 8 %ptroffset, i32 16, i1 false)
%14 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%15 = load i64, ptr %14, align 8
%uisitrunc = trunc i64 %15 to i32
%16 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%17 = load ptr, ptr %16, align 8
%18 = call i32 (ptr, ...) @printf(ptr @.str.20, i32 %uisitrunc, ptr %17)
%19 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%lo = load ptr, ptr %19, align 8
%20 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%hi = load i64, ptr %20, align 8
%21 = call { ptr, i8 } @test_readAndBuildSummary(ptr %lo, i64 %hi)
store { ptr, i8 } %21, ptr %result, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %summary, ptr align 8 %result, i32 16, i1 false)
%22 = call i32 (ptr, ...) @printf(ptr @.str.21)
%23 = load ptr, ptr @__stdoutp, align 8
call void @test_Summary_print(ptr %summary, ptr %23)
%24 = call i32 (ptr, ...) @printf(ptr @.str.22)
%25 = getelementptr inbounds %Summary, ptr %summary, i32 0, i32 0
%26 = load ptr, ptr %25, align 8
%ptrbool = icmp ne ptr %26, null
br i1 %ptrbool, label %cond.lhs, label %cond.rhs
cond.lhs: ; preds = %loop.body
%27 = getelementptr inbounds %Summary, ptr %summary, i32 0, i32 0
%28 = load ptr, ptr %27, align 8
%29 = load %"char[]", ptr %28, align 8
br label %cond.phi
cond.rhs: ; preds = %loop.body
br label %cond.phi
cond.phi: ; preds = %cond.rhs, %cond.lhs
%val = phi %"char[]" [ %29, %cond.lhs ], [ zeroinitializer, %cond.rhs ]
store %"char[]" %val, ptr %title_sure, align 8
%30 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 1
%31 = load i64, ptr %30, align 8
%uisitrunc2 = trunc i64 %31 to i32
%32 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 0
%33 = load ptr, ptr %32, align 8
%34 = call i32 (ptr, ...) @printf(ptr @.str.24, i32 %uisitrunc2, ptr %33)
%35 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0
%lo3 = load ptr, ptr %35, align 8
%36 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 1
%hi4 = load i64, ptr %36, align 8
%37 = call i64 @test_readWhetherTitleNonEmpty(ptr %retparam, ptr %lo3, i64 %hi4)
%not_err = icmp eq i64 %37, 0
br i1 %not_err, label %after_check, label %assign_optional
assign_optional: ; preds = %cond.phi
store i64 %37, ptr %has_title.f, align 8
br label %after_assign
after_check: ; preds = %cond.phi
%38 = load i8, ptr %retparam, align 1
store i8 %38, ptr %has_title, align 1
store i64 0, ptr %has_title.f, align 8
br label %after_assign
after_assign: ; preds = %after_check, %assign_optional
%optval = load i64, ptr %has_title.f, align 8
%not_err5 = icmp eq i64 %optval, 0
br i1 %not_err5, label %after_check6, label %else_block
after_check6: ; preds = %after_assign
%39 = load i8, ptr %has_title, align 1
%40 = call ptr @test_bool_to_string(i8 %39)
br label %phi_block
else_block: ; preds = %after_assign
%41 = load i64, ptr %has_title.f, align 8
%42 = call ptr @test_nameFromError(i64 %41)
br label %phi_block
phi_block: ; preds = %else_block, %after_check6
%val7 = phi ptr [ %40, %after_check6 ], [ %42, %else_block ]
%optval8 = load i64, ptr %has_title.f, align 8
%not_err9 = icmp eq i64 %optval8, 0
br i1 %not_err9, label %after_check10, label %else_block11
after_check10: ; preds = %phi_block
%43 = load i8, ptr %has_title, align 1
%44 = trunc i8 %43 to i1
br label %phi_block12
else_block11: ; preds = %phi_block
br label %phi_block12
phi_block12: ; preds = %else_block11, %after_check10
%val13 = phi i1 [ %44, %after_check10 ], [ false, %else_block11 ]
%ternary = select i1 %val13, ptr @.str.26, ptr @.str.27
%45 = call i32 (ptr, ...) @printf(ptr @.str.25, ptr %val7, ptr %ternary)
%46 = load i64, ptr %.anon1, align 8
%add = add i64 %46, 1
store i64 %add, ptr %.anon1, align 8
br label %loop.cond
loop.exit: ; preds = %loop.cond
ret void
}