mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
839 lines
30 KiB
Plaintext
839 lines
30 KiB
Plaintext
// #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.
|
|
isz 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(anyfault 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 = load ptr, ptr %0, align 8
|
|
%i2b = icmp ne ptr %2, null
|
|
br i1 %i2b, label %cond.lhs, label %cond.rhs
|
|
|
|
cond.lhs: ; preds = %entry
|
|
%3 = load ptr, ptr %0, align 8
|
|
%4 = load %"char[]", ptr %3, align 8
|
|
br label %cond.phi
|
|
|
|
cond.rhs: ; preds = %entry
|
|
br label %cond.phi
|
|
|
|
cond.phi: ; preds = %cond.rhs, %cond.lhs
|
|
%val = phi %"char[]" [ %4, %cond.lhs ], [ { ptr @.str.28, i64 7 }, %cond.rhs ]
|
|
store %"char[]" %val, ptr %title, align 8
|
|
%ptradd = getelementptr inbounds i8, ptr %title, i64 8
|
|
%5 = load i64, ptr %ptradd, align 8
|
|
%trunc = trunc i64 %5 to i32
|
|
%ptradd1 = getelementptr inbounds i8, ptr %0, i64 8
|
|
%6 = load i8, ptr %ptradd1, align 8
|
|
%7 = trunc i8 %6 to i1
|
|
%ternary = select i1 %7, ptr @.str.30, ptr @.str.31
|
|
%8 = load ptr, ptr %title, align 8
|
|
%9 = call i32 (ptr, ptr, ...) @fprintf(ptr %1, ptr @.str.29, i32 %trunc, ptr %8, ptr %ternary)
|
|
ret void
|
|
}
|
|
|
|
; Function Attrs:
|
|
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
|
|
store ptr %0, ptr %haystack, align 8
|
|
%ptradd = getelementptr inbounds i8, ptr %haystack, i64 8
|
|
store i64 %1, ptr %ptradd, align 8
|
|
store ptr %2, ptr %needle, align 8
|
|
%ptradd1 = getelementptr inbounds i8, ptr %needle, i64 8
|
|
store i64 %3, ptr %ptradd1, align 8
|
|
%ptradd2 = getelementptr inbounds i8, ptr %haystack, i64 8
|
|
%4 = load i64, ptr %ptradd2, align 8
|
|
store i64 %4, ptr %len, align 8
|
|
%ptradd3 = getelementptr inbounds i8, ptr %needle, i64 8
|
|
%5 = load i64, ptr %ptradd3, align 8
|
|
store i64 %5, ptr %needle_len, align 8
|
|
%6 = load i64, ptr %len, align 8
|
|
%7 = load i64, ptr %needle_len, align 8
|
|
%lt = icmp ult i64 %6, %7
|
|
br i1 %lt, label %if.then, label %if.exit
|
|
|
|
if.then: ; preds = %entry
|
|
ret i8 0
|
|
|
|
if.exit: ; preds = %entry
|
|
%8 = load i64, ptr %needle_len, align 8
|
|
%i2nb = icmp eq i64 %8, 0
|
|
br i1 %i2nb, label %if.then4, label %if.exit5
|
|
|
|
if.then4: ; preds = %if.exit
|
|
ret i8 1
|
|
|
|
if.exit5: ; preds = %if.exit
|
|
%9 = load i64, ptr %len, align 8
|
|
%10 = load i64, ptr %needle_len, align 8
|
|
%sub = sub i64 %10, 1
|
|
%sub6 = sub i64 %9, %sub
|
|
store i64 %sub6, ptr %len, align 8
|
|
store i64 0, ptr %i, align 8
|
|
br label %loop.cond
|
|
|
|
loop.cond: ; preds = %if.exit10, %if.exit5
|
|
%11 = load i64, ptr %i, align 8
|
|
%12 = load i64, ptr %len, align 8
|
|
%lt7 = icmp ult i64 %11, %12
|
|
br i1 %lt7, label %loop.body, label %loop.exit
|
|
|
|
loop.body: ; preds = %loop.cond
|
|
%13 = load ptr, ptr %haystack, align 8
|
|
%14 = load i64, ptr %i, align 8
|
|
%ptradd8 = getelementptr inbounds i8, ptr %13, i64 %14
|
|
%15 = load ptr, ptr %needle, align 8
|
|
%16 = load i64, ptr %needle_len, align 8
|
|
%17 = call i32 @memcmp(ptr %ptradd8, ptr %15, i64 %16)
|
|
%eq = icmp eq i32 %17, 0
|
|
br i1 %eq, label %if.then9, label %if.exit10
|
|
|
|
if.then9: ; preds = %loop.body
|
|
ret i8 1
|
|
|
|
if.exit10: ; preds = %loop.body
|
|
%18 = load i64, ptr %i, align 8
|
|
%add = add i64 %18, 1
|
|
store i64 %add, ptr %i, align 8
|
|
br label %loop.cond
|
|
|
|
loop.exit: ; preds = %loop.cond
|
|
ret i8 0
|
|
}
|
|
|
|
; Function Attrs:
|
|
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
|
|
%reterr11 = alloca i64, align 8
|
|
%literal12 = alloca %Doc, align 8
|
|
%error_var = alloca i64, align 8
|
|
%literal13 = alloca %Head, align 8
|
|
%value = alloca %Head, align 8
|
|
%temp = alloca ptr, align 8
|
|
%reterr21 = alloca i64, align 8
|
|
%literal22 = alloca %Doc, align 8
|
|
%error_var23 = alloca i64, align 8
|
|
%literal24 = alloca %Head, align 8
|
|
%error_var25 = alloca i64, align 8
|
|
%value26 = alloca %"char[]", align 8
|
|
%temp27 = alloca ptr, align 8
|
|
%value33 = alloca %Head, align 8
|
|
%temp34 = alloca ptr, align 8
|
|
%len = alloca i64, align 8
|
|
%str = alloca ptr, align 8
|
|
%reterr48 = alloca i64, align 8
|
|
%literal49 = alloca %Doc, align 8
|
|
%error_var50 = alloca i64, align 8
|
|
%literal51 = alloca %Head, align 8
|
|
%error_var52 = alloca i64, align 8
|
|
%value53 = alloca %"char[]", align 8
|
|
%temp54 = alloca ptr, align 8
|
|
%value60 = alloca %Head, align 8
|
|
%temp61 = alloca ptr, align 8
|
|
store ptr %1, ptr %url, align 8
|
|
%ptradd = getelementptr inbounds i8, ptr %url, i64 8
|
|
store i64 %2, ptr %ptradd, align 8
|
|
%lo = load ptr, ptr %url, align 8
|
|
%ptradd1 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%hi = load i64, ptr %ptradd1, align 8
|
|
%3 = call i8 @test.contains(ptr %lo, i64 %hi, ptr @.str, i64 4)
|
|
%4 = trunc i8 %3 to i1
|
|
br i1 %4, label %if.then, label %if.exit
|
|
|
|
if.then: ; preds = %entry
|
|
ret i64 ptrtoint (ptr @"test.ReadError$BAD_READ" to i64)
|
|
|
|
if.exit: ; preds = %entry
|
|
%lo2 = load ptr, ptr %url, align 8
|
|
%ptradd3 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%hi4 = load i64, ptr %ptradd3, align 8
|
|
%5 = call i8 @test.contains(ptr %lo2, i64 %hi4, ptr @.str.3, i64 12)
|
|
%6 = trunc i8 %5 to i1
|
|
br i1 %6, label %if.then5, label %if.exit6
|
|
|
|
if.then5: ; preds = %if.exit
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 8, i1 false)
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 8, i1 false)
|
|
ret i64 0
|
|
|
|
if.exit6: ; preds = %if.exit
|
|
%lo7 = load ptr, ptr %url, align 8
|
|
%ptradd8 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%hi9 = load i64, ptr %ptradd8, align 8
|
|
%7 = call i8 @test.contains(ptr %lo7, i64 %hi9, ptr @.str.4, i64 13)
|
|
%8 = trunc i8 %7 to i1
|
|
br i1 %8, label %if.then10, label %if.exit16
|
|
|
|
if.then10: ; preds = %if.exit6
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal13, ptr align 8 @.__const.5, i32 8, i1 false)
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value, ptr align 8 %literal13, i32 8, i1 false)
|
|
%9 = call ptr @std.core.mem.malloc(i64 8) #3
|
|
store ptr %9, ptr %temp, align 8
|
|
%10 = load ptr, ptr %temp, align 8
|
|
%i2nb = icmp eq ptr %10, null
|
|
br i1 %i2nb, label %if.then14, label %if.exit15
|
|
|
|
if.then14: ; preds = %if.then10
|
|
store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var, align 8
|
|
br label %guard_block
|
|
|
|
if.exit15: ; preds = %if.then10
|
|
%11 = load ptr, ptr %temp, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %11, ptr align 8 %value, i32 8, i1 false)
|
|
br label %noerr_block
|
|
|
|
guard_block: ; preds = %if.then14
|
|
%12 = load i64, ptr %error_var, align 8
|
|
ret i64 %12
|
|
|
|
noerr_block: ; preds = %if.exit15
|
|
%13 = load ptr, ptr %temp, align 8
|
|
store ptr %13, ptr %literal12, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal12, i32 8, i1 false)
|
|
ret i64 0
|
|
|
|
if.exit16: ; preds = %if.exit6
|
|
%lo17 = load ptr, ptr %url, align 8
|
|
%ptradd18 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%hi19 = load i64, ptr %ptradd18, align 8
|
|
%14 = call i8 @test.contains(ptr %lo17, i64 %hi19, ptr @.str.6, i64 11)
|
|
%15 = trunc i8 %14 to i1
|
|
br i1 %15, label %if.then20, label %if.exit40
|
|
|
|
if.then20: ; preds = %if.exit16
|
|
store ptr null, ptr %literal24, align 8
|
|
store %"char[]" zeroinitializer, ptr %value26, align 8
|
|
%16 = call ptr @std.core.mem.malloc(i64 16) #3
|
|
store ptr %16, ptr %temp27, align 8
|
|
%17 = load ptr, ptr %temp27, align 8
|
|
%i2nb28 = icmp eq ptr %17, null
|
|
br i1 %i2nb28, label %if.then29, label %if.exit30
|
|
|
|
if.then29: ; preds = %if.then20
|
|
store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var25, align 8
|
|
br label %guard_block31
|
|
|
|
if.exit30: ; preds = %if.then20
|
|
%18 = load ptr, ptr %temp27, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %18, ptr align 8 %value26, i32 16, i1 false)
|
|
br label %noerr_block32
|
|
|
|
guard_block31: ; preds = %if.then29
|
|
%19 = load i64, ptr %error_var25, align 8
|
|
ret i64 %19
|
|
|
|
noerr_block32: ; preds = %if.exit30
|
|
%20 = load ptr, ptr %temp27, align 8
|
|
store ptr %20, ptr %literal24, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value33, ptr align 8 %literal24, i32 8, i1 false)
|
|
%21 = call ptr @std.core.mem.malloc(i64 8) #3
|
|
store ptr %21, ptr %temp34, align 8
|
|
%22 = load ptr, ptr %temp34, align 8
|
|
%i2nb35 = icmp eq ptr %22, null
|
|
br i1 %i2nb35, label %if.then36, label %if.exit37
|
|
|
|
if.then36: ; preds = %noerr_block32
|
|
store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var23, align 8
|
|
br label %guard_block38
|
|
|
|
if.exit37: ; preds = %noerr_block32
|
|
%23 = load ptr, ptr %temp34, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %23, ptr align 8 %value33, i32 8, i1 false)
|
|
br label %noerr_block39
|
|
|
|
guard_block38: ; preds = %if.then36
|
|
%24 = load i64, ptr %error_var23, align 8
|
|
ret i64 %24
|
|
|
|
noerr_block39: ; preds = %if.exit37
|
|
%25 = load ptr, ptr %temp34, align 8
|
|
store ptr %25, ptr %literal22, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal22, i32 8, i1 false)
|
|
ret i64 0
|
|
|
|
if.exit40: ; preds = %if.exit16
|
|
%ptradd41 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%26 = load i64, ptr %ptradd41, align 8
|
|
%trunc = trunc i64 %26 to i32
|
|
%27 = load ptr, ptr %url, align 8
|
|
%28 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.7, i32 %trunc, ptr %27)
|
|
%sext = sext i32 %28 to i64
|
|
store i64 %sext, ptr %len, align 8
|
|
%29 = load i64, ptr %len, align 8
|
|
%add = add i64 %29, 1
|
|
%30 = call ptr @std.core.mem.malloc(i64 %add) #3
|
|
store ptr %30, ptr %str, align 8
|
|
%31 = load ptr, ptr %str, align 8
|
|
%i2nb42 = icmp eq ptr %31, null
|
|
br i1 %i2nb42, label %if.then43, label %if.exit44
|
|
|
|
if.then43: ; preds = %if.exit40
|
|
ret i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64)
|
|
|
|
if.exit44: ; preds = %if.exit40
|
|
%32 = load i64, ptr %len, align 8
|
|
%add45 = add i64 %32, 1
|
|
%ptradd46 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%33 = load i64, ptr %ptradd46, align 8
|
|
%trunc47 = trunc i64 %33 to i32
|
|
%34 = load ptr, ptr %str, align 8
|
|
%35 = load ptr, ptr %url, align 8
|
|
%36 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %34, i64 %add45, ptr @.str.8, i32 %trunc47, ptr %35)
|
|
store ptr null, ptr %literal51, align 8
|
|
%37 = load ptr, ptr %str, align 8
|
|
%38 = load i64, ptr %len, align 8
|
|
%sub = sub i64 %38, 1
|
|
%39 = add i64 %sub, 1
|
|
%size = sub i64 %39, 0
|
|
%40 = insertvalue %"char[]" undef, ptr %37, 0
|
|
%41 = insertvalue %"char[]" %40, i64 %size, 1
|
|
store %"char[]" %41, ptr %value53, align 8
|
|
%42 = call ptr @std.core.mem.malloc(i64 16) #3
|
|
store ptr %42, ptr %temp54, align 8
|
|
%43 = load ptr, ptr %temp54, align 8
|
|
%i2nb55 = icmp eq ptr %43, null
|
|
br i1 %i2nb55, label %if.then56, label %if.exit57
|
|
|
|
if.then56: ; preds = %if.exit44
|
|
store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var52, align 8
|
|
br label %guard_block58
|
|
|
|
if.exit57: ; preds = %if.exit44
|
|
%44 = load ptr, ptr %temp54, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %44, ptr align 8 %value53, i32 16, i1 false)
|
|
br label %noerr_block59
|
|
|
|
guard_block58: ; preds = %if.then56
|
|
%45 = load i64, ptr %error_var52, align 8
|
|
ret i64 %45
|
|
|
|
noerr_block59: ; preds = %if.exit57
|
|
%46 = load ptr, ptr %temp54, align 8
|
|
store ptr %46, ptr %literal51, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value60, ptr align 8 %literal51, i32 8, i1 false)
|
|
%47 = call ptr @std.core.mem.malloc(i64 8) #3
|
|
store ptr %47, ptr %temp61, align 8
|
|
%48 = load ptr, ptr %temp61, align 8
|
|
%i2nb62 = icmp eq ptr %48, null
|
|
br i1 %i2nb62, label %if.then63, label %if.exit64
|
|
|
|
if.then63: ; preds = %noerr_block59
|
|
store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var50, align 8
|
|
br label %guard_block65
|
|
|
|
if.exit64: ; preds = %noerr_block59
|
|
%49 = load ptr, ptr %temp61, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %49, ptr align 8 %value60, i32 8, i1 false)
|
|
br label %noerr_block66
|
|
|
|
guard_block65: ; preds = %if.then63
|
|
%50 = load i64, ptr %error_var50, align 8
|
|
ret i64 %50
|
|
|
|
noerr_block66: ; preds = %if.exit64
|
|
%51 = load ptr, ptr %temp61, align 8
|
|
store ptr %51, ptr %literal49, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal49, i32 8, i1 false)
|
|
ret i64 0
|
|
}
|
|
|
|
; Function Attrs:
|
|
define { ptr, i8 } @test.buildSummary(ptr %0) #0 {
|
|
entry:
|
|
%doc = alloca %Doc, align 8
|
|
%literal = alloca %Summary, align 8
|
|
store ptr %0, ptr %doc, align 8
|
|
store ptr null, ptr %literal, align 8
|
|
%ptradd = getelementptr inbounds i8, ptr %literal, i64 8
|
|
store i8 0, ptr %ptradd, align 8
|
|
%1 = load ptr, ptr %doc, align 8
|
|
%i2b = icmp ne ptr %1, null
|
|
br i1 %i2b, label %cond.lhs, label %cond.rhs
|
|
|
|
cond.lhs: ; preds = %entry
|
|
%2 = load ptr, ptr %doc, align 8
|
|
%3 = load ptr, ptr %2, align 8
|
|
br label %cond.phi
|
|
|
|
cond.rhs: ; preds = %entry
|
|
br label %cond.phi
|
|
|
|
cond.phi: ; preds = %cond.rhs, %cond.lhs
|
|
%val = phi ptr [ %3, %cond.lhs ], [ null, %cond.rhs ]
|
|
store ptr %val, ptr %literal, align 8
|
|
%ptradd1 = getelementptr inbounds i8, ptr %literal, i64 8
|
|
store i8 1, ptr %ptradd1, align 8
|
|
%4 = load { ptr, i8 }, ptr %literal, align 8
|
|
ret { ptr, i8 } %4
|
|
}
|
|
|
|
; Function Attrs:
|
|
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
|
|
store ptr %0, ptr %url, align 8
|
|
%ptradd = getelementptr inbounds i8, ptr %url, i64 8
|
|
store i64 %1, ptr %ptradd, align 8
|
|
%lo = load ptr, ptr %url, align 8
|
|
%ptradd1 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%hi = load i64, ptr %ptradd1, align 8
|
|
%2 = call i64 @test.readDoc(ptr %retparam, ptr %lo, i64 %hi)
|
|
%not_err = icmp eq i64 %2, 0
|
|
%3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
|
br i1 %3, label %after_check, label %else_block
|
|
|
|
after_check: ; preds = %entry
|
|
%4 = load ptr, ptr %retparam, align 8
|
|
%5 = call { ptr, i8 } @test.buildSummary(ptr %4)
|
|
store { ptr, i8 } %5, ptr %result, align 8
|
|
br label %phi_block
|
|
|
|
else_block: ; preds = %entry
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.9, i32 16, i1 false)
|
|
br label %phi_block
|
|
|
|
phi_block: ; preds = %else_block, %after_check
|
|
%val = phi ptr [ %result, %after_check ], [ %literal, %else_block ]
|
|
%6 = load { ptr, i8 }, ptr %val, align 8
|
|
ret { ptr, i8 } %6
|
|
}
|
|
|
|
; Function Attrs:
|
|
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
|
|
store ptr %1, ptr %doc, align 8
|
|
%2 = load ptr, ptr %doc, align 8
|
|
%i2nb = icmp eq ptr %2, null
|
|
br i1 %i2nb, label %if.then, label %if.exit
|
|
|
|
if.then: ; preds = %entry
|
|
ret i64 ptrtoint (ptr @"test.TitleResult$TITLE_MISSING" to i64)
|
|
|
|
if.exit: ; preds = %entry
|
|
%3 = load ptr, ptr %doc, align 8
|
|
%4 = load ptr, ptr %3, align 8
|
|
store ptr %4, ptr %head, align 8
|
|
%5 = load ptr, ptr %head, align 8
|
|
%i2nb1 = icmp eq ptr %5, null
|
|
br i1 %i2nb1, 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
|
|
%6 = load ptr, ptr %head, align 8
|
|
%ptradd = getelementptr inbounds i8, ptr %6, i64 8
|
|
%7 = load i64, ptr %ptradd, align 8
|
|
%lt = icmp ult i64 0, %7
|
|
%8 = zext i1 %lt to i8
|
|
store i8 %8, ptr %0, align 1
|
|
ret i64 0
|
|
}
|
|
|
|
; Function Attrs:
|
|
define i64 @test.readWhetherTitleNonEmpty(ptr %0, ptr %1, i64 %2) #0 {
|
|
entry:
|
|
%url = alloca %"char[]", align 8
|
|
%reterr = alloca i64, align 8
|
|
%retparam = alloca %Doc, align 8
|
|
%retparam2 = alloca i8, align 1
|
|
store ptr %1, ptr %url, align 8
|
|
%ptradd = getelementptr inbounds i8, ptr %url, i64 8
|
|
store i64 %2, ptr %ptradd, align 8
|
|
%lo = load ptr, ptr %url, align 8
|
|
%ptradd1 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%hi = load i64, ptr %ptradd1, align 8
|
|
%3 = call i64 @test.readDoc(ptr %retparam, ptr %lo, i64 %hi)
|
|
%not_err = icmp eq i64 %3, 0
|
|
%4 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
|
br i1 %4, label %after_check, label %assign_optional
|
|
|
|
assign_optional: ; preds = %entry
|
|
store i64 %3, ptr %reterr, align 8
|
|
br label %err_retblock
|
|
|
|
after_check: ; preds = %entry
|
|
%5 = load ptr, ptr %retparam, align 8
|
|
%6 = call i64 @test.isTitleNonEmpty(ptr %retparam2, ptr %5)
|
|
%not_err3 = icmp eq i64 %6, 0
|
|
%7 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true)
|
|
br i1 %7, label %after_check5, label %assign_optional4
|
|
|
|
assign_optional4: ; preds = %after_check
|
|
store i64 %6, ptr %reterr, align 8
|
|
br label %err_retblock
|
|
|
|
after_check5: ; preds = %after_check
|
|
%8 = load i8, ptr %retparam2, align 1
|
|
store i8 %8, ptr %0, align 1
|
|
ret i64 0
|
|
|
|
err_retblock: ; preds = %assign_optional4, %assign_optional
|
|
%9 = load i64, ptr %reterr, align 8
|
|
ret i64 %9
|
|
}
|
|
|
|
; Function Attrs:
|
|
define ptr @test.bool_to_string(i8 zeroext %0) #0 {
|
|
entry:
|
|
%1 = trunc i8 %0 to i1
|
|
%ternary = select i1 %1, ptr @.str.10, ptr @.str.11
|
|
ret ptr %ternary
|
|
}
|
|
|
|
; Function Attrs:
|
|
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.12
|
|
|
|
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.13
|
|
|
|
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.14
|
|
|
|
next_if6: ; preds = %next_if3
|
|
br label %switch.default
|
|
|
|
switch.default: ; preds = %next_if6
|
|
ret ptr @.str.15
|
|
}
|
|
|
|
; Function Attrs:
|
|
define void @test.main() #0 {
|
|
entry:
|
|
%.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
|
|
%blockret = alloca i64, align 8
|
|
%f = alloca i64, align 8
|
|
%0 = load i64, ptr getelementptr inbounds (i8, ptr @main.URLS, i64 8), align 8
|
|
store i64 %0, ptr %.anon, align 8
|
|
store i64 0, ptr %.anon1, align 8
|
|
br label %loop.cond
|
|
|
|
loop.cond:
|
|
%1 = load i64, ptr %.anon1, align 8
|
|
%2 = load i64, ptr %.anon, align 8
|
|
%lt = icmp ult i64 %1, %2
|
|
br i1 %lt, label %loop.body, label %loop.exit
|
|
|
|
loop.body: ; preds = %loop.cond
|
|
%3 = load ptr, ptr @main.URLS, align 8
|
|
%4 = load i64, ptr %.anon1, align 8
|
|
%ptroffset = getelementptr inbounds [16 x i8], ptr %3, i64 %4
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %url, ptr align 8 %ptroffset, i32 16, i1 false)
|
|
%ptradd = getelementptr inbounds i8, ptr %url, i64 8
|
|
%5 = load i64, ptr %ptradd, align 8
|
|
%trunc = trunc i64 %5 to i32
|
|
%6 = load ptr, ptr %url, align 8
|
|
%7 = call i32 (ptr, ...) @printf(ptr @.str.21, i32 %trunc, ptr %6)
|
|
%lo = load ptr, ptr %url, align 8
|
|
%ptradd2 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%hi = load i64, ptr %ptradd2, align 8
|
|
%8 = call { ptr, i8 } @test.readAndBuildSummary(ptr %lo, i64 %hi)
|
|
store { ptr, i8 } %8, ptr %result, align 8
|
|
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %summary, ptr align 8 %result, i32 16, i1 false)
|
|
%9 = call i32 (ptr, ...) @printf(ptr @.str.22)
|
|
%10 = load ptr, ptr @__stdoutp, align 8
|
|
call void @test.Summary.print(ptr %summary, ptr %10)
|
|
%11 = call i32 (ptr, ...) @printf(ptr @.str.23)
|
|
%12 = load ptr, ptr %summary, align 8
|
|
%i2b = icmp ne ptr %12, null
|
|
br i1 %i2b, label %cond.lhs, label %cond.rhs
|
|
|
|
cond.lhs: ; preds = %loop.body
|
|
%13 = load ptr, ptr %summary, align 8
|
|
%14 = load %"char[]", ptr %13, 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[]" [ %14, %cond.lhs ], [ zeroinitializer, %cond.rhs ]
|
|
store %"char[]" %val, ptr %title_sure, align 8
|
|
%ptradd3 = getelementptr inbounds i8, ptr %title_sure, i64 8
|
|
%15 = load i64, ptr %ptradd3, align 8
|
|
%trunc4 = trunc i64 %15 to i32
|
|
%16 = load ptr, ptr %title_sure, align 8
|
|
%17 = call i32 (ptr, ...) @printf(ptr @.str.24, i32 %trunc4, ptr %16)
|
|
%lo5 = load ptr, ptr %url, align 8
|
|
%ptradd6 = getelementptr inbounds i8, ptr %url, i64 8
|
|
%hi7 = load i64, ptr %ptradd6, align 8
|
|
%18 = call i64 @test.readWhetherTitleNonEmpty(ptr %retparam, ptr %lo5, i64 %hi7)
|
|
%not_err = icmp eq i64 %18, 0
|
|
%19 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
|
br i1 %19, label %after_check, label %assign_optional
|
|
|
|
assign_optional: ; preds = %cond.phi
|
|
store i64 %18, ptr %has_title.f, align 8
|
|
br label %after_assign
|
|
|
|
after_check: ; preds = %cond.phi
|
|
%20 = load i8, ptr %retparam, align 1
|
|
store i8 %20, 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_err8 = icmp eq i64 %optval, 0
|
|
%21 = call i1 @llvm.expect.i1(i1 %not_err8, i1 true)
|
|
br i1 %21, label %after_check9, label %else_block
|
|
|
|
after_check9: ; preds = %after_assign
|
|
%22 = load i8, ptr %has_title, align 1
|
|
%23 = call ptr @test.bool_to_string(i8 zeroext %22)
|
|
br label %phi_block
|
|
|
|
else_block: ; preds = %after_assign
|
|
br label %testblock
|
|
|
|
testblock: ; preds = %else_block
|
|
%optval10 = load i64, ptr %has_title.f, align 8
|
|
%not_err11 = icmp eq i64 %optval10, 0
|
|
%24 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true)
|
|
br i1 %24, label %after_check13, label %assign_optional12
|
|
|
|
assign_optional12: ; preds = %testblock
|
|
store i64 %optval10, ptr %f, align 8
|
|
br label %end_block
|
|
|
|
after_check13: ; preds = %testblock
|
|
store i64 0, ptr %f, align 8
|
|
br label %end_block
|
|
|
|
end_block: ; preds = %after_check13, %assign_optional12
|
|
%25 = load i64, ptr %f, align 8
|
|
%i2b14 = icmp ne i64 %25, 0
|
|
br i1 %i2b14, label %if.then, label %if.exit
|
|
|
|
if.then: ; preds = %end_block
|
|
%26 = load i64, ptr %f, align 8
|
|
store i64 %26, ptr %blockret, align 8
|
|
br label %expr_block.exit
|
|
|
|
if.exit: ; preds = %end_block
|
|
store i64 0, ptr %blockret, align 8
|
|
br label %expr_block.exit
|
|
|
|
expr_block.exit: ; preds = %if.exit, %if.then
|
|
%27 = load i64, ptr %blockret, align 8
|
|
%28 = call ptr @test.nameFromError(i64 %27)
|
|
br label %phi_block
|
|
|
|
phi_block: ; preds = %expr_block.exit, %after_check9
|
|
%val15 = phi ptr [ %23, %after_check9 ], [ %28, %expr_block.exit ]
|
|
%optval16 = load i64, ptr %has_title.f, align 8
|
|
%not_err17 = icmp eq i64 %optval16, 0
|
|
%29 = call i1 @llvm.expect.i1(i1 %not_err17, i1 true)
|
|
br i1 %29, label %after_check18, label %else_block19
|
|
|
|
after_check18: ; preds = %phi_block
|
|
%30 = load i8, ptr %has_title, align 1
|
|
%31 = trunc i8 %30 to i1
|
|
br label %phi_block20
|
|
|
|
else_block19: ; preds = %phi_block
|
|
br label %phi_block20
|
|
|
|
phi_block20: ; preds = %else_block19, %after_check18
|
|
%val21 = phi i1 [ %31, %after_check18 ], [ false, %else_block19 ]
|
|
%ternary = select i1 %val21, ptr @.str.26, ptr @.str.27
|
|
%32 = call i32 (ptr, ...) @printf(ptr @.str.25, ptr %val15, ptr %ternary)
|
|
%33 = load i64, ptr %.anon1, align 8
|
|
%addnuw = add nuw i64 %33, 1
|
|
store i64 %addnuw, ptr %.anon1, align 8
|
|
br label %loop.cond
|
|
|
|
loop.exit: ; preds = %loop.cond
|
|
ret void
|
|
}
|