mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Auto-import std::core. Fix module assignment of declarations. Introspection improvements. Deref null error panics in safe mode. Support for LLVM 15
This commit is contained in:
committed by
Christoffer Lerno
parent
df41caabdd
commit
b1d83e2ccd
8
.github/workflows/main.yml
vendored
8
.github/workflows/main.yml
vendored
@@ -159,7 +159,11 @@ jobs:
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
cd test
|
||||
python3 src/tester.py ../build/c3c test_suite/
|
||||
if [[ "${{matrix.llvm_version}}" < 15 ]]; then
|
||||
python3 src/tester.py ../build/c3c test_suite/
|
||||
else
|
||||
python3 src/tester.py ../build/c3c test_suite2/
|
||||
fi
|
||||
|
||||
build-mac:
|
||||
runs-on: macos-latest
|
||||
@@ -168,7 +172,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
llvm_version: [12, 13]
|
||||
llvm_version: [12, 13, 14]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Download LLVM
|
||||
|
||||
@@ -8,9 +8,14 @@ set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-3 -O3")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gdwarf-3")
|
||||
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1 -fsanitize=undefined")
|
||||
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O1 -fsanitize=undefined")
|
||||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-3 -O3 -fsanitize=undefined")
|
||||
#set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gdwarf-3 -fsanitize=undefined")
|
||||
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")
|
||||
|
||||
option(C3_USE_TB "Enable TB" OFF)
|
||||
set(C3_LLVM_VERSION "auto" CACHE STRING "Use LLVM version [default: auto]")
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::array;
|
||||
import std::mem;
|
||||
|
||||
/**
|
||||
* @require elements > 0
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::builtin;
|
||||
module std::core::builtin;
|
||||
import libc;
|
||||
|
||||
fault IteratorResult
|
||||
{
|
||||
NO_MORE_ELEMENT
|
||||
}
|
||||
|
||||
fault VarCastResult
|
||||
{
|
||||
TYPE_MISMATCH
|
||||
@@ -76,6 +81,29 @@ macro unreachable($string = "Unreachable statement reached.") @autoimport @noret
|
||||
$$unreachable();
|
||||
}
|
||||
|
||||
enum TypeKind : char
|
||||
{
|
||||
VOID, // 0
|
||||
BOOL, // 1
|
||||
FLOAT, // 2
|
||||
INTEGER,// 3
|
||||
STRUCT, // 4
|
||||
UNION, // 5
|
||||
ENUM, // 6
|
||||
FAULT, // 7
|
||||
ARRAY,
|
||||
POINTER,
|
||||
VAR_ARRAY,
|
||||
SUBARRAY,
|
||||
OPAQUE
|
||||
// ALIAS,
|
||||
}
|
||||
|
||||
struct TypeEnum
|
||||
{
|
||||
TypeKind type;
|
||||
usize elements;
|
||||
}
|
||||
/*
|
||||
enum TypeKind
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::cinterop;
|
||||
module std::core::cinterop;
|
||||
|
||||
const C_INT_SIZE = $$C_INT_SIZE;
|
||||
const C_LONG_SIZE = $$C_LONG_SIZE;
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::env;
|
||||
module std::core::env;
|
||||
|
||||
enum CompilerOptLevel
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::mem;
|
||||
module std::core::mem;
|
||||
|
||||
macro @volatile_load(&x)
|
||||
{
|
||||
@@ -77,6 +77,11 @@ fault AllocationFailure
|
||||
|
||||
private tlocal Allocator thread_allocator = { null, SYSTEM_ALLOCATOR };
|
||||
|
||||
macro Allocator current_allocator()
|
||||
{
|
||||
return thread_allocator;
|
||||
}
|
||||
|
||||
struct Allocator
|
||||
{
|
||||
void* data;
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::mem;
|
||||
module std::core::mem;
|
||||
|
||||
define AllocatorFunction = fn void*!(void* alloc_data, usize new_size, usize alignment, void* old_pointer, AllocationKind kind);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::mem;
|
||||
module std::core::mem;
|
||||
import libc;
|
||||
|
||||
private fn void*! null_allocator_fn(void *data, usize bytes, usize alignment, void* old_pointer, AllocationKind kind)
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::mem;
|
||||
module std::core::mem;
|
||||
|
||||
const TEMP_BLOCK_SIZE = 1024;
|
||||
const TEMP_PAGES = 64;
|
||||
@@ -1,5 +1,4 @@
|
||||
module std::os::linux;
|
||||
import std::env;
|
||||
module std::core::os::linux;
|
||||
|
||||
$if (env::OS_TYPE == OsType.LINUX):
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
module std::os::macos;
|
||||
import std::env;
|
||||
|
||||
module std::core::os::macos;
|
||||
$if (env::OS_TYPE == OsType.MACOSX):
|
||||
|
||||
extern fn int* __error();
|
||||
@@ -1,5 +1,4 @@
|
||||
module std::os::windows;
|
||||
import std::env;
|
||||
module std::core::os::windows;
|
||||
|
||||
$if (env::OS_TYPE == OsType.WIN32):
|
||||
|
||||
166
lib/std/core/str.c3
Normal file
166
lib/std/core/str.c3
Normal file
@@ -0,0 +1,166 @@
|
||||
module std::core::str;
|
||||
|
||||
|
||||
define ZString = distinct char*;
|
||||
define Char32 = uint;
|
||||
|
||||
fn String join(char[][] s, char[] joiner)
|
||||
{
|
||||
if (!s.len) return (String)null;
|
||||
usize total_size = joiner.len * s.len;
|
||||
foreach (char[]* &str : s)
|
||||
{
|
||||
total_size += str.len;
|
||||
}
|
||||
String res = string::new_with_capacity(total_size);
|
||||
res.append(s[0]);
|
||||
foreach (char[]* &str : s[1..])
|
||||
{
|
||||
res.append(joiner);
|
||||
res.append(*str);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
fn ZString copy_zstring(char[] s)
|
||||
{
|
||||
usize len = s.len;
|
||||
char* str = mem::alloc(len + 1);
|
||||
mem::copy(str, s.ptr, len);
|
||||
str[len] = 0;
|
||||
return (ZString)str;
|
||||
}
|
||||
|
||||
fn ZString tcopy_zstring(char[] s)
|
||||
{
|
||||
usize len = s.len;
|
||||
char* str = mem::talloc(len + 1)!!;
|
||||
mem::copy(str, s.ptr, len);
|
||||
str[len] = 0;
|
||||
return (ZString)str;
|
||||
}
|
||||
|
||||
fault UnicodeResult
|
||||
{
|
||||
INVALID_UTF8
|
||||
}
|
||||
|
||||
fn Char32! utf8CharTo32(char* ptr, int* size)
|
||||
{
|
||||
int max_size = *size;
|
||||
if (max_size < 1) return UnicodeResult.INVALID_UTF8!;
|
||||
char c = (ptr++)[0];
|
||||
|
||||
if ((c & 0x80) == 0)
|
||||
{
|
||||
*size = 1;
|
||||
return c;
|
||||
}
|
||||
if ((c & 0xE0) == 0xC0)
|
||||
{
|
||||
if (max_size < 2) return UnicodeResult.INVALID_UTF8!;
|
||||
*size = 2;
|
||||
Char32 uc = (c & 0x1F) << 6;
|
||||
c = *ptr;
|
||||
if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!;
|
||||
return uc + c & 0x3F;
|
||||
}
|
||||
if ((c & 0xF0) == 0xE0)
|
||||
{
|
||||
if (max_size < 3) return UnicodeResult.INVALID_UTF8!;
|
||||
*size = 3;
|
||||
Char32 uc = (c & 0x0F) << 12;
|
||||
c = ptr++[0];
|
||||
if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!;
|
||||
uc += (c & 0x3F) << 6;
|
||||
c = ptr++[0];
|
||||
if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!;
|
||||
return uc + c & 0x3F;
|
||||
}
|
||||
if (max_size < 4) return UnicodeResult.INVALID_UTF8!;
|
||||
*size = 4;
|
||||
Char32 uc = (c & 0x07) << 18;
|
||||
c = ptr++[0];
|
||||
if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!;
|
||||
uc += (c & 0x3F) << 12;
|
||||
c = ptr++[0];
|
||||
if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!;
|
||||
uc += (c & 0x3F) << 6;
|
||||
c = ptr++[0];
|
||||
if (c & 0xC0 != 0x80) return UnicodeResult.INVALID_UTF8!;
|
||||
return uc + c & 0x3F;
|
||||
}
|
||||
|
||||
fn usize utf8_codepoints(char[] utf8)
|
||||
{
|
||||
usize len = 0;
|
||||
foreach (char c : utf8)
|
||||
{
|
||||
if (c & 0xC0 != 0x80) len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
fn Char32[]! utf8to32(char[] utf8, Allocator allocator = { null, null })
|
||||
{
|
||||
if (!allocator.function) allocator = mem::current_allocator();
|
||||
usize len = utf8.len;
|
||||
Char32* data = allocator.alloc((len + 1) * Char32.sizeof)?;
|
||||
usize len32 = 0;
|
||||
for (usize i = 0; i < len;)
|
||||
{
|
||||
int width = (int)min(len - i, 4);
|
||||
Char32 uc = utf8CharTo32(&utf8[i], &width) @inline?;
|
||||
i += width;
|
||||
data[len32++] = uc;
|
||||
}
|
||||
return data[0 .. len32 - 1];
|
||||
}
|
||||
|
||||
fn char[] copy(char[] s)
|
||||
{
|
||||
usize len = s.len;
|
||||
ZString str_copy = copy_zstring(s) @inline;
|
||||
return str_copy[..len];
|
||||
}
|
||||
|
||||
fn char[] tcopy(char[] s)
|
||||
{
|
||||
usize len = s.len;
|
||||
ZString str_copy = tcopy_zstring(s) @inline;
|
||||
return str_copy[..len];
|
||||
}
|
||||
|
||||
fn char[] tconcat(char[] s1, char[] s2)
|
||||
{
|
||||
usize full_len = s1.len + s2.len;
|
||||
char* str = mem::talloc(full_len + 1)!!;
|
||||
usize s1_len = s1.len;
|
||||
mem::copy(str, s1.ptr, s1_len);
|
||||
mem::copy(str + s1_len, s2.ptr, s2.len);
|
||||
str[full_len] = 0;
|
||||
return str[..full_len];
|
||||
}
|
||||
|
||||
fn char[] concat(char[] s1, char[] s2)
|
||||
{
|
||||
usize full_len = s1.len + s2.len;
|
||||
char* str = mem::alloc(full_len + 1);
|
||||
usize s1_len = s1.len;
|
||||
mem::copy(str, s1.ptr, s1_len);
|
||||
mem::copy(str + s1_len, s2.ptr, s2.len);
|
||||
str[full_len] = 0;
|
||||
return str[..full_len];
|
||||
}
|
||||
|
||||
fn usize ZString.len(ZString *str)
|
||||
{
|
||||
usize len = 0;
|
||||
char* ptr = (char*)*str;
|
||||
while (char c = ptr++[0])
|
||||
{
|
||||
if (c & 0xC0 != 0x80) len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
255
lib/std/core/string.c3
Normal file
255
lib/std/core/string.c3
Normal file
@@ -0,0 +1,255 @@
|
||||
module std::core::string;
|
||||
import libc;
|
||||
|
||||
define String = distinct void*;
|
||||
|
||||
private struct StringData
|
||||
{
|
||||
Allocator allocator;
|
||||
usize len;
|
||||
usize capacity;
|
||||
char[*] chars;
|
||||
}
|
||||
|
||||
const usize MIN_CAPACITY = 16;
|
||||
|
||||
fn String new_with_capacity(usize capacity, Allocator allocator = { null, null })
|
||||
{
|
||||
if (capacity < MIN_CAPACITY) capacity = MIN_CAPACITY;
|
||||
if (!allocator.function)
|
||||
{
|
||||
allocator = mem::current_allocator();
|
||||
}
|
||||
assert(allocator.function, "Expected an allocator to be present.");
|
||||
StringData* data = allocator.alloc(StringData.sizeof + capacity)!!;
|
||||
data.allocator = allocator;
|
||||
data.len = 0;
|
||||
data.capacity = capacity;
|
||||
return (String)data;
|
||||
}
|
||||
|
||||
fn String new(char[] c)
|
||||
{
|
||||
usize len = c.len;
|
||||
String str = new_with_capacity(len);
|
||||
StringData* data = str.data();
|
||||
if (len)
|
||||
{
|
||||
data.len = len;
|
||||
mem::copy(&data.chars, c.ptr, len);
|
||||
}
|
||||
return (String)data;
|
||||
}
|
||||
|
||||
fn ZString String.zstr(String* str)
|
||||
{
|
||||
StringData* data = str.data();
|
||||
if (!str) return (ZString)"";
|
||||
if (data.capacity == data.len)
|
||||
{
|
||||
libc::printf("feofk\n");
|
||||
str.reserve(1);
|
||||
data.chars[data.len] = 0;
|
||||
}
|
||||
else if (data.chars[data.len] != 0)
|
||||
{
|
||||
data.chars[data.len] = 0;
|
||||
}
|
||||
return (ZString)&data.chars[0];
|
||||
}
|
||||
|
||||
fn usize String.len(String* this)
|
||||
{
|
||||
if (!*this) return 0;
|
||||
return this.data().len;
|
||||
}
|
||||
/**
|
||||
* @require new_size <= this.len()
|
||||
*/
|
||||
fn void String.chop(String* this, usize new_size)
|
||||
{
|
||||
if (!*this) return;
|
||||
this.data().len = new_size;
|
||||
}
|
||||
|
||||
fn char[] String.str(String* str)
|
||||
{
|
||||
StringData* data = (StringData*)*str;
|
||||
return data.chars[0..data.len - 1];
|
||||
}
|
||||
|
||||
fn void String.append_utf32(String* str, Char32[] chars)
|
||||
{
|
||||
str.reserve(chars.len);
|
||||
foreach (Char32 c : chars)
|
||||
{
|
||||
str.append_char32(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @require c < 0x10ffff
|
||||
*/
|
||||
fn void String.append_char32(String* str, Char32 c)
|
||||
{
|
||||
if (c < 0x7f)
|
||||
{
|
||||
str.reserve(1);
|
||||
StringData* data = str.data();
|
||||
data.chars[data.len++] = (char)c;
|
||||
return;
|
||||
}
|
||||
if (c < 0x7ff)
|
||||
{
|
||||
str.reserve(2);
|
||||
StringData* data = str.data();
|
||||
data.chars[data.len++] = (char)(0xC0 | c >> 6);
|
||||
data.chars[data.len++] = (char)(0x80 | (c & 0x3F));
|
||||
return;
|
||||
}
|
||||
if (c < 0xffff)
|
||||
{
|
||||
str.reserve(3);
|
||||
StringData* data = str.data();
|
||||
data.chars[data.len++] = (char)(0xE0 | c >> 12);
|
||||
data.chars[data.len++] = (char)(0x80 | (c >> 6 & 0x3F));
|
||||
data.chars[data.len++] = (char)(0x80 | (c & 0x3F));
|
||||
return;
|
||||
}
|
||||
str.reserve(4);
|
||||
StringData* data = str.data();
|
||||
data.chars[data.len++] = (char)(0xF0 | c >> 18);
|
||||
data.chars[data.len++] = (char)(0x80 | (c >> 12 & 0x3F));
|
||||
data.chars[data.len++] = (char)(0x80 | (c >> 6 & 0x3F));
|
||||
data.chars[data.len++] = (char)(0x80 | (c & 0x3F));
|
||||
}
|
||||
|
||||
fn String String.copy(String* str, Allocator allocator = { null, null })
|
||||
{
|
||||
if (!*str)
|
||||
{
|
||||
if (allocator.function) return new_with_capacity(0, allocator);
|
||||
return (String)null;
|
||||
}
|
||||
if (!allocator.function) allocator = mem::current_allocator();
|
||||
StringData* data = str.data();
|
||||
String new_string = new_with_capacity(data.capacity, allocator);
|
||||
mem::copy((char*)new_string.data(), (char*)data, StringData.sizeof + data.len);
|
||||
return new_string;
|
||||
}
|
||||
|
||||
fn ZString String.copy_zstr(String* str, Allocator allocator = { null, null })
|
||||
{
|
||||
usize str_len = str.len();
|
||||
if (!str_len)
|
||||
{
|
||||
if (allocator.function) return (ZString)allocator.calloc(1, 1)!!;
|
||||
return (ZString)mem::calloc(1, 1);
|
||||
}
|
||||
if (!allocator.function) allocator = mem::current_allocator();
|
||||
char* zstr = allocator.alloc(str_len + 1)!!;
|
||||
StringData* data = str.data();
|
||||
mem::copy(zstr, &data.chars, str_len);
|
||||
zstr[str_len] = 0;
|
||||
return (ZString)zstr;
|
||||
}
|
||||
|
||||
fn bool String.equals(String* str, String other_string)
|
||||
{
|
||||
StringData *str1 = str.data();
|
||||
StringData *str2 = other_string.data();
|
||||
if (str1 == str2) return true;
|
||||
if (!str1) return str2.len == 0;
|
||||
if (!str2) return str1.len == 0;
|
||||
usize str1_len = str1.len;
|
||||
if (str1_len != str2.len) return false;
|
||||
for (int i = 0; i < str1_len; i++)
|
||||
{
|
||||
if (str1.chars[i] != str2.chars[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn void String.destroy(String* str)
|
||||
{
|
||||
if (!*str) return;
|
||||
StringData* data = str.data();
|
||||
data.allocator.free(data);
|
||||
*str = (String)null;
|
||||
}
|
||||
|
||||
fn bool String.less_than(String* str, String other_string)
|
||||
{
|
||||
StringData* str1 = str.data();
|
||||
StringData* str2 = other_string.data();
|
||||
if (str1 == str2) return false;
|
||||
if (!str1) return str2.len != 0;
|
||||
if (!str2) return str1.len == 0;
|
||||
usize str1_len = str1.len;
|
||||
usize str2_len = str2.len;
|
||||
if (str1_len != str2_len) return str1_len < str2_len;
|
||||
for (int i = 0; i < str1_len; i++)
|
||||
{
|
||||
if (str1.chars[i] >= str2.chars[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn void String.append(String* this, char[] str)
|
||||
{
|
||||
usize other_len = str.len;
|
||||
if (!other_len) return;
|
||||
if (!*this)
|
||||
{
|
||||
*this = new(str);
|
||||
return;
|
||||
}
|
||||
this.reserve(other_len);
|
||||
StringData* data = (StringData*)*this;
|
||||
mem::copy(&data.chars[data.len], str.ptr, other_len);
|
||||
data.len += other_len;
|
||||
}
|
||||
|
||||
fn Char32[] String.copy_utf32(String* this, Allocator allocator = { null, null })
|
||||
{
|
||||
return str::utf8to32(this.str(), allocator) @inline!!;
|
||||
}
|
||||
|
||||
fn void String.append_string(String* this, String str)
|
||||
{
|
||||
StringData* other = (StringData*)str;
|
||||
if (!other) return;
|
||||
this.append(str.str());
|
||||
}
|
||||
|
||||
fn void String.append_char(String* str, char c)
|
||||
{
|
||||
if (!*str)
|
||||
{
|
||||
*str = new_with_capacity(MIN_CAPACITY);
|
||||
}
|
||||
str.reserve(1);
|
||||
StringData* data = (StringData*)*str;
|
||||
data.chars[data.len++] = c;
|
||||
}
|
||||
|
||||
private fn StringData* String.data(String* str) @inline
|
||||
{
|
||||
return (StringData*)*str;
|
||||
}
|
||||
|
||||
|
||||
private fn void String.reserve(String* str, usize addition)
|
||||
{
|
||||
StringData* data = str.data();
|
||||
if (!data)
|
||||
{
|
||||
*str = string::new_with_capacity(addition);
|
||||
return;
|
||||
}
|
||||
usize len = data.len + addition;
|
||||
if (data.capacity >= len) return;
|
||||
usize new_capacity = data.capacity * 2;
|
||||
if (new_capacity < MIN_CAPACITY) new_capacity = MIN_CAPACITY;
|
||||
*str = (String)data.allocator.realloc(data, StringData.sizeof + new_capacity)!!;
|
||||
}
|
||||
25
lib/std/core/string_iterator.c3
Normal file
25
lib/std/core/string_iterator.c3
Normal file
@@ -0,0 +1,25 @@
|
||||
module std::core::string::iterator;
|
||||
|
||||
|
||||
|
||||
struct StringIterator
|
||||
{
|
||||
char[] utf8;
|
||||
usize current;
|
||||
}
|
||||
|
||||
fn void StringIterator.reset(StringIterator* this)
|
||||
{
|
||||
this.current = 0;
|
||||
}
|
||||
|
||||
fn Char32! StringIterator.next(StringIterator* this)
|
||||
{
|
||||
usize len = this.utf8.len;
|
||||
usize current = this.current;
|
||||
if (current >= len) return IteratorResult.NO_MORE_ELEMENT!;
|
||||
int read = (int)(len - current < 4 ? len - current : 4);
|
||||
Char32 res = str::utf8CharTo32(&this.utf8[current], &read)?;
|
||||
this.current += read;
|
||||
return res;
|
||||
}
|
||||
@@ -2,9 +2,7 @@
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::io;
|
||||
import std::mem;
|
||||
import libc;
|
||||
import std::env;
|
||||
|
||||
struct File
|
||||
{
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module libc;
|
||||
import std::cinterop;
|
||||
import std::env;
|
||||
import std::os::linux;
|
||||
import std::os::macos;
|
||||
import std::os::windows;
|
||||
// stdlib
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::array::linkedlist<Type>;
|
||||
import std::mem;
|
||||
|
||||
private struct Node
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::array::list<Type>;
|
||||
import std::mem;
|
||||
|
||||
struct List
|
||||
{
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
module std::str;
|
||||
import std::mem;
|
||||
|
||||
define ZString = char*;
|
||||
define String = char[];
|
||||
|
||||
fn ZString copy_zstring(String s)
|
||||
{
|
||||
usize len = s.len;
|
||||
char* str = mem::alloc(len + 1);
|
||||
mem::copy(str, s.ptr, len);
|
||||
str[len] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
fn ZString tcopy_zstring(String s)
|
||||
{
|
||||
usize len = s.len;
|
||||
char* str = mem::talloc(len + 1)!!;
|
||||
mem::copy(str, s.ptr, len);
|
||||
str[len] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
fn String copy(String s)
|
||||
{
|
||||
usize len = s.len;
|
||||
ZString str_copy = copy_zstring(s) @inline;
|
||||
return str_copy[..len];
|
||||
}
|
||||
|
||||
fn String tcopy(String s)
|
||||
{
|
||||
usize len = s.len;
|
||||
ZString str_copy = tcopy_zstring(s) @inline;
|
||||
return str_copy[..len];
|
||||
}
|
||||
|
||||
fn String tconcat(String s1, String s2)
|
||||
{
|
||||
usize full_len = s1.len + s2.len;
|
||||
char* str = mem::talloc(full_len + 1)!!;
|
||||
usize s1_len = s1.len;
|
||||
mem::copy(str, s1.ptr, s1_len);
|
||||
mem::copy(str + s1_len, s2.ptr, s2.len);
|
||||
str[full_len] = 0;
|
||||
return str[..full_len];
|
||||
}
|
||||
|
||||
fn String concat(String s1, String s2)
|
||||
{
|
||||
usize full_len = s1.len + s2.len;
|
||||
char* str = mem::alloc(full_len + 1);
|
||||
usize s1_len = s1.len;
|
||||
mem::copy(str, s1.ptr, s1_len);
|
||||
mem::copy(str + s1_len, s2.ptr, s2.len);
|
||||
str[full_len] = 0;
|
||||
return str[..full_len];
|
||||
}
|
||||
@@ -91,6 +91,9 @@ static void usage(void)
|
||||
OUTPUT(" -O2 - Default optimization level.");
|
||||
OUTPUT(" -Os - Optimize for size.");
|
||||
OUTPUT(" -O3 - Aggressive optimization.");
|
||||
OUTPUT(" --build-dir <dir> - Override build output directory.");
|
||||
OUTPUT(" --obj-out <dir> - Override object file output directory.");
|
||||
OUTPUT(" --llvm-out <dir> - Override llvm output directory for '--emit-llvm'.");
|
||||
OUTPUT(" --emit-llvm - Emit LLVM IR as a .ll file per module.");
|
||||
OUTPUT(" --target <target> - Compile for a particular architecture + OS target.");
|
||||
OUTPUT(" --threads <number> - Set the number of threads to use for compilation.");
|
||||
@@ -612,6 +615,24 @@ static void parse_option(BuildOptions *options)
|
||||
options->win.crt_linking = (WinCrtLinking)parse_multi_option(argopt, 3, wincrt_linking);
|
||||
return;
|
||||
}
|
||||
if (match_longopt("build-dir"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --build-dir needs a directory.");
|
||||
options->build_dir = next_arg();
|
||||
return;
|
||||
}
|
||||
if (match_longopt("obj-out"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --obj-out needs a directory.");
|
||||
options->obj_out = next_arg();
|
||||
return;
|
||||
}
|
||||
if (match_longopt("llvm-out"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --llvm-out needs a directory.");
|
||||
options->llvm_out = next_arg();
|
||||
return;
|
||||
}
|
||||
if (match_longopt("lib"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --lib needs a name.");
|
||||
@@ -691,7 +712,9 @@ BuildOptions parse_arguments(int argc, const char *argv[])
|
||||
.backend = BACKEND_LLVM,
|
||||
.x86_vector_capability = X86VECTOR_DEFAULT,
|
||||
.win.crt_linking = WIN_CRT_DEFAULT,
|
||||
.files = NULL
|
||||
.files = NULL,
|
||||
.build_dir = NULL,
|
||||
|
||||
};
|
||||
for (int i = DIAG_NONE; i < DIAG_WARNING_TYPE; i++)
|
||||
{
|
||||
|
||||
@@ -256,6 +256,9 @@ typedef struct BuildOptions_
|
||||
bool force_linker;
|
||||
const char *panicfn;
|
||||
const char *cc;
|
||||
const char *build_dir;
|
||||
const char *llvm_out;
|
||||
const char *obj_out;
|
||||
RelocModel reloc_model;
|
||||
X86VectorCapability x86_vector_capability;
|
||||
bool print_keywords;
|
||||
@@ -309,6 +312,8 @@ typedef struct
|
||||
const char *cpu;
|
||||
const char **link_args;
|
||||
const char *build_dir;
|
||||
const char *object_file_dir;
|
||||
const char *llvm_file_dir;
|
||||
bool run_after_compile : 1;
|
||||
bool test_output : 1;
|
||||
bool output_headers : 1;
|
||||
|
||||
@@ -61,6 +61,30 @@ ArchOsTarget default_target = ELF_RISCV64;
|
||||
ArchOsTarget default_target = ARCH_OS_TARGET_DEFAULT;
|
||||
#endif
|
||||
|
||||
static bool command_is_compile(CompilerCommand command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case COMMAND_COMPILE:
|
||||
case COMMAND_COMPILE_ONLY:
|
||||
case COMMAND_COMPILE_RUN:
|
||||
return true;
|
||||
case COMMAND_MISSING:
|
||||
case COMMAND_GENERATE_HEADERS:
|
||||
case COMMAND_INIT:
|
||||
case COMMAND_BUILD:
|
||||
case COMMAND_RUN:
|
||||
case COMMAND_CLEAN_RUN:
|
||||
case COMMAND_CLEAN:
|
||||
case COMMAND_DIST:
|
||||
case COMMAND_DOCS:
|
||||
case COMMAND_BENCH:
|
||||
case COMMAND_UNIT_TEST:
|
||||
case COMMAND_PRINT_SYNTAX:
|
||||
return false;
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
static void update_build_target_from_options(BuildTarget *target, BuildOptions *options)
|
||||
{
|
||||
switch (options->command)
|
||||
@@ -163,6 +187,18 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
|
||||
{
|
||||
target->feature.x86_vector_capability = options->x86_vector_capability;
|
||||
}
|
||||
if (command_is_compile(options->command))
|
||||
{
|
||||
target->build_dir = options->build_dir ? options->build_dir : NULL;
|
||||
target->object_file_dir = options->obj_out ? options->obj_out : target->build_dir;
|
||||
target->llvm_file_dir = options->llvm_out ? options->llvm_out : target->build_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
target->build_dir = options->build_dir ? options->build_dir : "build";
|
||||
target->object_file_dir = options->obj_out ? options->obj_out : file_append_path(target->build_dir, "tmp");
|
||||
target->llvm_file_dir = options->llvm_out ? options->llvm_out : file_append_path(target->build_dir, "llvm_ir");
|
||||
}
|
||||
switch (options->compile_option)
|
||||
{
|
||||
case COMPILE_NORMAL:
|
||||
@@ -231,7 +267,6 @@ void init_build_target(BuildTarget *target, BuildOptions *options)
|
||||
Project *project = project_load();
|
||||
*target = *project_select_target(project, options->target_select);
|
||||
|
||||
target->build_dir = "build";
|
||||
update_build_target_from_options(target, options);
|
||||
if (target->build_dir && !file_exists(target->build_dir))
|
||||
{
|
||||
|
||||
@@ -222,6 +222,27 @@ void compiler_compile(void)
|
||||
void **gen_contexts = VECNEW(void*, module_count);
|
||||
void (*task)(void *);
|
||||
|
||||
if (active_target.llvm_file_dir || active_target.emit_object_files)
|
||||
{
|
||||
if (active_target.build_dir && !file_exists(active_target.build_dir) && !dir_make(active_target.build_dir))
|
||||
{
|
||||
error_exit("Failed to create build directory '%s'.", active_target.build_dir);
|
||||
}
|
||||
}
|
||||
if (active_target.llvm_file_dir && active_target.emit_llvm)
|
||||
{
|
||||
if (!file_exists(active_target.llvm_file_dir) && !dir_make(active_target.llvm_file_dir))
|
||||
{
|
||||
error_exit("Failed to create output directory '%s'.", active_target.llvm_file_dir);
|
||||
}
|
||||
}
|
||||
if (active_target.object_file_dir && active_target.emit_object_files)
|
||||
{
|
||||
if (!file_exists(active_target.object_file_dir) && !dir_make(active_target.object_file_dir))
|
||||
{
|
||||
error_exit("Failed to create output directory '%s'.", active_target.object_file_dir);
|
||||
}
|
||||
}
|
||||
switch (active_target.backend)
|
||||
{
|
||||
case BACKEND_LLVM:
|
||||
|
||||
@@ -583,6 +583,7 @@ typedef struct Decl_
|
||||
bool is_maybe_unused : 1;
|
||||
bool is_must_use : 1;
|
||||
bool will_reflect : 1;
|
||||
bool is_dynamic : 1;
|
||||
OperatorOverload operator : 4;
|
||||
union
|
||||
{
|
||||
@@ -616,8 +617,9 @@ typedef struct Decl_
|
||||
Decl **methods;
|
||||
union
|
||||
{
|
||||
// Unions, Fault and Struct use strukt
|
||||
// Unions, Struct use strukt
|
||||
StructDecl strukt;
|
||||
// Enums and Fault
|
||||
EnumDecl enums;
|
||||
DistinctDecl distinct_decl;
|
||||
BitStructDecl bitstruct;
|
||||
@@ -1573,7 +1575,7 @@ extern Type *type_cuint;
|
||||
extern const char *attribute_list[NUMBER_OF_ATTRIBUTES];
|
||||
extern const char *builtin_list[NUMBER_OF_BUILTINS];
|
||||
|
||||
extern const char *kw_std__builtin;
|
||||
extern const char *kw_std__core;
|
||||
|
||||
extern const char *kw_std;
|
||||
extern const char *kw_max;
|
||||
|
||||
@@ -166,7 +166,9 @@ void decl_register(Decl *decl)
|
||||
|
||||
void unit_register_global_decl(CompilationUnit *unit, Decl *decl)
|
||||
{
|
||||
assert(!decl->module || decl->module->is_generic);
|
||||
decl->module = unit->module;
|
||||
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_POISONED:
|
||||
|
||||
@@ -168,6 +168,29 @@ typedef enum
|
||||
DOC_DIRECTIVE_ENSURE,
|
||||
} DocDirectiveKind;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INTROSPECT_TYPE_VOID = 0,
|
||||
INTROSPECT_TYPE_BOOL = 1,
|
||||
INTROSPECT_TYPE_SIGNED_INT = 2,
|
||||
INTROSPECT_TYPE_UNSIGNED_INT = 3,
|
||||
INTROSPECT_TYPE_FLOAT = 4,
|
||||
INTROSPECT_TYPE_TYPEID = 5,
|
||||
INTROSPECT_TYPE_ANYERR = 6,
|
||||
INTROSPECT_TYPE_ANY = 7,
|
||||
INTROSPECT_TYPE_ENUM = 8,
|
||||
INTROSPECT_TYPE_FAULT = 9,
|
||||
INTROSPECT_TYPE_STRUCT = 10,
|
||||
INTROSPECT_TYPE_UNION = 11,
|
||||
INTROSPECT_TYPE_BITSTRUCT = 12,
|
||||
INTROSPECT_TYPE_FUNC = 13,
|
||||
INTROSPECT_TYPE_FAILABLE = 14,
|
||||
INTROSPECT_TYPE_ARRAY = 15,
|
||||
INTROSPECT_TYPE_SUBARRAY = 16,
|
||||
INTROSPECT_TYPE_VECTOR = 17,
|
||||
INTROSPECT_TYPE_DISTINCT = 18
|
||||
} IntrospectType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EXPR_POISONED,
|
||||
|
||||
@@ -482,7 +482,7 @@ void gencontext_emit_object_file(GenContext *context)
|
||||
LLVMDisposeMessage(layout);
|
||||
|
||||
// Generate .o or .obj file
|
||||
if (LLVMTargetMachineEmitToFile(context->machine, context->module, context->object_filename, LLVMObjectFile, &err))
|
||||
if (LLVMTargetMachineEmitToFile(context->machine, context->module, (char *)context->object_filename, LLVMObjectFile, &err))
|
||||
{
|
||||
error_exit("Could not emit object file: %s", err);
|
||||
}
|
||||
@@ -712,96 +712,11 @@ void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value)
|
||||
}
|
||||
|
||||
}
|
||||
void llvm_emit_introspection_type_from_decl(GenContext *c, Decl *decl)
|
||||
{
|
||||
llvm_get_type(c, decl->type);
|
||||
if (decl_is_struct_type(decl))
|
||||
{
|
||||
Decl **decls = decl->strukt.members;
|
||||
VECEACH(decls, i)
|
||||
{
|
||||
Decl *member_decl = decls[i];
|
||||
if (decl_is_struct_type(member_decl))
|
||||
{
|
||||
llvm_emit_introspection_type_from_decl(c, member_decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (decl_is_enum_kind(decl))
|
||||
{
|
||||
Decl **enum_vals = decl->enums.values;
|
||||
unsigned elements = vec_size(enum_vals);
|
||||
LLVMTypeRef element_type = llvm_get_type(c, type_voidptr);
|
||||
LLVMTypeRef elements_type = LLVMArrayType(element_type, elements);
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->extname);
|
||||
scratch_buffer_append("$elements");
|
||||
LLVMValueRef enum_elements = llvm_add_global_type(c, scratch_buffer_to_string(), elements_type, 0);
|
||||
LLVMSetGlobalConstant(enum_elements, 1);
|
||||
llvm_set_linkage(c, decl, enum_elements);
|
||||
LLVMSetInitializer(enum_elements, LLVMConstNull(elements_type));
|
||||
AlignSize alignment = type_alloca_alignment(type_voidptr);
|
||||
for (unsigned i = 0; i < elements; i++)
|
||||
{
|
||||
AlignSize store_align;
|
||||
enum_vals[i]->backend_ref = llvm_emit_array_gep_raw(c, enum_elements, elements_type, i, alignment, &store_align);
|
||||
}
|
||||
Decl **associated_values = decl->enums.parameters;
|
||||
unsigned associated_value_count = vec_size(associated_values);
|
||||
if (associated_value_count && elements)
|
||||
{
|
||||
|
||||
LLVMValueRef *values = malloc_arena(elements * sizeof(LLVMValueRef));
|
||||
LLVMTypeRef val_type;
|
||||
VECEACH(associated_values, ai)
|
||||
{
|
||||
val_type = NULL;
|
||||
bool mixed = false;
|
||||
for (unsigned i = 0; i < elements; i++)
|
||||
{
|
||||
BEValue value;
|
||||
llvm_emit_expr(c, &value, enum_vals[i]->enum_constant.args[ai]);
|
||||
assert(!llvm_value_is_addr(&value));
|
||||
LLVMValueRef llvm_value = llvm_value_is_bool(&value) ? LLVMConstZExt(value.value, c->byte_type) : value.value;
|
||||
values[i] = llvm_value;
|
||||
if (!val_type)
|
||||
{
|
||||
val_type = LLVMTypeOf(llvm_value);
|
||||
continue;
|
||||
}
|
||||
if (val_type != LLVMTypeOf(llvm_value)) mixed = true;
|
||||
}
|
||||
Decl *associated_value = associated_values[ai];
|
||||
LLVMValueRef associated_value_arr = mixed ? LLVMConstStruct(values, elements, true) : LLVMConstArray(val_type, values, elements);
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->extname);
|
||||
scratch_buffer_append("$$");
|
||||
scratch_buffer_append(associated_value->name);
|
||||
LLVMValueRef global_ref = llvm_add_global_type(c, scratch_buffer_to_string(), LLVMTypeOf(associated_value_arr), 0);
|
||||
LLVMSetInitializer(global_ref, associated_value_arr);
|
||||
LLVMSetGlobalConstant(global_ref, true);
|
||||
if (mixed)
|
||||
{
|
||||
LLVMTypeRef cast_type = llvm_get_ptr_type(c, type_get_array(associated_value->type, elements));
|
||||
associated_value->backend_ref = LLVMConstBitCast(global_ref, cast_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
associated_value->backend_ref = global_ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append("introspect.");
|
||||
scratch_buffer_append(decl->name ? decl->name : "anon");
|
||||
LLVMValueRef global_name = llvm_add_global_var(c, scratch_buffer_to_string(), type_char, 0);
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false));
|
||||
decl->type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));
|
||||
llvm_set_linkage(c, decl, global_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void llvm_value_set_bool(BEValue *value, LLVMValueRef llvm_value)
|
||||
@@ -847,9 +762,6 @@ LLVMBasicBlockRef llvm_basic_block_new(GenContext *c, const char *name)
|
||||
return LLVMCreateBasicBlockInContext(c->context, name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void llvm_emit_type_decls(GenContext *context, Decl *decl)
|
||||
{
|
||||
switch (decl->decl_kind)
|
||||
@@ -864,19 +776,17 @@ static void llvm_emit_type_decls(GenContext *context, Decl *decl)
|
||||
break;
|
||||
case DECL_TYPEDEF:
|
||||
break;
|
||||
case DECL_DISTINCT:
|
||||
// TODO
|
||||
break;
|
||||
case DECL_ENUM_CONSTANT:
|
||||
case DECL_FAULTVALUE:
|
||||
// TODO
|
||||
break;;
|
||||
case DECL_DISTINCT:
|
||||
case DECL_STRUCT:
|
||||
case DECL_UNION:
|
||||
case DECL_ENUM:
|
||||
case DECL_FAULT:
|
||||
case DECL_BITSTRUCT:
|
||||
llvm_emit_introspection_type_from_decl(context, decl);
|
||||
llvm_get_typeid(context, decl->type);
|
||||
break;
|
||||
case DECL_BODYPARAM:
|
||||
case NON_TYPE_DECLS:
|
||||
@@ -999,7 +909,10 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl)
|
||||
if (decl->define_decl.define_kind != DEFINE_TYPE_GENERIC) return llvm_get_ref(c, decl->define_decl.alias);
|
||||
UNREACHABLE
|
||||
case DECL_FAULTVALUE:
|
||||
llvm_emit_introspection_type_from_decl(c, declptr(decl->enum_constant.parent));
|
||||
if (!decl->backend_ref)
|
||||
{
|
||||
llvm_get_typeid(c, declptr(decl->enum_constant.parent)->type);
|
||||
}
|
||||
assert(decl->backend_ref);
|
||||
return decl->backend_ref;
|
||||
case DECL_POISONED:
|
||||
@@ -1036,7 +949,6 @@ void *llvm_gen(Module *module)
|
||||
gencontext_init(gen_context, module);
|
||||
gencontext_begin_module(gen_context);
|
||||
|
||||
|
||||
VECEACH(module->units, j)
|
||||
{
|
||||
CompilationUnit *unit = module->units[j];
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValue *lhs_loaded, BinaryOp binary_op);
|
||||
static void llvm_emit_any_pointer(GenContext *c, BEValue *any, BEValue *pointer);
|
||||
static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr);
|
||||
static void gencontext_emit_unary_expr(GenContext *context, BEValue *value, Expr *expr);
|
||||
static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr);
|
||||
static inline void llvm_emit_post_inc_dec(GenContext *c, BEValue *value, Expr *expr, int diff, bool use_mod);
|
||||
static inline void llvm_emit_pre_inc_dec(GenContext *c, BEValue *value, Expr *expr, int diff, bool use_mod);
|
||||
static inline void llvm_emit_inc_dec_change(GenContext *c, bool use_mod, BEValue *addr, BEValue *after, BEValue *before, Expr *expr, int diff);
|
||||
@@ -2044,6 +2044,21 @@ static inline void llvm_emit_pre_inc_dec(GenContext *c, BEValue *value, Expr *ex
|
||||
llvm_emit_inc_dec_change(c, use_mod, &addr, value, NULL, expr, diff);
|
||||
}
|
||||
|
||||
static inline void llvm_emit_deref(GenContext *c, BEValue *value, Expr *inner, Type *type)
|
||||
{
|
||||
llvm_emit_expr(c, value, inner);
|
||||
llvm_value_rvalue(c, value);
|
||||
if (active_target.feature.safe_mode)
|
||||
{
|
||||
LLVMValueRef check = LLVMBuildICmp(c->builder, LLVMIntEQ, value->value, llvm_get_zero(c, inner->type), "checknull");
|
||||
llvm_emit_panic_on_true(c, check, "Dereference of null pointer", inner->span);
|
||||
}
|
||||
// Load the pointer value.
|
||||
llvm_value_rvalue(c, value);
|
||||
// Convert pointer to address
|
||||
value->kind = BE_ADDRESS;
|
||||
value->type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit the common x++ and x-- operations.
|
||||
@@ -2063,7 +2078,7 @@ static inline void llvm_emit_post_inc_dec(GenContext *c, BEValue *value, Expr *e
|
||||
}
|
||||
|
||||
|
||||
static void gencontext_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
Type *type = type_reduced_from_expr(expr->unary_expr.expr);
|
||||
Expr *inner = expr->unary_expr.expr;
|
||||
@@ -2166,13 +2181,7 @@ static void gencontext_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr
|
||||
value->type = type_lowering(expr->type);
|
||||
return;
|
||||
case UNARYOP_DEREF:
|
||||
REMINDER("insert a check for deref in debug mode");
|
||||
llvm_emit_expr(c, value, inner);
|
||||
// Load the pointer value.
|
||||
llvm_value_rvalue(c, value);
|
||||
// Convert pointer to address
|
||||
value->kind = BE_ADDRESS;
|
||||
value->type = type_lowering(expr->type);
|
||||
llvm_emit_deref(c, value, inner, type_lowering(expr->type));
|
||||
return;
|
||||
case UNARYOP_INC:
|
||||
llvm_emit_pre_inc_dec(c, value, inner, 1, false);
|
||||
@@ -2313,7 +2322,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
|
||||
Expr *start = exprptr(slice->slice_expr.start);
|
||||
Expr *end = exprptrzero(slice->slice_expr.end);
|
||||
|
||||
Type *parent_type = parent_expr->type->canonical;
|
||||
Type *parent_type = type_flatten_distinct(parent_expr->type);
|
||||
BEValue parent_addr_x;
|
||||
llvm_emit_expr(c, &parent_addr_x, parent_expr);
|
||||
llvm_value_addr(c, &parent_addr_x);
|
||||
@@ -2325,12 +2334,13 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
|
||||
switch (parent_type->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
parent_load_value = parent_base = gencontext_emit_load(c, parent_type, parent_addr);
|
||||
parent_load_value = parent_base = LLVMBuildLoad2(c->builder, llvm_get_type(c, parent_type), parent_addr, "");
|
||||
break;
|
||||
case TYPE_SUBARRAY:
|
||||
parent_load_value = gencontext_emit_load(c, parent_type, parent_addr);
|
||||
parent_load_value = LLVMBuildLoad2(c->builder, llvm_get_type(c, parent_type), parent_addr, "");
|
||||
parent_base = LLVMBuildExtractValue(c->builder, parent_load_value, 0, "");
|
||||
break;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_ARRAY:
|
||||
parent_base = parent_addr;
|
||||
break;
|
||||
@@ -2345,12 +2355,15 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
|
||||
llvm_value_rvalue(c, &start_index);
|
||||
|
||||
BEValue len = { .value = NULL };
|
||||
bool check_end = true;
|
||||
if (!end || slice->slice_expr.start_from_back || slice->slice_expr.end_from_back || active_target.feature.safe_mode)
|
||||
{
|
||||
switch (parent_type->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
len.value = NULL;
|
||||
check_end = false;
|
||||
break;
|
||||
case TYPE_SUBARRAY:
|
||||
assert(parent_load_value);
|
||||
@@ -2371,7 +2384,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
|
||||
}
|
||||
|
||||
// Check that index does not extend beyond the length.
|
||||
if (parent_type->type_kind != TYPE_POINTER && active_target.feature.safe_mode)
|
||||
if (check_end && active_target.feature.safe_mode)
|
||||
{
|
||||
assert(len.value);
|
||||
BEValue exceeds_size;
|
||||
@@ -2448,6 +2461,7 @@ static void gencontext_emit_slice(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
{
|
||||
Type *pointer_type = type_get_ptr(parent.type->array.base);
|
||||
// Move pointer
|
||||
@@ -2462,7 +2476,6 @@ static void gencontext_emit_slice(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
case TYPE_POINTER:
|
||||
start_pointer = llvm_emit_pointer_inbounds_gep_raw(c, llvm_get_pointee_type(c, parent.type), parent.value, start.value);
|
||||
break;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
TODO
|
||||
default:
|
||||
@@ -3299,77 +3312,11 @@ static void llvm_emit_post_unary_expr(GenContext *context, BEValue *be_value, Ex
|
||||
false);
|
||||
}
|
||||
|
||||
void llvm_emit_derived_backend_type(GenContext *c, Type *type)
|
||||
{
|
||||
llvm_get_type(c, type);
|
||||
LLVMValueRef global_name = llvm_add_global_type(c, type->name, llvm_get_type(c, type_char), 0);
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false));
|
||||
type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));
|
||||
Decl *origin = NULL;
|
||||
Type *original_type = type;
|
||||
while (!origin)
|
||||
{
|
||||
switch (original_type->type_kind)
|
||||
{
|
||||
case TYPE_FAILABLE:
|
||||
original_type = type->failable;
|
||||
continue;
|
||||
case TYPE_VECTOR:
|
||||
original_type = type->array.base;
|
||||
continue;
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
original_type = original_type->array.base;
|
||||
continue;
|
||||
case TYPE_POINTER:
|
||||
original_type = original_type->pointer;
|
||||
continue;
|
||||
case TYPE_ENUM:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
case TYPE_BITSTRUCT:
|
||||
case TYPE_FAULTTYPE:
|
||||
case TYPE_DISTINCT:
|
||||
origin = type->decl;
|
||||
continue;
|
||||
case TYPE_TYPEDEF:
|
||||
original_type = original_type->canonical;
|
||||
continue;
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_TYPEINFO:
|
||||
UNREACHABLE
|
||||
default:
|
||||
goto PRIMITIVE;
|
||||
}
|
||||
}
|
||||
llvm_set_linkage(c, origin, global_name);
|
||||
return;
|
||||
|
||||
PRIMITIVE:
|
||||
llvm_set_weak(c, global_name);
|
||||
}
|
||||
|
||||
void llvm_emit_typeid(GenContext *c, BEValue *be_value, Type *type)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
type = type->canonical;
|
||||
if (type_is_builtin(type->type_kind))
|
||||
{
|
||||
value = llvm_const_int(c, type_usize, type->type_kind);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!type->backend_typeid)
|
||||
{
|
||||
llvm_emit_derived_backend_type(c, type);
|
||||
}
|
||||
value = type->backend_typeid;
|
||||
}
|
||||
llvm_value_set(be_value, value, type_typeid);
|
||||
llvm_value_set(be_value, llvm_get_typeid(c, type), type_typeid);
|
||||
}
|
||||
|
||||
void llvm_emit_try_assign_try_catch(GenContext *c, bool is_try, BEValue *be_value, BEValue *var_addr, BEValue *catch_addr, Expr *rhs)
|
||||
@@ -4818,7 +4765,8 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
}
|
||||
}
|
||||
|
||||
llvm_add_abi_call_attributes(c, call_value, 1, non_variadic_params, params, abi_args);
|
||||
assert(!prototype->ret_by_ref || prototype->ret_by_ref_abi_info->kind != ABI_ARG_INDIRECT);
|
||||
llvm_add_abi_call_attributes(c, call_value, prototype->ret_by_ref ? 2 : 1, non_variadic_params, params, abi_args);
|
||||
if (prototype->abi_varargs)
|
||||
{
|
||||
llvm_add_abi_call_attributes(c,
|
||||
@@ -5346,7 +5294,7 @@ void llvm_emit_try_unwrap(GenContext *c, BEValue *value, Expr *expr)
|
||||
}
|
||||
else
|
||||
{
|
||||
llvm_emit_local_decl(c, expr->try_unwrap_expr.decl);
|
||||
llvm_emit_local_decl(c, expr->try_unwrap_expr.decl, &addr);
|
||||
llvm_value_set_decl_address(c, &addr, expr->try_unwrap_expr.decl);
|
||||
}
|
||||
assert(llvm_value_is_addr(&addr));
|
||||
@@ -5362,7 +5310,7 @@ void llvm_emit_catch_unwrap(GenContext *c, BEValue *value, Expr *expr)
|
||||
}
|
||||
else if (expr->catch_unwrap_expr.decl)
|
||||
{
|
||||
llvm_emit_local_decl(c, expr->catch_unwrap_expr.decl);
|
||||
llvm_emit_local_decl(c, expr->catch_unwrap_expr.decl, &addr);
|
||||
llvm_value_set_decl_address(c, &addr, expr->catch_unwrap_expr.decl);
|
||||
}
|
||||
else
|
||||
@@ -5573,8 +5521,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
case EXPR_BUILTIN:
|
||||
UNREACHABLE;
|
||||
case EXPR_DECL:
|
||||
llvm_emit_local_decl(c, expr->decl_expr);
|
||||
llvm_value_set_decl_address(c, value, expr->decl_expr);
|
||||
llvm_emit_local_decl(c, expr->decl_expr, value);
|
||||
return;
|
||||
case EXPR_SLICE_ASSIGN:
|
||||
llvm_emit_slice_assign(c, value, expr);
|
||||
@@ -5610,7 +5557,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
llvm_emit_expr_block(c, value, expr);
|
||||
return;
|
||||
case EXPR_UNARY:
|
||||
gencontext_emit_unary_expr(c, value, expr);
|
||||
llvm_emit_unary_expr(c, value, expr);
|
||||
return;
|
||||
case EXPR_CONST:
|
||||
llvm_emit_const_expr(c, value, expr);
|
||||
|
||||
@@ -79,8 +79,8 @@ typedef struct
|
||||
LLVMBuilderRef builder;
|
||||
LLVMBasicBlockRef current_block;
|
||||
LLVMBasicBlockRef catch_block;
|
||||
char *ir_filename;
|
||||
char *object_filename;
|
||||
const char *ir_filename;
|
||||
const char *object_filename;
|
||||
// The recipient of the error value in a catch(err = ...) expression.
|
||||
LLVMValueRef error_var;
|
||||
LLVMTypeRef bool_type;
|
||||
@@ -234,6 +234,7 @@ void llvm_value_set_decl(GenContext *c, BEValue *value, Decl *decl);
|
||||
void llvm_value_fold_failable(GenContext *c, BEValue *value);
|
||||
void llvm_value_struct_gep(GenContext *c, BEValue *element, BEValue *struct_pointer, unsigned index);
|
||||
|
||||
LLVMValueRef llvm_get_typeid(GenContext *context, Type *type);
|
||||
LLVMTypeRef llvm_abi_type(GenContext *c, AbiType type);
|
||||
TypeSize llvm_abi_size(GenContext *c, LLVMTypeRef type);
|
||||
BitSize llvm_bitsize(GenContext *c, LLVMTypeRef type);
|
||||
@@ -262,7 +263,6 @@ void llvm_emit_convert_value_from_coerced(GenContext *c, BEValue *result, LLVMTy
|
||||
void llvm_emit_coerce_store(GenContext *c, LLVMValueRef addr, AlignSize alignment, LLVMTypeRef coerced, LLVMValueRef value, LLVMTypeRef target_type);
|
||||
void llvm_emit_function_body(GenContext *context, Decl *decl);
|
||||
void llvm_emit_function_decl(GenContext *c, Decl *decl);
|
||||
void llvm_emit_introspection_type_from_decl(GenContext *c, Decl *decl);
|
||||
void llvm_set_weak(GenContext *c, LLVMValueRef global);
|
||||
void llvm_set_linkonce(GenContext *c, LLVMValueRef global);
|
||||
void llvm_set_comdat(GenContext *c, LLVMValueRef global);
|
||||
@@ -320,7 +320,7 @@ LLVMValueRef llvm_emit_lshr_fixed(GenContext *c, LLVMValueRef data, int shift);
|
||||
|
||||
// -- general --
|
||||
void llvm_emit_local_var_alloca(GenContext *c, Decl *decl);
|
||||
LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl);
|
||||
void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value);
|
||||
LLVMValueRef llvm_emit_aggregate_value(GenContext *c, Type *type, ...);
|
||||
LLVMValueRef llvm_emit_memclear_size_align(GenContext *c, LLVMValueRef ref, uint64_t size, AlignSize align, bool bitcast);
|
||||
void llvm_store_zero(GenContext *c, BEValue *ref);
|
||||
@@ -377,13 +377,6 @@ void llvm_store_decl_raw(GenContext *context, Decl *decl, LLVMValueRef value);
|
||||
LLVMTypeRef llvm_get_twostruct(GenContext *context, LLVMTypeRef lo, LLVMTypeRef hi);
|
||||
LLVMValueRef llvm_emit_coerce(GenContext *c, LLVMTypeRef coerced, BEValue *value, Type *original_type);
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_load(GenContext *c, Type *type, LLVMValueRef value)
|
||||
{
|
||||
assert(llvm_get_type(c, type) == LLVMGetElementType(LLVMTypeOf(value)));
|
||||
return LLVMBuildLoad2(c->builder, llvm_get_type(c, type), value, "");
|
||||
}
|
||||
|
||||
|
||||
static inline LLVMValueRef decl_failable_ref(Decl *decl)
|
||||
{
|
||||
assert(decl->decl_kind == DECL_VAR);
|
||||
@@ -494,7 +487,6 @@ static inline LLVMValueRef llvm_const_int(GenContext *c, Type *type, uint64_t va
|
||||
|
||||
static inline LLVMValueRef llvm_add_global_var(GenContext *c, const char *name, Type *type, AlignSize alignment)
|
||||
{
|
||||
printf("Adding %s with %d\n", name, (int)alignment);
|
||||
type = type_lowering(type_no_fail(type));
|
||||
LLVMValueRef ref = LLVMAddGlobal(c->module, llvm_get_type(c, type), name);
|
||||
LLVMSetAlignment(ref, (unsigned)alignment ? alignment : type_alloca_alignment(type));
|
||||
@@ -503,7 +495,6 @@ static inline LLVMValueRef llvm_add_global_var(GenContext *c, const char *name,
|
||||
|
||||
static inline LLVMValueRef llvm_add_global_type(GenContext *c, const char *name, LLVMTypeRef type, AlignSize alignment)
|
||||
{
|
||||
printf("Adding %s with %d\n", name, (int)alignment);
|
||||
LLVMValueRef ref = LLVMAddGlobal(c->module, type, name);
|
||||
LLVMSetAlignment(ref, (unsigned)alignment ? alignment : LLVMPreferredAlignmentOfGlobal(c->target_data, ref));
|
||||
return ref;
|
||||
|
||||
@@ -11,8 +11,9 @@ void gencontext_begin_module(GenContext *c)
|
||||
|
||||
const char *result = module_create_object_file_name(c->code_module);
|
||||
c->ir_filename = str_printf("%s.ll", result);
|
||||
if (active_target.llvm_file_dir) c->ir_filename = file_append_path(active_target.llvm_file_dir, c->ir_filename);
|
||||
c->object_filename = str_printf("%s%s", result, get_object_extension());
|
||||
|
||||
if (active_target.object_file_dir) c->object_filename = file_append_path(active_target.object_file_dir, c->object_filename);
|
||||
c->panicfn = global_context.panic_fn;
|
||||
c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context);
|
||||
c->machine = llvm_target_machine_create();
|
||||
@@ -57,9 +58,32 @@ void gencontext_begin_module(GenContext *c)
|
||||
|
||||
VECEACH(global_context.type, i)
|
||||
{
|
||||
global_context.type[i]->backend_type = NULL;
|
||||
global_context.type[i]->backend_debug_type = NULL;
|
||||
global_context.type[i]->backend_typeid = NULL;
|
||||
Type *type = global_context.type[i];
|
||||
type->backend_type = NULL;
|
||||
type->backend_debug_type = NULL;
|
||||
type->backend_typeid = NULL;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_ENUM:
|
||||
case TYPE_FAULTTYPE:
|
||||
{
|
||||
Decl **values = type->decl->enums.values;
|
||||
VECEACH(values, j)
|
||||
{
|
||||
values[j]->backend_ref = NULL;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
}
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
case TYPE_DISTINCT:
|
||||
type->decl->backend_ref = NULL;
|
||||
break;
|
||||
case TYPE_FUNC:
|
||||
// TODO
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c->panicfn) c->panicfn->backend_ref = NULL;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ void llvm_emit_compound_stmt(GenContext *c, Ast *ast)
|
||||
/**
|
||||
* This emits a local declaration.
|
||||
*/
|
||||
LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl)
|
||||
void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value)
|
||||
{
|
||||
// 1. Get the declaration and the LLVM type.
|
||||
Type *var_type = type_lowering(type_no_fail(decl->type));
|
||||
@@ -35,7 +35,11 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl)
|
||||
if (decl->var.is_static)
|
||||
{
|
||||
// In defers we might already have generated this variable.
|
||||
if (decl->backend_ref) return decl->backend_ref;
|
||||
if (decl->backend_ref)
|
||||
{
|
||||
llvm_value_set_decl(c, value, decl);
|
||||
return;
|
||||
}
|
||||
void *builder = c->builder;
|
||||
c->builder = NULL;
|
||||
decl->backend_ref = llvm_add_global_var(c, "tempglobal", var_type, decl->alignment);
|
||||
@@ -48,12 +52,14 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl)
|
||||
}
|
||||
llvm_emit_global_variable_init(c, decl);
|
||||
c->builder = builder;
|
||||
return decl->backend_ref;
|
||||
llvm_value_set_decl(c, value, decl);
|
||||
return;
|
||||
}
|
||||
assert(!decl->backend_ref);
|
||||
llvm_emit_local_var_alloca(c, decl);
|
||||
Expr *init = decl->var.init_expr;
|
||||
if (IS_FAILABLE(decl))
|
||||
bool is_failable = IS_FAILABLE(decl);
|
||||
if (is_failable)
|
||||
{
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->name);
|
||||
@@ -64,15 +70,18 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl)
|
||||
|
||||
if (init)
|
||||
{
|
||||
// If we don't have undef, then make an assign.
|
||||
if (!decl->var.no_init)
|
||||
llvm_value_set_decl_address(c, value, decl);
|
||||
value->kind = BE_ADDRESS;
|
||||
BEValue res = llvm_emit_assign_expr(c, value, decl->var.init_expr, decl->var.failable_ref);
|
||||
if (!is_failable) *value = res;
|
||||
}
|
||||
else if (decl->var.no_init)
|
||||
{
|
||||
llvm_value_set(value, LLVMGetUndef(alloc_type), decl->type);
|
||||
if (decl->var.failable_ref)
|
||||
{
|
||||
BEValue value;
|
||||
llvm_value_set_decl_address(c, &value, decl);
|
||||
value.kind = BE_ADDRESS;
|
||||
llvm_emit_assign_expr(c, &value, decl->var.init_expr, decl->var.failable_ref);
|
||||
LLVMBuildStore(c->builder, LLVMGetUndef(llvm_get_type(c, type_anyerr)), decl->var.failable_ref);
|
||||
}
|
||||
// TODO trap on undef in debug mode.
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -86,16 +95,16 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl)
|
||||
if (type_is_builtin(type->type_kind) || type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
llvm_emit_store(c, decl, LLVMConstNull(alloc_type));
|
||||
llvm_value_set(value, LLVMConstNull(alloc_type), type);
|
||||
}
|
||||
else
|
||||
{
|
||||
BEValue value;
|
||||
llvm_value_set_decl_address(c, &value, decl);
|
||||
value.kind = BE_ADDRESS;
|
||||
llvm_store_zero(c, &value);
|
||||
llvm_value_set_decl_address(c, value, decl);
|
||||
value->kind = BE_ADDRESS;
|
||||
llvm_store_zero(c, value);
|
||||
llvm_value_set(value, llvm_get_zero(c, type), type);
|
||||
}
|
||||
}
|
||||
return decl->backend_ref;
|
||||
}
|
||||
|
||||
void llvm_emit_decl_expr_list_ignore_result(GenContext *context, Expr *expr)
|
||||
@@ -124,7 +133,8 @@ void llvm_emit_decl_expr_list(GenContext *context, BEValue *be_value, Expr *expr
|
||||
if (last->expr_kind == EXPR_DECL)
|
||||
{
|
||||
type = last->decl_expr->var.type_info->type;
|
||||
LLVMValueRef decl_value = llvm_emit_local_decl(context, last->decl_expr);
|
||||
|
||||
LLVMValueRef decl_value = llvm_get_ref(context, last->decl_expr);
|
||||
if (bool_cast && last->decl_expr->var.unwrap)
|
||||
{
|
||||
llvm_value_set_bool(be_value, LLVMConstInt(context->bool_type, 1, false));
|
||||
@@ -1134,8 +1144,11 @@ void llvm_emit_stmt(GenContext *c, Ast *ast)
|
||||
gencontext_emit_expr_stmt(c, ast);
|
||||
break;
|
||||
case AST_DECLARE_STMT:
|
||||
llvm_emit_local_decl(c, ast->declare_stmt);
|
||||
{
|
||||
BEValue value;
|
||||
llvm_emit_local_decl(c, ast->declare_stmt, &value);
|
||||
break;
|
||||
}
|
||||
case AST_BREAK_STMT:
|
||||
llvm_emit_break(c, ast);
|
||||
break;
|
||||
|
||||
@@ -447,3 +447,327 @@ LLVMTypeRef llvm_abi_type(GenContext *c, AbiType type)
|
||||
if (abi_type_is_type(type)) return llvm_get_type(c, type.type);
|
||||
return LLVMIntTypeInContext(c->context, type.int_bits_plus_1 - 1);
|
||||
}
|
||||
|
||||
static inline Module *type_base_module(Type *type)
|
||||
{
|
||||
RETRY:
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_POISONED:
|
||||
case TYPE_VOID:
|
||||
case ALL_INTS:
|
||||
case ALL_FLOATS:
|
||||
case TYPE_BOOL:
|
||||
case TYPE_ANY:
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_TYPEID:
|
||||
return NULL;
|
||||
case TYPE_POINTER:
|
||||
type = type->pointer;
|
||||
goto RETRY;
|
||||
case TYPE_ENUM:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
case TYPE_BITSTRUCT:
|
||||
case TYPE_FAULTTYPE:
|
||||
case TYPE_DISTINCT:
|
||||
return type->decl->module;
|
||||
case TYPE_TYPEDEF:
|
||||
type = type->canonical;
|
||||
goto RETRY;
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
type = type->array.base;
|
||||
goto RETRY;
|
||||
case TYPE_FAILABLE:
|
||||
type = type->failable;
|
||||
goto RETRY;
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_TYPEINFO:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
LLVMValueRef llvm_get_introspection_for_derived_type(GenContext *c, IntrospectType kind, Type *type, Type *inner, LLVMValueRef extra)
|
||||
{
|
||||
LLVMValueRef value = llvm_get_typeid(c, inner);
|
||||
LLVMValueRef values[3] = { llvm_const_int(c, type_char, kind), value };
|
||||
int count = 2;
|
||||
if (extra)
|
||||
{
|
||||
values[2] = extra;
|
||||
count = 3;
|
||||
}
|
||||
LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, count, false);
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(".typeid.");
|
||||
Module *module = type_base_module(inner);
|
||||
if (module)
|
||||
{
|
||||
scratch_buffer_append(module->name->module);
|
||||
scratch_buffer_append_char('.');
|
||||
}
|
||||
scratch_buffer_append(type->name);
|
||||
LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMTypeOf(strukt), scratch_buffer_to_string());
|
||||
LLVMSetAlignment(global_name, llvm_abi_alignment(c, LLVMTypeOf(strukt)));
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, strukt);
|
||||
llvm_set_linkonce(c, global_name);
|
||||
return type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_get_introspection_for_builtin_type(GenContext *c, Type *type, IntrospectType introspect_type, int bits)
|
||||
{
|
||||
LLVMValueRef values[2];
|
||||
int count = 1;
|
||||
values[0] = llvm_const_int(c, type_char, introspect_type);
|
||||
if (bits)
|
||||
{
|
||||
values[1] = llvm_const_int(c, type_ushort, bits);
|
||||
count = 2;
|
||||
}
|
||||
LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, count, false);
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(".typeid.");
|
||||
scratch_buffer_append(type->name);
|
||||
LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMTypeOf(strukt), scratch_buffer_to_string());
|
||||
LLVMSetAlignment(global_name, llvm_abi_alignment(c, LLVMTypeOf(strukt)));
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, strukt);
|
||||
llvm_set_linkonce(c, global_name);
|
||||
return type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_get_introspection_weak(GenContext *c, Type *type, const char *name, LLVMValueRef data)
|
||||
{
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(".typeid.");
|
||||
scratch_buffer_append(name);
|
||||
LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMTypeOf(data), scratch_buffer_to_string());
|
||||
LLVMSetAlignment(global_name, llvm_abi_alignment(c, LLVMTypeOf(data)));
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, data);
|
||||
llvm_set_linkonce(c, global_name);
|
||||
return type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_get_introspection_external(GenContext *c, Type *type, LLVMValueRef data)
|
||||
{
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(".typeid.");
|
||||
scratch_buffer_append(type->name);
|
||||
LLVMValueRef global_name = LLVMAddGlobal(c->module, LLVMTypeOf(data), scratch_buffer_to_string());
|
||||
LLVMSetAlignment(global_name, llvm_abi_alignment(c, LLVMTypeOf(data)));
|
||||
LLVMSetLinkage(global_name, LLVMExternalLinkage);
|
||||
return type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_get_introspection_for_enum(GenContext *c, Type *type)
|
||||
{
|
||||
Decl *decl = type->decl;
|
||||
bool is_external = decl->module != c->code_module;
|
||||
bool is_dynamic = decl->is_dynamic;
|
||||
|
||||
Decl **enum_vals = decl->enums.values;
|
||||
unsigned elements = vec_size(enum_vals);
|
||||
Decl **associated_values = decl->enums.parameters;
|
||||
unsigned associated_value_count = vec_size(associated_values);
|
||||
if (is_external && is_dynamic)
|
||||
{
|
||||
elements = 0;
|
||||
}
|
||||
LLVMValueRef en_values[] = { llvm_const_int(c, type_char, INTROSPECT_TYPE_ENUM ),
|
||||
llvm_const_int(c, type_usize, elements),
|
||||
llvm_const_int(c, type_usize, associated_value_count) };
|
||||
LLVMValueRef strukt = LLVMConstStructInContext(c->context, en_values, 3, false);
|
||||
|
||||
if (is_external && !is_dynamic)
|
||||
{
|
||||
return llvm_get_introspection_external(c, type, strukt);
|
||||
}
|
||||
|
||||
LLVMValueRef val = llvm_get_introspection_weak(c, type, decl_get_extname(decl), strukt);
|
||||
if (!associated_value_count) return val;
|
||||
|
||||
LLVMValueRef *values = elements ? malloc_arena(elements * sizeof(LLVMValueRef)) : NULL;
|
||||
LLVMTypeRef val_type;
|
||||
VECEACH(associated_values, ai)
|
||||
{
|
||||
val_type = NULL;
|
||||
bool mixed = false;
|
||||
for (unsigned i = 0; i < elements; i++)
|
||||
{
|
||||
BEValue value;
|
||||
llvm_emit_expr(c, &value, enum_vals[i]->enum_constant.args[ai]);
|
||||
assert(!llvm_value_is_addr(&value));
|
||||
LLVMValueRef llvm_value = llvm_value_is_bool(&value) ? LLVMConstZExt(value.value, c->byte_type)
|
||||
: value.value;
|
||||
values[i] = llvm_value;
|
||||
if (!val_type)
|
||||
{
|
||||
val_type = LLVMTypeOf(llvm_value);
|
||||
continue;
|
||||
}
|
||||
if (val_type != LLVMTypeOf(llvm_value)) mixed = true;
|
||||
}
|
||||
Decl *associated_value = associated_values[ai];
|
||||
LLVMValueRef associated_value_arr = mixed ? LLVMConstStruct(values, elements, true) : LLVMConstArray(val_type,
|
||||
values,
|
||||
elements);
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->extname);
|
||||
scratch_buffer_append(".");
|
||||
scratch_buffer_append(associated_value->name);
|
||||
LLVMValueRef global_ref = llvm_add_global_type(c,
|
||||
scratch_buffer_to_string(),
|
||||
LLVMTypeOf(associated_value_arr),
|
||||
0);
|
||||
llvm_set_linkonce(c, global_ref);
|
||||
LLVMSetInitializer(global_ref, associated_value_arr);
|
||||
LLVMSetGlobalConstant(global_ref, true);
|
||||
if (mixed)
|
||||
{
|
||||
LLVMTypeRef cast_type = llvm_get_ptr_type(c, type_get_array(associated_value->type, elements));
|
||||
associated_value->backend_ref = LLVMConstBitCast(global_ref, cast_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
associated_value->backend_ref = global_ref;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_get_introspection_for_struct_union(GenContext *c, Type *type)
|
||||
{
|
||||
Decl *decl = type->decl;
|
||||
Decl **decls = decl->strukt.members;
|
||||
VECEACH(decls, i)
|
||||
{
|
||||
Decl *member_decl = decls[i];
|
||||
if (decl_is_struct_type(member_decl))
|
||||
{
|
||||
llvm_get_typeid(c, member_decl->type);
|
||||
}
|
||||
}
|
||||
LLVMValueRef values[] = { llvm_const_int(c, type_char, decl->decl_kind == DECL_STRUCT ? INTROSPECT_TYPE_STRUCT : INTROSPECT_TYPE_UNION ),
|
||||
llvm_const_int(c, type_usize, vec_size(decls)) };
|
||||
LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, 2, false);
|
||||
return llvm_get_introspection_weak(c, type, decl_get_extname(decl), strukt);
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_get_introspection_for_fault(GenContext *c, Type *type)
|
||||
{
|
||||
Decl *decl = type->decl;
|
||||
Decl **fault_vals = decl->enums.values;
|
||||
unsigned elements = vec_size(fault_vals);
|
||||
AlignSize store_align;
|
||||
for (unsigned i = 0; i < elements; i++)
|
||||
{
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl_get_extname(decl));
|
||||
scratch_buffer_append_char('.');
|
||||
Decl *val = fault_vals[i];
|
||||
scratch_buffer_append(val->name);
|
||||
LLVMValueRef global_name = llvm_add_global_var(c, scratch_buffer_to_string(), type_char, 0);
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false));
|
||||
llvm_set_linkonce(c, global_name);
|
||||
val->backend_ref = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));
|
||||
}
|
||||
LLVMTypeRef element_type = llvm_get_type(c, type_typeid);
|
||||
LLVMTypeRef elements_type = LLVMArrayType(element_type, elements);
|
||||
LLVMValueRef start = LLVMConstNull(elements_type);
|
||||
for (unsigned i = 0; i < elements; i++)
|
||||
{
|
||||
start = LLVMConstInsertValue(start, LLVMConstBitCast(fault_vals[i]->backend_ref, element_type), &i, 1);
|
||||
}
|
||||
LLVMValueRef values[] = { llvm_const_int(c, type_char, INTROSPECT_TYPE_FAULT ), llvm_const_int(c, type_usize, elements), start };
|
||||
LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, 3, false);
|
||||
return llvm_get_introspection_weak(c, type, decl_get_extname(decl), strukt);
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef llvm_get_typeid(GenContext *c, Type *type)
|
||||
{
|
||||
if (type->backend_typeid) return type->backend_typeid;
|
||||
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_FAILABLE:
|
||||
return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_FAILABLE, type, type->failable, NULL);
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_ARRAY, type, type->array.base,
|
||||
llvm_const_int(c, type_usize, 0));
|
||||
case TYPE_VECTOR:
|
||||
return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_VECTOR, type, type->array.base,
|
||||
llvm_const_int(c, type_usize, type->array.len));
|
||||
case TYPE_ARRAY:
|
||||
return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_ARRAY, type, type->array.base,
|
||||
llvm_const_int(c, type_usize, type->array.len));
|
||||
case TYPE_SUBARRAY:
|
||||
return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_ARRAY, type, type->array.base, NULL);
|
||||
case TYPE_POINTER:
|
||||
return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_ARRAY, type, type->pointer, NULL);
|
||||
case TYPE_DISTINCT:
|
||||
return llvm_get_introspection_for_derived_type(c, INTROSPECT_TYPE_DISTINCT, type, type->decl->distinct_decl.base_type, NULL);
|
||||
case TYPE_ENUM:
|
||||
return llvm_get_introspection_for_enum(c, type);
|
||||
case TYPE_FAULTTYPE:
|
||||
return llvm_get_introspection_for_fault(c, type);
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
return llvm_get_introspection_for_struct_union(c, type);
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
LLVMValueRef values[] = { llvm_const_int(c, type_char, INTROSPECT_TYPE_FUNC ) };
|
||||
LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, 1, false);
|
||||
return llvm_get_introspection_weak(c, type, decl_get_extname(type->decl), strukt);
|
||||
|
||||
}
|
||||
case TYPE_BITSTRUCT:
|
||||
{
|
||||
LLVMValueRef values[] = { llvm_const_int(c, type_char, INTROSPECT_TYPE_BITSTRUCT ) };
|
||||
LLVMValueRef strukt = LLVMConstStructInContext(c->context, values, 1, false);
|
||||
return llvm_get_introspection_weak(c, type, decl_get_extname(type->decl), strukt);
|
||||
}
|
||||
case TYPE_TYPEDEF:
|
||||
return llvm_get_typeid(c, type->canonical);
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_TYPEINFO:
|
||||
UNREACHABLE
|
||||
case TYPE_VOID:
|
||||
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_VOID, 0);
|
||||
case TYPE_BOOL:
|
||||
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_BOOL, 0);
|
||||
case ALL_SIGNED_INTS:
|
||||
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_SIGNED_INT,
|
||||
type_kind_bitsize(type->type_kind));
|
||||
case ALL_UNSIGNED_INTS:
|
||||
return llvm_get_introspection_for_builtin_type(c,
|
||||
type,
|
||||
INTROSPECT_TYPE_UNSIGNED_INT,
|
||||
type_kind_bitsize(type->type_kind));
|
||||
case ALL_FLOATS:
|
||||
return llvm_get_introspection_for_builtin_type(c,
|
||||
type,
|
||||
INTROSPECT_TYPE_FLOAT,
|
||||
type_kind_bitsize(type->type_kind));
|
||||
case TYPE_ANYERR:
|
||||
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_ANYERR, 0);
|
||||
case TYPE_ANY:
|
||||
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_ANY, 0);
|
||||
case TYPE_TYPEID:
|
||||
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_TYPEID, 0);
|
||||
case TYPE_POISONED:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
@@ -617,7 +617,7 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool
|
||||
if (to == type_voidptr || from == type_voidptr) return true;
|
||||
|
||||
// Special handling of int* = int[4]*
|
||||
if (from->pointer->type_kind == TYPE_ARRAY)
|
||||
if (from->pointer->type_kind == TYPE_ARRAY || from->pointer->type_kind == TYPE_FLEXIBLE_ARRAY)
|
||||
{
|
||||
if (type_is_subtype(to->pointer, from->pointer->array.base))
|
||||
{
|
||||
|
||||
@@ -68,8 +68,10 @@ static inline bool sema_check_no_duplicate_parameter(Decl **decls, Decl *current
|
||||
|
||||
|
||||
|
||||
static inline bool sema_analyse_struct_member(SemaContext *context, Decl *decl)
|
||||
static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent, Decl *decl)
|
||||
{
|
||||
assert(!decl->module || decl->module->is_generic);
|
||||
decl->module = parent->module;
|
||||
if (decl->name)
|
||||
{
|
||||
Decl *other = sema_resolve_symbol_in_current_dynamic_scope(context, decl->name);
|
||||
@@ -125,7 +127,7 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl, Decl **
|
||||
decl_poison(decl);
|
||||
continue;
|
||||
}
|
||||
if (!sema_analyse_struct_member(context, member))
|
||||
if (!sema_analyse_struct_member(context, decl, member))
|
||||
{
|
||||
if (decl_ok(decl))
|
||||
{
|
||||
@@ -224,7 +226,7 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl *
|
||||
decl_poison(decl);
|
||||
continue;
|
||||
}
|
||||
if (!sema_analyse_struct_member(context, member))
|
||||
if (!sema_analyse_struct_member(context, decl, member))
|
||||
{
|
||||
if (decl_ok(decl))
|
||||
{
|
||||
@@ -1614,6 +1616,7 @@ static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl)
|
||||
}
|
||||
Decl *function = decl_new(DECL_FUNC, NULL, decl->span, VISIBLE_EXTERN);
|
||||
function->name = kw_mainstub;
|
||||
function->module = decl->module;
|
||||
function->extname = kw_main;
|
||||
function->has_extname = true;
|
||||
function->func_decl.function_signature.returntype = type_infoid(type_info_new_base(type_cint, decl->span));
|
||||
@@ -2286,7 +2289,7 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl)
|
||||
}
|
||||
|
||||
decl->resolve_status = RESOLVE_RUNNING;
|
||||
decl->module = context->unit->module;
|
||||
assert(decl->module);
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_BITSTRUCT:
|
||||
|
||||
@@ -882,6 +882,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
|
||||
Decl *ambiguous_decl = NULL;
|
||||
Decl *private_symbol = NULL;
|
||||
|
||||
assert(expr && expr->identifier_expr.ident);
|
||||
DEBUG_LOG("Now resolving %s", expr->identifier_expr.ident);
|
||||
|
||||
DeclId body_param;
|
||||
@@ -992,6 +993,8 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
|
||||
|
||||
static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *expr)
|
||||
{
|
||||
assert(expr && expr->ct_ident_expr.identifier);
|
||||
|
||||
DEBUG_LOG("Now resolving %s", expr->ct_ident_expr.identifier);
|
||||
Decl *decl = sema_resolve_symbol(context, expr->ct_ident_expr.identifier, NULL, expr->span);
|
||||
|
||||
@@ -1012,6 +1015,7 @@ static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *e
|
||||
|
||||
static inline bool sema_expr_analyse_hash_identifier(SemaContext *context, Expr *expr)
|
||||
{
|
||||
assert(expr && expr->hash_ident_expr.identifier);
|
||||
DEBUG_LOG("Now resolving %s", expr->hash_ident_expr.identifier);
|
||||
Decl *decl = sema_resolve_symbol(context, expr->hash_ident_expr.identifier, NULL, expr->span);
|
||||
|
||||
@@ -4292,6 +4296,7 @@ static inline bool sema_expr_analyse_ct_identifier_lvalue(SemaContext *context,
|
||||
|
||||
Decl *ambiguous_decl = NULL;
|
||||
Decl *private_symbol = NULL;
|
||||
assert(expr && expr->ct_ident_expr.identifier);
|
||||
DEBUG_LOG("Now resolving %s", expr->ct_ident_expr.identifier);
|
||||
Decl *decl = sema_find_symbol(context, expr->ct_ident_expr.identifier);
|
||||
|
||||
@@ -7277,11 +7282,6 @@ bool splitpathref(const char *string, ArraySize len, Path **path_ref, const char
|
||||
if (!*ident_ref)
|
||||
{
|
||||
scratch_buffer_clear();
|
||||
if (*path_ref)
|
||||
{
|
||||
scratch_buffer_append_len((*path_ref)->module, (*path_ref)->len);
|
||||
scratch_buffer_append("::");
|
||||
}
|
||||
scratch_buffer_append_len(string, len);
|
||||
*ident_ref = scratch_buffer_to_string();
|
||||
*type_ref = TOKEN_INVALID_TOKEN;
|
||||
|
||||
@@ -165,11 +165,11 @@ static bool decl_is_visible(CompilationUnit *unit, Decl *decl)
|
||||
// 2. Same top module as unit -> ok
|
||||
if (top == unit->module->top_module) return true;
|
||||
|
||||
// 3. We want to check std::builtin
|
||||
// 3. We want to check std::core
|
||||
Module *lookup = module;
|
||||
while (lookup)
|
||||
{
|
||||
if (lookup->name->module == kw_std__builtin) return true;
|
||||
if (lookup->name->module == kw_std__core) return true;
|
||||
lookup = lookup->parent_module;
|
||||
}
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ void sema_analysis_run(void)
|
||||
|
||||
if (active_target.panicfn || !active_target.no_stdlib)
|
||||
{
|
||||
const char *panicfn = active_target.panicfn ? active_target.panicfn : "std::builtin::panic";
|
||||
const char *panicfn = active_target.panicfn ? active_target.panicfn : "std::core::builtin::panic";
|
||||
Path *path;
|
||||
const char *ident;
|
||||
TokenType type;
|
||||
|
||||
@@ -39,7 +39,7 @@ static SymTab symtab;
|
||||
const char *attribute_list[NUMBER_OF_ATTRIBUTES];
|
||||
const char *builtin_list[NUMBER_OF_BUILTINS];
|
||||
|
||||
const char *kw_std__builtin;
|
||||
const char *kw_std__core;
|
||||
const char *kw_in;
|
||||
const char *kw_out;
|
||||
const char *kw_inout;
|
||||
@@ -128,7 +128,7 @@ void symtab_init(uint32_t capacity)
|
||||
kw_FUNC = KW_DEF("FUNC");
|
||||
|
||||
type = TOKEN_IDENT;
|
||||
kw_std__builtin = KW_DEF("std::builtin");
|
||||
kw_std__core = KW_DEF("std::core");
|
||||
kw_sizeof = KW_DEF("sizeof");
|
||||
kw_in = KW_DEF("in");
|
||||
kw_out = KW_DEF("out");
|
||||
@@ -152,7 +152,6 @@ void symtab_init(uint32_t capacity)
|
||||
kw_ordinal = KW_DEF("ordinal");
|
||||
kw_ptr = KW_DEF("ptr");
|
||||
kw_pure = KW_DEF("pure");
|
||||
KW_DEF("require");
|
||||
kw_std = KW_DEF("std");
|
||||
kw_values = KW_DEF("values");
|
||||
kw_incr = KW_DEF("incr");
|
||||
|
||||
@@ -1049,7 +1049,6 @@ static inline Type *func_create_new_func_proto(FunctionSignature *sig, CallABI a
|
||||
}
|
||||
c_abi_func_create(proto);
|
||||
|
||||
|
||||
Type *type = type_new(TYPE_FUNC, "#Function");
|
||||
type->func.prototype = proto;
|
||||
type->canonical = type;
|
||||
|
||||
@@ -27,6 +27,8 @@ int main_real(int argc, const char *argv[])
|
||||
{
|
||||
bench_begin();
|
||||
|
||||
// Setjmp will allow us to add things like fuzzing with
|
||||
// easy restarts.
|
||||
int result = setjmp(on_error_jump);
|
||||
if (result)
|
||||
{
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.2.6"
|
||||
#define COMPILER_VERSION "0.2.7"
|
||||
@@ -229,8 +229,14 @@ class Issues:
|
||||
lines = reader.read().splitlines()
|
||||
searched_line = 0
|
||||
current_line = 0
|
||||
while searched_line < len(file.expected_lines):
|
||||
total_lines = len(file.expected_lines)
|
||||
while searched_line < total_lines:
|
||||
line = file.expected_lines[searched_line].strip()
|
||||
next_line = None
|
||||
if searched_line + 1 < total_lines:
|
||||
alt_line = file.expected_lines[searched_line + 1].strip()
|
||||
if alt_line.startswith("??"):
|
||||
next_line = alt_line[2:].strip()
|
||||
if line == "":
|
||||
searched_line += 1
|
||||
continue
|
||||
@@ -243,8 +249,11 @@ class Issues:
|
||||
current_line += 1
|
||||
searched_line += 1
|
||||
continue
|
||||
if next_line != None and next_line in lines[current_line]:
|
||||
current_line += 1
|
||||
searched_line += 2
|
||||
continue
|
||||
current_line += 1
|
||||
|
||||
if not self.has_errors:
|
||||
self.conf.numsuccess += 1
|
||||
print(" Passed.")
|
||||
|
||||
@@ -21,9 +21,9 @@ fn int main()
|
||||
|
||||
%Foo = type { [2 x float] }
|
||||
|
||||
$introspect.Foo = comdat any
|
||||
$.typeid.test.Foo = comdat any
|
||||
|
||||
@introspect.Foo = linkonce constant i8 1
|
||||
@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 1 }, comdat, align 8
|
||||
|
||||
declare void @printf(i8*, ...) #0
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ if.then: ; preds = %entry
|
||||
ret void
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
call void @"std::builtin.panic"(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i32 0, i32 0), i32 10)
|
||||
call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i32 0, i32 0), i32 10)
|
||||
unreachable
|
||||
|
||||
after.unreachable: ; No predecessors!
|
||||
|
||||
@@ -28,7 +28,7 @@ fn void main() @TestZero
|
||||
|
||||
%Foo = type { i32, [1020 x i8], i32, [1020 x i8] }
|
||||
|
||||
@introspect.Foo = linkonce constant i8 1
|
||||
@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@test.f = local_unnamed_addr global %Foo zeroinitializer, align 1024
|
||||
|
||||
define void @test.testme() #0 {
|
||||
|
||||
@@ -18,12 +18,11 @@ fn void main()
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
@"test.Foo$elements" = linkonce constant [2 x i8*] zeroinitializer
|
||||
@"test.Foo$$val" = constant [2 x i32] [i32 123, i32 333]
|
||||
@.typeid.test.Foo = linkonce constant { i8, i64, i64 } { i8 8, i64 2, i64 2 }, align 8
|
||||
@test.Foo.val = linkonce constant [2 x i32] [i32 123, i32 333], align 4
|
||||
@.str = private unnamed_addr constant [9 x i8] c"Number A\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [9 x i8] c"Number B\00", align 1
|
||||
@"test.Foo$$testme" = constant [2 x i8*] [i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i32 0, i32 0)]
|
||||
@introspect.Foo = linkonce constant i8 1
|
||||
@test.Foo.testme = linkonce constant [2 x i8*] [i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i32 0, i32 0)], align 8
|
||||
@.str.2 = private unnamed_addr constant [17 x i8] c"%d (%s) %d (%s)\0A\00", align 1
|
||||
|
||||
; Function Attrs: nounwind
|
||||
@@ -36,16 +35,16 @@ entry:
|
||||
store i32 1, i32* %f, align 4
|
||||
store i32 0, i32* %g, align 4
|
||||
%0 = load i32, i32* %f, align 4
|
||||
%1 = getelementptr inbounds [2 x i32], [2 x i32]* @"test.Foo$$val", i32 0, i32 %0
|
||||
%1 = getelementptr inbounds [2 x i32], [2 x i32]* @test.Foo.val, i32 0, i32 %0
|
||||
%2 = load i32, i32* %1, align 4
|
||||
%3 = load i32, i32* %f, align 4
|
||||
%4 = getelementptr inbounds [2 x i8*], [2 x i8*]* @"test.Foo$$testme", i32 0, i32 %3
|
||||
%4 = getelementptr inbounds [2 x i8*], [2 x i8*]* @test.Foo.testme, i32 0, i32 %3
|
||||
%5 = load i8*, i8** %4, align 8
|
||||
%6 = load i32, i32* %g, align 4
|
||||
%7 = getelementptr inbounds [2 x i32], [2 x i32]* @"test.Foo$$val", i32 0, i32 %6
|
||||
%7 = getelementptr inbounds [2 x i32], [2 x i32]* @test.Foo.val, i32 0, i32 %6
|
||||
%8 = load i32, i32* %7, align 4
|
||||
%9 = load i32, i32* %g, align 4
|
||||
%10 = getelementptr inbounds [2 x i8*], [2 x i8*]* @"test.Foo$$testme", i32 0, i32 %9
|
||||
%10 = getelementptr inbounds [2 x i8*], [2 x i8*]* @test.Foo.testme, i32 0, i32 %9
|
||||
%11 = load i8*, i8** %10, align 8
|
||||
%12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.2, i32 0, i32 0), i32 %2, i8* %5, i32 %8, i8* %11)
|
||||
ret void
|
||||
|
||||
@@ -29,7 +29,7 @@ fn void main()
|
||||
; Function Attrs: nounwind
|
||||
define i64 @anyerr_void.errorThing() #0 {
|
||||
entry:
|
||||
ret i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"anyerr_void.MyError$elements", i64 0, i64 1) to i64)
|
||||
ret i64 ptrtoint (i8* @anyerr_void.MyError.BAR to i64)
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
@@ -65,8 +65,8 @@ noerr_block: ; preds = %after.errcheck, %er
|
||||
store i64 %1, i64* %z, align 8
|
||||
%2 = load i64, i64* %z, align 8
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i64 %2)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"anyerr_void.MyError$elements", i64 0, i64 1) to i64))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), i64 ptrtoint ([2 x i8*]* @"anyerr_void.MyError$elements" to i64))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), i64 ptrtoint (i8* @anyerr_void.MyError.BAR to i64))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), i64 ptrtoint (i8* @anyerr_void.MyError.FOO to i64))
|
||||
store i64 0, i64* %error_var1, align 8
|
||||
%3 = call i64 @anyerr_void.errorThing2()
|
||||
%not_err2 = icmp eq i64 %3, 0
|
||||
|
||||
22
test/test_suite/errors/error_else.c3t
Normal file
22
test/test_suite/errors/error_else.c3t
Normal file
@@ -0,0 +1,22 @@
|
||||
module foo;
|
||||
|
||||
fault Baz
|
||||
{
|
||||
TEST
|
||||
}
|
||||
|
||||
module bar;
|
||||
import foo;
|
||||
|
||||
fn int! abc()
|
||||
{
|
||||
return Baz.TEST!;
|
||||
}
|
||||
|
||||
module baz;
|
||||
import foo;
|
||||
|
||||
fn int! abc()
|
||||
{
|
||||
return Baz.TEST!;
|
||||
}
|
||||
@@ -318,7 +318,7 @@ entry:
|
||||
br i1 %12, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %entry
|
||||
ret i64 ptrtoint ([2 x i8*]* @"test.ReadError$elements" to i64)
|
||||
ret i64 ptrtoint (i8* @test.ReadError.BAD_READ to i64)
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
%13 = bitcast %"char[]"* %url to { i8*, i64 }*
|
||||
@@ -366,7 +366,7 @@ if.then15: ; preds = %if.exit9
|
||||
store %"char[]"* null, %"char[]"** %33, align 8
|
||||
%34 = load %Head, %Head* %literal18, align 8
|
||||
store %Head %34, %Head* %value, align 8
|
||||
%35 = call i8* @"std::mem.alloc"(i64 8, i64 0)
|
||||
%35 = call i8* @"std::core::mem.alloc"(i64 8, i64 0)
|
||||
%ptrptr = bitcast i8* %35 to %Head*
|
||||
store %Head* %ptrptr, %Head** %temp, align 8
|
||||
%36 = load %Head*, %Head** %temp, align 8
|
||||
@@ -374,7 +374,7 @@ if.then15: ; preds = %if.exit9
|
||||
br i1 %not, label %if.then19, label %if.exit20
|
||||
|
||||
if.then19: ; preds = %if.then15
|
||||
store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var, align 8
|
||||
store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var, align 8
|
||||
br label %guard_block
|
||||
|
||||
if.exit20: ; preds = %if.then15
|
||||
@@ -418,7 +418,7 @@ if.then27: ; preds = %if.exit21
|
||||
store %"char[]"* null, %"char[]"** %53, align 8
|
||||
%54 = getelementptr inbounds %Head, %Head* %literal32, i32 0, i32 0
|
||||
store %"char[]" { i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.4, i32 0, i32 0), i64 0 }, %"char[]"* %value34, align 8
|
||||
%55 = call i8* @"std::mem.alloc"(i64 16, i64 0)
|
||||
%55 = call i8* @"std::core::mem.alloc"(i64 16, i64 0)
|
||||
%ptrptr36 = bitcast i8* %55 to %"char[]"*
|
||||
store %"char[]"* %ptrptr36, %"char[]"** %temp35, align 8
|
||||
%56 = load %"char[]"*, %"char[]"** %temp35, align 8
|
||||
@@ -426,7 +426,7 @@ if.then27: ; preds = %if.exit21
|
||||
br i1 %not37, label %if.then38, label %if.exit39
|
||||
|
||||
if.then38: ; preds = %if.then27
|
||||
store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var33, align 8
|
||||
store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var33, align 8
|
||||
br label %guard_block40
|
||||
|
||||
if.exit39: ; preds = %if.then27
|
||||
@@ -445,7 +445,7 @@ noerr_block41: ; preds = %if.exit39
|
||||
store %"char[]"* %61, %"char[]"** %54, align 8
|
||||
%62 = load %Head, %Head* %literal32, align 8
|
||||
store %Head %62, %Head* %value31, align 8
|
||||
%63 = call i8* @"std::mem.alloc"(i64 8, i64 0)
|
||||
%63 = call i8* @"std::core::mem.alloc"(i64 8, i64 0)
|
||||
%ptrptr43 = bitcast i8* %63 to %Head*
|
||||
store %Head* %ptrptr43, %Head** %temp42, align 8
|
||||
%64 = load %Head*, %Head** %temp42, align 8
|
||||
@@ -453,7 +453,7 @@ noerr_block41: ; preds = %if.exit39
|
||||
br i1 %not44, label %if.then45, label %if.exit46
|
||||
|
||||
if.then45: ; preds = %noerr_block41
|
||||
store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var30, align 8
|
||||
store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var30, align 8
|
||||
br label %guard_block47
|
||||
|
||||
if.exit46: ; preds = %noerr_block41
|
||||
@@ -486,14 +486,14 @@ if.exit49: ; preds = %if.exit21
|
||||
%77 = load i32, i32* %len, align 4
|
||||
%siuiext = sext i32 %77 to i64
|
||||
%add = add i64 %siuiext, 1
|
||||
%78 = call i8* @"std::mem.alloc"(i64 %add, i64 0)
|
||||
%78 = call i8* @"std::core::mem.alloc"(i64 %add, i64 0)
|
||||
store i8* %78, i8** %str, align 8
|
||||
%79 = load i8*, i8** %str, align 8
|
||||
%not50 = icmp eq i8* %79, null
|
||||
br i1 %not50, label %if.then51, label %if.exit52
|
||||
|
||||
if.then51: ; preds = %if.exit49
|
||||
ret i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64)
|
||||
ret i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64)
|
||||
|
||||
if.exit52: ; preds = %if.exit49
|
||||
%80 = load i8*, i8** %str, align 8
|
||||
@@ -520,7 +520,7 @@ if.exit52: ; preds = %if.exit49
|
||||
%93 = insertvalue %"char[]" undef, i8* %ptroffset, 0
|
||||
%94 = insertvalue %"char[]" %93, i64 %size, 1
|
||||
store %"char[]" %94, %"char[]"* %value62, align 8
|
||||
%95 = call i8* @"std::mem.alloc"(i64 16, i64 0)
|
||||
%95 = call i8* @"std::core::mem.alloc"(i64 16, i64 0)
|
||||
%ptrptr64 = bitcast i8* %95 to %"char[]"*
|
||||
store %"char[]"* %ptrptr64, %"char[]"** %temp63, align 8
|
||||
%96 = load %"char[]"*, %"char[]"** %temp63, align 8
|
||||
@@ -528,7 +528,7 @@ if.exit52: ; preds = %if.exit49
|
||||
br i1 %not65, label %if.then66, label %if.exit67
|
||||
|
||||
if.then66: ; preds = %if.exit52
|
||||
store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var61, align 8
|
||||
store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var61, align 8
|
||||
br label %guard_block68
|
||||
|
||||
if.exit67: ; preds = %if.exit52
|
||||
@@ -547,7 +547,7 @@ noerr_block69: ; preds = %if.exit67
|
||||
store %"char[]"* %101, %"char[]"** %89, align 8
|
||||
%102 = load %Head, %Head* %literal60, align 8
|
||||
store %Head %102, %Head* %value59, align 8
|
||||
%103 = call i8* @"std::mem.alloc"(i64 8, i64 0)
|
||||
%103 = call i8* @"std::core::mem.alloc"(i64 8, i64 0)
|
||||
%ptrptr71 = bitcast i8* %103 to %Head*
|
||||
store %Head* %ptrptr71, %Head** %temp70, align 8
|
||||
%104 = load %Head*, %Head** %temp70, align 8
|
||||
@@ -555,7 +555,7 @@ noerr_block69: ; preds = %if.exit67
|
||||
br i1 %not72, label %if.then73, label %if.exit74
|
||||
|
||||
if.then73: ; preds = %noerr_block69
|
||||
store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), i64* %error_var58, align 8
|
||||
store i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), i64* %error_var58, align 8
|
||||
br label %guard_block75
|
||||
|
||||
if.exit74: ; preds = %noerr_block69
|
||||
@@ -683,7 +683,7 @@ entry:
|
||||
br i1 %not, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %entry
|
||||
ret i64 ptrtoint ([1 x i8*]* @"test.TitleResult$elements" to i64)
|
||||
ret i64 ptrtoint (i8* @test.TitleResult.TITLE_MISSING to i64)
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
%5 = getelementptr inbounds %Doc, %Doc* %doc, i32 0, i32 0
|
||||
@@ -696,7 +696,7 @@ if.exit: ; preds = %entry
|
||||
br i1 %not1, label %if.then2, label %if.exit3
|
||||
|
||||
if.then2: ; preds = %if.exit
|
||||
ret i64 ptrtoint ([1 x i8*]* @"test.TitleResult$elements" to i64)
|
||||
ret i64 ptrtoint (i8* @test.TitleResult.TITLE_MISSING to i64)
|
||||
|
||||
if.exit3: ; preds = %if.exit
|
||||
%10 = load %"char[]"*, %"char[]"** %head, align 8
|
||||
@@ -770,21 +770,21 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%1 = load i64, i64* %switch, align 8
|
||||
%eq = icmp eq i64 ptrtoint ([1 x i8*]* @"test.TitleResult$elements" to i64), %1
|
||||
%eq = icmp eq i64 ptrtoint (i8* @test.TitleResult.TITLE_MISSING to i64), %1
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
ret i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.9, i32 0, i32 0)
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq1 = icmp eq i64 ptrtoint ([2 x i8*]* @"test.ReadError$elements" to i64), %1
|
||||
%eq1 = icmp eq i64 ptrtoint (i8* @test.ReadError.BAD_READ to i64), %1
|
||||
br i1 %eq1, label %switch.case2, label %next_if3
|
||||
|
||||
switch.case2: ; preds = %next_if
|
||||
ret i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.10, i32 0, i32 0)
|
||||
|
||||
next_if3: ; preds = %next_if
|
||||
%eq4 = icmp eq i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"test.ReadError$elements", i64 0, i64 1) to i64), %1
|
||||
%eq4 = icmp eq i64 ptrtoint (i8* @test.ReadError.OUT_OF_MEMORY to i64), %1
|
||||
br i1 %eq4, label %switch.case5, label %next_if6
|
||||
|
||||
switch.case5: ; preds = %next_if3
|
||||
|
||||
@@ -39,7 +39,8 @@ entry:
|
||||
%x.f = alloca i64, align 8
|
||||
%y = alloca %Bar, align 4
|
||||
%error_var = alloca i64, align 8
|
||||
store i64 ptrtoint ([2 x i8*]* @"test.Foo$elements" to i64), i64* %x.f, align 8
|
||||
%reterr = alloca i64, align 8
|
||||
store i64 ptrtoint (i8* @test.Foo.MY_VAL1 to i64), i64* %x.f, align 8
|
||||
%0 = load i64, i64* %x.f, align 8
|
||||
%not_err = icmp eq i64 %0, 0
|
||||
br i1 %not_err, label %after_check, label %error
|
||||
@@ -68,6 +69,7 @@ entry:
|
||||
%x.f = alloca i64, align 8
|
||||
%y = alloca %Bar, align 4
|
||||
%error_var = alloca i64, align 8
|
||||
%reterr = alloca i64, align 8
|
||||
%0 = bitcast %Bar* %x to i32*
|
||||
store i32 0, i32* %0, align 4
|
||||
store i64 0, i64* %x.f, align 8
|
||||
|
||||
@@ -27,9 +27,9 @@ fn void main()
|
||||
|
||||
%Foo = type { i32, i32 }
|
||||
|
||||
@introspect.Foo = linkonce constant i8 1
|
||||
@"test.MyErr$elements" = linkonce constant [1 x i8*] zeroinitializer
|
||||
@introspect.MyErr = linkonce constant i8 1
|
||||
@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@test.MyErr.FOO = linkonce constant i8 1, align 1
|
||||
@.typeid.test.MyErr = linkonce constant { i8, i64, [1 x i64] } { i8 9, i64 1, [1 x i64] [i64 ptrtoint (i8* @test.MyErr.FOO to i64)] }, align 8
|
||||
@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [17 x i8] c"Not visible: %d\0A\00", align 1
|
||||
|
||||
@@ -78,7 +78,7 @@ after_check2: ; preds = %after_assign
|
||||
br label %voiderr
|
||||
|
||||
voiderr: ; preds = %after_check2, %after_assign
|
||||
store i64 ptrtoint ([1 x i8*]* @"test.MyErr$elements" to i64), i64* %z.f, align 8
|
||||
store i64 ptrtoint (i8* @test.MyErr.FOO to i64), i64* %z.f, align 8
|
||||
br label %voiderr3
|
||||
|
||||
voiderr3: ; preds = %voiderr
|
||||
|
||||
@@ -70,7 +70,7 @@ fn void main()
|
||||
a.hello();
|
||||
}
|
||||
|
||||
// #expect: foo.ll
|
||||
/* #expect: foo.ll
|
||||
|
||||
define void @foo.Foo__hello(i64* %0) #0 {
|
||||
entry:
|
||||
@@ -98,8 +98,8 @@ entry:
|
||||
%z = alloca i64, align 8
|
||||
%b = alloca i32, align 4
|
||||
%a = alloca i32, align 4
|
||||
store i64 ptrtoint ([5 x i8*]* @"foo.Foo$elements" to i64), i64* %f, align 8
|
||||
store i64 ptrtoint (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 0, i64 1) to i64), i64* %ef, align 8
|
||||
store i64 ptrtoint (i8* @foo.Foo.X to i64), i64* %f, align 8
|
||||
store i64 ptrtoint (i8* @foo.Foo.Y to i64), i64* %ef, align 8
|
||||
%0 = load i64, i64* %f, align 8
|
||||
store i64 %0, i64* %x, align 8
|
||||
%1 = load i64, i64* %x, align 8
|
||||
@@ -112,22 +112,22 @@ entry:
|
||||
store i64 %5, i64* %z, align 8
|
||||
%6 = load i64, i64* %z, align 8
|
||||
%7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0), i64 %6)
|
||||
store i64 ptrtoint (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 0, i64 3) to i64), i64* %x, align 8
|
||||
store i64 ptrtoint (i8* @foo.Foo.W to i64), i64* %x, align 8
|
||||
%8 = load i64, i64* %x, align 8
|
||||
store i64 %8, i64* %z, align 8
|
||||
%9 = load i64, i64* %z, align 8
|
||||
%10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i64 %9)
|
||||
store i64 ptrtoint (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @"foo.Foo$elements", i64 0, i64 4) to i64), i64* %x, align 8
|
||||
store i64 ptrtoint (i8* @foo.Foo.W1 to i64), i64* %x, align 8
|
||||
%11 = load i64, i64* %x, align 8
|
||||
store i64 %11, i64* %z, align 8
|
||||
%12 = load i64, i64* %z, align 8
|
||||
%13 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.3, i32 0, i32 0), i64 %12)
|
||||
store i64 ptrtoint ([2 x i8*]* @"foo.Foob$elements" to i64), i64* %x, align 8
|
||||
store i64 ptrtoint (i8* @foo.Foob.X1 to i64), i64* %x, align 8
|
||||
%14 = load i64, i64* %x, align 8
|
||||
store i64 %14, i64* %z, align 8
|
||||
%15 = load i64, i64* %z, align 8
|
||||
%16 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0), i64 %15)
|
||||
store i64 ptrtoint (i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"foo.Foob$elements", i64 0, i64 1) to i64), i64* %x, align 8
|
||||
store i64 ptrtoint (i8* @foo.Foob.Y2 to i64), i64* %x, align 8
|
||||
%17 = load i64, i64* %x, align 8
|
||||
store i64 %17, i64* %z, align 8
|
||||
%18 = load i64, i64* %z, align 8
|
||||
|
||||
@@ -23,7 +23,7 @@ fn void main()
|
||||
|
||||
define i64 @test.abc(i32* %0) #0 {
|
||||
entry:
|
||||
ret i64 ptrtoint ([1 x i8*]* @"test.Tester$elements" to i64)
|
||||
ret i64 ptrtoint (i8* @test.Tester.FOO to i64)
|
||||
}
|
||||
|
||||
define void @test.main() #0 {
|
||||
|
||||
@@ -13,12 +13,12 @@ fn void main()
|
||||
int! i = Blurg.Y!;
|
||||
}
|
||||
|
||||
// #expect: foo.ll
|
||||
/* #expect: foo.ll
|
||||
|
||||
define void @foo.main() #0 {
|
||||
entry:
|
||||
%i = alloca i32, align 4
|
||||
%i.f = alloca i64, align 8
|
||||
store i64 ptrtoint ([1 x i8*]* @"foo.Blurg$elements" to i64), i64* %i.f, align 8
|
||||
store i64 ptrtoint (i8* @foo.Blurg.Y to i64), i64* %i.f, align 8
|
||||
ret void
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
// #target: macos-x64
|
||||
extern fn void printf(char* c, ...);
|
||||
|
||||
struct ExtraSimple
|
||||
@@ -42,10 +42,10 @@ fn void testSimple()
|
||||
%anon = type { i32, i32 }
|
||||
%anon.0 = type { double }
|
||||
|
||||
@introspect.c = linkonce constant i8 1
|
||||
@introspect.anon = linkonce constant i8 1
|
||||
@introspect.anon.1 = linkonce constant i8 1
|
||||
@introspect.ExtraSimple = linkonce constant i8 1
|
||||
@.typeid.pointer_access.c = linkonce constant { i8, i64 } { i8 10, i64 5 }, align 8
|
||||
@.typeid.pointer_access.anon = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@.typeid.pointer_access.anon.1 = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8
|
||||
@.typeid.pointer_access.ExtraSimple = linkonce constant { i8, i64 } { i8 10, i64 6 }, align 8
|
||||
@.str = private unnamed_addr constant [71 x i8] c"a = %d, c.e = %f, c.f = %f, c.j = %f, g = %d, o0 = %f, r = %d, s = %d\0A\00", align 1
|
||||
|
||||
define void @pointer_access.testSimple() #0 {
|
||||
|
||||
@@ -33,144 +33,144 @@ fn int main()
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
%a = alloca i32, align 4
|
||||
%a.f = alloca i64, align 8
|
||||
%x = alloca i32, align 4
|
||||
%blockret = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
%b.f = alloca i64, align 8
|
||||
%x1 = alloca i32, align 4
|
||||
%blockret2 = alloca i32, align 4
|
||||
%c = alloca i32, align 4
|
||||
%c.f = alloca i64, align 8
|
||||
%x8 = alloca i32, align 4
|
||||
%blockret9 = alloca i32, align 4
|
||||
store i32 1, i32* %x, align 4
|
||||
%0 = load i32, i32* %x, align 4
|
||||
%intbool = icmp ne i32 %0, 0
|
||||
br i1 %intbool, label %if.then, label %if.exit
|
||||
%a.f = alloca i64, align 8
|
||||
%x = alloca i32, align 4
|
||||
%blockret = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
%b.f = alloca i64, align 8
|
||||
%x1 = alloca i32, align 4
|
||||
%blockret2 = alloca i32, align 4
|
||||
%c = alloca i32, align 4
|
||||
%c.f = alloca i64, align 8
|
||||
%x8 = alloca i32, align 4
|
||||
%blockret9 = alloca i32, align 4
|
||||
store i32 1, i32* %x, align 4
|
||||
%0 = load i32, i32* %x, align 4
|
||||
%intbool = icmp ne i32 %0, 0
|
||||
br i1 %intbool, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %entry
|
||||
%1 = load i32, i32* %x, align 4
|
||||
store i32 %1, i32* %blockret, align 4
|
||||
br label %expr_block.exit
|
||||
if.then: ; preds = %entry
|
||||
%1 = load i32, i32* %x, align 4
|
||||
store i32 %1, i32* %blockret, align 4
|
||||
br label %expr_block.exit
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %a.f, align 8
|
||||
br label %after_assign
|
||||
if.exit: ; preds = %entry
|
||||
store i64 ptrtoint (i8* @failable_catch.MyErr.TEST to i64), i64* %a.f, align 8
|
||||
br label %after_assign
|
||||
|
||||
expr_block.exit: ; preds = %if.then
|
||||
%2 = load i32, i32* %blockret, align 4
|
||||
store i32 %2, i32* %a, align 4
|
||||
store i64 0, i64* %a.f, align 8
|
||||
br label %after_assign
|
||||
expr_block.exit: ; preds = %if.then
|
||||
%2 = load i32, i32* %blockret, align 4
|
||||
store i32 %2, i32* %a, align 4
|
||||
store i64 0, i64* %a.f, align 8
|
||||
br label %after_assign
|
||||
|
||||
after_assign: ; preds = %expr_block.exit, %if.exit
|
||||
%3 = load i64, i64* %a.f, align 8
|
||||
%not_err = icmp eq i64 %3, 0
|
||||
br i1 %not_err, label %after_check, label %else_block
|
||||
after_assign: ; preds = %expr_block.exit, %if.exit
|
||||
%3 = load i64, i64* %a.f, align 8
|
||||
%not_err = icmp eq i64 %3, 0
|
||||
br i1 %not_err, label %after_check, label %else_block
|
||||
|
||||
after_check: ; preds = %after_assign
|
||||
%4 = load i32, i32* %a, align 4
|
||||
%add = add i32 %4, 3
|
||||
br label %phi_block
|
||||
after_check: ; preds = %after_assign
|
||||
%4 = load i32, i32* %a, align 4
|
||||
%add = add i32 %4, 3
|
||||
br label %phi_block
|
||||
|
||||
else_block: ; preds = %after_assign
|
||||
br label %phi_block
|
||||
else_block: ; preds = %after_assign
|
||||
br label %phi_block
|
||||
|
||||
phi_block: ; preds = %else_block, %after_check
|
||||
%val = phi i32 [ %add, %after_check ], [ 2, %else_block ]
|
||||
store i32 %val, i32* %x1, align 4
|
||||
%5 = load i32, i32* %x1, align 4
|
||||
%intbool3 = icmp ne i32 %5, 0
|
||||
br i1 %intbool3, label %if.then4, label %if.exit5
|
||||
phi_block: ; preds = %else_block, %after_check
|
||||
%val = phi i32 [ %add, %after_check ], [ 2, %else_block ]
|
||||
store i32 %val, i32* %x1, align 4
|
||||
%5 = load i32, i32* %x1, align 4
|
||||
%intbool3 = icmp ne i32 %5, 0
|
||||
br i1 %intbool3, label %if.then4, label %if.exit5
|
||||
|
||||
if.then4: ; preds = %phi_block
|
||||
%6 = load i32, i32* %x1, align 4
|
||||
store i32 %6, i32* %blockret2, align 4
|
||||
br label %expr_block.exit6
|
||||
if.then4: ; preds = %phi_block
|
||||
%6 = load i32, i32* %x1, align 4
|
||||
store i32 %6, i32* %blockret2, align 4
|
||||
br label %expr_block.exit6
|
||||
|
||||
if.exit5: ; preds = %phi_block
|
||||
store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %b.f, align 8
|
||||
br label %after_assign7
|
||||
if.exit5: ; preds = %phi_block
|
||||
store i64 ptrtoint (i8* @failable_catch.MyErr.TEST to i64), i64* %b.f, align 8
|
||||
br label %after_assign7
|
||||
|
||||
expr_block.exit6: ; preds = %if.then4
|
||||
%7 = load i32, i32* %blockret2, align 4
|
||||
store i32 %7, i32* %b, align 4
|
||||
store i64 0, i64* %b.f, align 8
|
||||
br label %after_assign7
|
||||
expr_block.exit6: ; preds = %if.then4
|
||||
%7 = load i32, i32* %blockret2, align 4
|
||||
store i32 %7, i32* %b, align 4
|
||||
store i64 0, i64* %b.f, align 8
|
||||
br label %after_assign7
|
||||
|
||||
after_assign7: ; preds = %expr_block.exit6, %if.exit5
|
||||
store i32 0, i32* %x8, align 4
|
||||
%8 = load i32, i32* %x8, align 4
|
||||
%intbool10 = icmp ne i32 %8, 0
|
||||
br i1 %intbool10, label %if.then11, label %if.exit12
|
||||
after_assign7: ; preds = %expr_block.exit6, %if.exit5
|
||||
store i32 0, i32* %x8, align 4
|
||||
%8 = load i32, i32* %x8, align 4
|
||||
%intbool10 = icmp ne i32 %8, 0
|
||||
br i1 %intbool10, label %if.then11, label %if.exit12
|
||||
|
||||
if.then11: ; preds = %after_assign7
|
||||
%9 = load i32, i32* %x8, align 4
|
||||
store i32 %9, i32* %blockret9, align 4
|
||||
br label %expr_block.exit13
|
||||
if.then11: ; preds = %after_assign7
|
||||
%9 = load i32, i32* %x8, align 4
|
||||
store i32 %9, i32* %blockret9, align 4
|
||||
br label %expr_block.exit13
|
||||
|
||||
if.exit12: ; preds = %after_assign7
|
||||
store i64 ptrtoint ([1 x i8*]* @"failable_catch.MyErr$elements" to i64), i64* %c.f, align 8
|
||||
br label %after_assign14
|
||||
if.exit12: ; preds = %after_assign7
|
||||
store i64 ptrtoint (i8* @failable_catch.MyErr.TEST to i64), i64* %c.f, align 8
|
||||
br label %after_assign14
|
||||
|
||||
expr_block.exit13: ; preds = %if.then11
|
||||
%10 = load i32, i32* %blockret9, align 4
|
||||
store i32 %10, i32* %c, align 4
|
||||
store i64 0, i64* %c.f, align 8
|
||||
br label %after_assign14
|
||||
expr_block.exit13: ; preds = %if.then11
|
||||
%10 = load i32, i32* %blockret9, align 4
|
||||
store i32 %10, i32* %c, align 4
|
||||
store i64 0, i64* %c.f, align 8
|
||||
br label %after_assign14
|
||||
|
||||
after_assign14: ; preds = %expr_block.exit13, %if.exit12
|
||||
%11 = load i64, i64* %a.f, align 8
|
||||
%not_err15 = icmp eq i64 %11, 0
|
||||
br i1 %not_err15, label %after_check16, label %voiderr
|
||||
after_assign14: ; preds = %expr_block.exit13, %if.exit12
|
||||
%11 = load i64, i64* %a.f, align 8
|
||||
%not_err15 = icmp eq i64 %11, 0
|
||||
br i1 %not_err15, label %after_check16, label %voiderr
|
||||
|
||||
after_check16: ; preds = %after_assign14
|
||||
%12 = load i32, i32* %a, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 %12)
|
||||
br label %voiderr
|
||||
after_check16: ; preds = %after_assign14
|
||||
%12 = load i32, i32* %a, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 %12)
|
||||
br label %voiderr
|
||||
|
||||
voiderr: ; preds = %after_check16, %after_assign14
|
||||
%13 = load i64, i64* %b.f, align 8
|
||||
%not_err17 = icmp eq i64 %13, 0
|
||||
br i1 %not_err17, label %after_check18, label %voiderr19
|
||||
voiderr: ; preds = %after_check16, %after_assign14
|
||||
%13 = load i64, i64* %b.f, align 8
|
||||
%not_err17 = icmp eq i64 %13, 0
|
||||
br i1 %not_err17, label %after_check18, label %voiderr19
|
||||
|
||||
after_check18: ; preds = %voiderr
|
||||
%14 = load i32, i32* %b, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 %14)
|
||||
br label %voiderr19
|
||||
after_check18: ; preds = %voiderr
|
||||
%14 = load i32, i32* %b, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 %14)
|
||||
br label %voiderr19
|
||||
|
||||
voiderr19: ; preds = %after_check18, %voiderr
|
||||
%15 = load i64, i64* %c.f, align 8
|
||||
%not_err20 = icmp eq i64 %15, 0
|
||||
br i1 %not_err20, label %after_check21, label %voiderr22
|
||||
voiderr19: ; preds = %after_check18, %voiderr
|
||||
%15 = load i64, i64* %c.f, align 8
|
||||
%not_err20 = icmp eq i64 %15, 0
|
||||
br i1 %not_err20, label %after_check21, label %voiderr22
|
||||
|
||||
after_check21: ; preds = %voiderr19
|
||||
%16 = load i32, i32* %c, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i32 %16)
|
||||
br label %voiderr22
|
||||
after_check21: ; preds = %voiderr19
|
||||
%16 = load i32, i32* %c, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i32 %16)
|
||||
br label %voiderr22
|
||||
|
||||
voiderr22: ; preds = %after_check21, %voiderr19
|
||||
%17 = load i64, i64* %c.f, align 8
|
||||
%neq = icmp ne i64 %17, 0
|
||||
br i1 %neq, label %if.then23, label %if.exit24
|
||||
voiderr22: ; preds = %after_check21, %voiderr19
|
||||
%17 = load i64, i64* %c.f, align 8
|
||||
%neq = icmp ne i64 %17, 0
|
||||
br i1 %neq, label %if.then23, label %if.exit24
|
||||
|
||||
if.then23: ; preds = %voiderr22
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i32 0, i32 0))
|
||||
br label %if.exit24
|
||||
if.then23: ; preds = %voiderr22
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i32 0, i32 0))
|
||||
br label %if.exit24
|
||||
|
||||
if.exit24: ; preds = %if.then23, %voiderr22
|
||||
store i32 3, i32* %c, align 4
|
||||
store i64 0, i64* %c.f, align 8
|
||||
%18 = load i64, i64* %c.f, align 8
|
||||
%not_err25 = icmp eq i64 %18, 0
|
||||
br i1 %not_err25, label %after_check26, label %voiderr27
|
||||
if.exit24: ; preds = %if.then23, %voiderr22
|
||||
store i32 3, i32* %c, align 4
|
||||
store i64 0, i64* %c.f, align 8
|
||||
%18 = load i64, i64* %c.f, align 8
|
||||
%not_err25 = icmp eq i64 %18, 0
|
||||
br i1 %not_err25, label %after_check26, label %voiderr27
|
||||
|
||||
after_check26: ; preds = %if.exit24
|
||||
%19 = load i32, i32* %c, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.4, i32 0, i32 0), i32 %19)
|
||||
br label %voiderr27
|
||||
after_check26: ; preds = %if.exit24
|
||||
%19 = load i32, i32* %c, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.4, i32 0, i32 0), i32 %19)
|
||||
br label %voiderr27
|
||||
|
||||
voiderr27: ; preds = %after_check26, %if.exit24
|
||||
ret i32 0
|
||||
}
|
||||
voiderr27: ; preds = %after_check26, %if.exit24
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// #target: macos-x64
|
||||
module examples;
|
||||
import libc;
|
||||
import std;
|
||||
import std::io;
|
||||
|
||||
fn void example_for()
|
||||
{
|
||||
@@ -110,7 +110,7 @@ loop.body: ; preds = %loop.cond
|
||||
br label %loop.cond
|
||||
|
||||
loop.exit: ; preds = %loop.cond
|
||||
call void @"std::builtin.panic"(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.zstr.2, i64 0, i64 0), i32 14)
|
||||
call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.zstr.2, i64 0, i64 0), i32 14)
|
||||
unreachable
|
||||
|
||||
unreachable_block: ; No predecessors!
|
||||
|
||||
@@ -54,7 +54,7 @@ entry:
|
||||
br i1 %eq, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %entry
|
||||
ret i64 ptrtoint ([1 x i8*]* @"demo.MathError$elements" to i64)
|
||||
ret i64 ptrtoint (i8* @demo.MathError.DIVISION_BY_ZERO to i64)
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
%sifp = sitofp i32 %1 to double
|
||||
@@ -114,7 +114,6 @@ after.errcheck: ; preds = %entry
|
||||
br label %after_assign
|
||||
|
||||
after_assign: ; preds = %after.errcheck, %error
|
||||
store i64 0, i64* %err, align 8
|
||||
br label %testblock
|
||||
|
||||
testblock: ; preds = %after_assign
|
||||
@@ -141,7 +140,7 @@ if.then: ; preds = %end_block
|
||||
|
||||
switch.entry: ; preds = %if.then
|
||||
%6 = load i64, i64* %switch, align 8
|
||||
%eq = icmp eq i64 ptrtoint ([1 x i8*]* @"demo.MathError$elements" to i64), %6
|
||||
%eq = icmp eq i64 ptrtoint (i8* @demo.MathError.DIVISION_BY_ZERO to i64), %6
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
|
||||
@@ -234,8 +234,8 @@ fn Type getValue(Blob blob)
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
%Blob.0 = type { i32 }
|
||||
%Blob.1 = type { double }
|
||||
%Blob = type { i32 }
|
||||
%Blob.0 = type { double }
|
||||
%Foo2 = type { i32 }
|
||||
%Bobo = type { i16, float, i16, i16, float, i16 }
|
||||
%"int[]" = type { i32*, i64 }
|
||||
@@ -244,6 +244,13 @@ fn Type getValue(Blob blob)
|
||||
%List = type { i64, i64, i32* }
|
||||
%Foo = type { i32, i32 }
|
||||
|
||||
@.typeid.test.Bobo = linkonce constant { i8, i64 } { i8 10, i64 6 }, align 8
|
||||
@.typeid.test.Blob = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@.typeid.test.Foor = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8
|
||||
@.typeid.test.Foo2 = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8
|
||||
@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@.typeid.test.MyEnum = linkonce constant { i8, i64, i64 } { i8 8, i64 3, i64 0 }, align 8
|
||||
|
||||
define void @test.Foo2__printme(%Foo2* %0) #0 {
|
||||
entry:
|
||||
%1 = getelementptr inbounds %Foo2, %Foo2* %0, i32 0, i32 0
|
||||
@@ -432,8 +439,8 @@ entry:
|
||||
%elements = alloca i32, align 4
|
||||
%array = alloca %List, align 8
|
||||
%i1 = alloca i32, align 4
|
||||
%a = alloca %Blob.0, align 4
|
||||
%b = alloca %Blob.1, align 8
|
||||
%a = alloca %Blob, align 4
|
||||
%b = alloca %Blob.0, align 8
|
||||
%tempcoerce = alloca double, align 8
|
||||
%ddx = alloca %Foo, align 4
|
||||
%fro = alloca i32, align 4
|
||||
@@ -515,15 +522,15 @@ loop.body5: ; preds = %loop.cond2
|
||||
|
||||
loop.exit8: ; preds = %loop.cond2
|
||||
call void @"std::array::list.int.List__free"(%List* %array)
|
||||
%21 = bitcast %Blob.0* %a to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob.0* @.__const.6 to i8*), i32 4, i1 false)
|
||||
%22 = bitcast %Blob.1* %b to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.1* @.__const.7 to i8*), i32 8, i1 false)
|
||||
%23 = getelementptr inbounds %Blob.0, %Blob.0* %a, i32 0, i32 0
|
||||
%21 = bitcast %Blob* %a to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob* @.__const.6 to i8*), i32 4, i1 false)
|
||||
%22 = bitcast %Blob.0* %b to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.0* @.__const.7 to i8*), i32 8, i1 false)
|
||||
%23 = getelementptr inbounds %Blob, %Blob* %a, i32 0, i32 0
|
||||
%24 = load i32, i32* %23, align 4
|
||||
%25 = call i32 @test2.int.getValue(i32 %24)
|
||||
%26 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i32 %25)
|
||||
%27 = getelementptr inbounds %Blob.1, %Blob.1* %b, i32 0, i32 0
|
||||
%27 = getelementptr inbounds %Blob.0, %Blob.0* %b, i32 0, i32 0
|
||||
%28 = bitcast double* %tempcoerce to i8*
|
||||
%29 = bitcast double* %27 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %28, i8* align 8 %29, i32 8, i1 false)
|
||||
|
||||
@@ -236,8 +236,8 @@ fn Type getValue(Blob blob)
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
%Blob.0 = type { i32 }
|
||||
%Blob.1 = type { double }
|
||||
%Blob = type { i32 }
|
||||
%Blob.0 = type { double }
|
||||
%Foo2 = type { i32 }
|
||||
%Bobo = type { i16, float, i16, i16, float, i16 }
|
||||
%"int[]" = type { i32*, i64 }
|
||||
@@ -246,21 +246,24 @@ fn Type getValue(Blob blob)
|
||||
%List = type { i64, i64, i32* }
|
||||
%Foo = type { i32, i32 }
|
||||
|
||||
$introspect.Bobo = comdat any
|
||||
$.typeid.test.Bobo = comdat any
|
||||
|
||||
$introspect.Blob = comdat any
|
||||
$.typeid.test.Blob = comdat any
|
||||
|
||||
$introspect.Foor = comdat any
|
||||
$.typeid.test.Foor = comdat any
|
||||
|
||||
$introspect.Foo2 = comdat any
|
||||
$.typeid.test.Foo2 = comdat any
|
||||
|
||||
$introspect.Foo = comdat any
|
||||
$.typeid.test.Foo = comdat any
|
||||
|
||||
@introspect.Bobo = linkonce constant i8 1, comdat
|
||||
@introspect.Blob = linkonce constant i8 1, comdat
|
||||
@introspect.Foor = linkonce constant i8 1, comdat
|
||||
@introspect.Foo2 = linkonce constant i8 1, comdat
|
||||
@introspect.Foo = linkonce constant i8 1, comdat
|
||||
$.typeid.test.MyEnum = comdat any
|
||||
|
||||
@.typeid.test.Bobo = linkonce constant { i8, i64 } { i8 10, i64 6 }, comdat, align 8
|
||||
@.typeid.test.Blob = linkonce constant { i8, i64 } { i8 10, i64 2 }, comdat, align 8
|
||||
@.typeid.test.Foor = linkonce constant { i8, i64 } { i8 11, i64 2 }, comdat, align 8
|
||||
@.typeid.test.Foo2 = linkonce constant { i8, i64 } { i8 10, i64 1 }, comdat, align 8
|
||||
@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, comdat, align 8
|
||||
@.typeid.test.MyEnum = linkonce constant { i8, i64, i64 } { i8 8, i64 3, i64 0 }, comdat, align 8
|
||||
@.str = private unnamed_addr constant [13 x i8] c"helloWorld!\0A\00", align 1
|
||||
@test_static.x = internal unnamed_addr global i32 1, align 4
|
||||
@.str.1 = private unnamed_addr constant [16 x i8] c"Test static %d\0A\00", align 1
|
||||
@@ -269,8 +272,8 @@ $introspect.Foo = comdat any
|
||||
@.str.3 = private unnamed_addr constant [14 x i8] c"Elements: %d\0A\00", align 1
|
||||
@.str.4 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1
|
||||
@.str.5 = private unnamed_addr constant [17 x i8] c"Element[%d]: %d\0A\00", align 1
|
||||
@.__const.6 = private unnamed_addr constant %Blob.0 { i32 42 }, align 4
|
||||
@.__const.7 = private unnamed_addr constant %Blob.1 { double 3.330000e+01 }, align 8
|
||||
@.__const.6 = private unnamed_addr constant %Blob { i32 42 }, align 4
|
||||
@.__const.7 = private unnamed_addr constant %Blob.0 { double 3.330000e+01 }, align 8
|
||||
@.str.8 = private unnamed_addr constant [10 x i8] c"a was %d\0A\00", align 1
|
||||
@.str.9 = private unnamed_addr constant [10 x i8] c"b was %f\0A\00", align 1
|
||||
@.str.10 = private unnamed_addr constant [17 x i8] c"Mult int was %d\0A\00", align 1
|
||||
@@ -287,6 +290,7 @@ $introspect.Foo = comdat any
|
||||
@.str.21 = private unnamed_addr constant [12 x i8] c"Foo is: %d\0A\00", align 1
|
||||
@.str.22 = private unnamed_addr constant [9 x i8] c"Mutating\00", align 1
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @test.Foo2__printme(%Foo2* %0) #0 {
|
||||
entry:
|
||||
%1 = getelementptr inbounds %Foo2, %Foo2* %0, i32 0, i32 0
|
||||
@@ -295,6 +299,7 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @test.Foo2__mutate(%Foo2* %0) #0 {
|
||||
entry:
|
||||
%1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.22, i32 0, i32 0))
|
||||
@@ -465,8 +470,8 @@ entry:
|
||||
%elements = alloca i32, align 4
|
||||
%array = alloca %List, align 8
|
||||
%i1 = alloca i32, align 4
|
||||
%a = alloca %Blob.0, align 4
|
||||
%b = alloca %Blob.1, align 8
|
||||
%a = alloca %Blob, align 4
|
||||
%b = alloca %Blob.0, align 8
|
||||
%tempcoerce = alloca i64, align 8
|
||||
%ddx = alloca %Foo, align 4
|
||||
%fro = alloca i32, align 4
|
||||
@@ -554,15 +559,15 @@ loop.body5: ; preds = %loop.cond2
|
||||
|
||||
loop.exit8: ; preds = %loop.cond2
|
||||
call void @"std::array::list.int.List__free"(%List* %array)
|
||||
%21 = bitcast %Blob.0* %a to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob.0* @.__const.6 to i8*), i32 4, i1 false)
|
||||
%22 = bitcast %Blob.1* %b to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.1* @.__const.7 to i8*), i32 8, i1 false)
|
||||
%23 = getelementptr inbounds %Blob.0, %Blob.0* %a, i32 0, i32 0
|
||||
%21 = bitcast %Blob* %a to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %21, i8* align 4 bitcast (%Blob* @.__const.6 to i8*), i32 4, i1 false)
|
||||
%22 = bitcast %Blob.0* %b to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %22, i8* align 8 bitcast (%Blob.0* @.__const.7 to i8*), i32 8, i1 false)
|
||||
%23 = getelementptr inbounds %Blob, %Blob* %a, i32 0, i32 0
|
||||
%24 = load i32, i32* %23, align 4
|
||||
%25 = call i32 @test2.int.getValue(i32 %24)
|
||||
%26 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i32 %25)
|
||||
%27 = getelementptr inbounds %Blob.1, %Blob.1* %b, i32 0, i32 0
|
||||
%27 = getelementptr inbounds %Blob.0, %Blob.0* %b, i32 0, i32 0
|
||||
%28 = bitcast i64* %tempcoerce to i8*
|
||||
%29 = bitcast double* %27 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %28, i8* align 8 %29, i32 8, i1 false)
|
||||
|
||||
@@ -22,6 +22,8 @@ fn int main()
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2
|
||||
|
||||
define void @test.retest(i8* %0, i64 %1) #0 {
|
||||
entry:
|
||||
%foo = alloca %"variant[]", align 8
|
||||
@@ -74,7 +76,7 @@ entry:
|
||||
store i32 1, i32* %taddr, align 4
|
||||
%0 = bitcast i32* %taddr to i8*
|
||||
%1 = insertvalue %variant undef, i8* %0, 0
|
||||
%2 = insertvalue %variant %1, i64 5, 1
|
||||
%2 = insertvalue %variant %1, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
%3 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots, i64 0, i64 0
|
||||
store %variant %2, %variant* %3, align 16
|
||||
%4 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1
|
||||
@@ -91,7 +93,7 @@ entry:
|
||||
store i32 1, i32* %taddr3, align 4
|
||||
%10 = bitcast i32* %taddr3 to i8*
|
||||
%11 = insertvalue %variant undef, i8* %10, 0
|
||||
%12 = insertvalue %variant %11, i64 5, 1
|
||||
%12 = insertvalue %variant %11, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
%13 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots2, i64 0, i64 0
|
||||
store %variant %12, %variant* %13, align 16
|
||||
%14 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg1, i32 0, i32 1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module test;
|
||||
import std::mem;
|
||||
import std::core::mem;
|
||||
import hello_world; // #error: No module named
|
||||
import test; // #error: Importing the current
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import std::io, std::mem;
|
||||
import std::io, std::core::mem;
|
||||
|
||||
int foo = 1;
|
||||
@@ -38,8 +38,8 @@ fn int test()
|
||||
%"int[]" = type { i32*, i64 }
|
||||
%"Bar[]" = type { %Bar*, i64 }
|
||||
|
||||
@introspect.Baz = linkonce constant i8 1
|
||||
@introspect.Bar = linkonce constant i8 1
|
||||
@.typeid.general_tests.Baz = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8
|
||||
@.typeid.general_tests.Bar = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@.__const = private unnamed_addr constant { i32, [4 x i8] } { i32 1, [4 x i8] undef }, align 8
|
||||
@test.foo1 = internal unnamed_addr global i32 22, align 4
|
||||
@.str = private unnamed_addr constant [7 x i8] c"Hello!\00", align 1
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// #target: macos-x64
|
||||
import std::io;
|
||||
import std::mem;
|
||||
import libc;
|
||||
union Baz
|
||||
{
|
||||
@@ -36,8 +35,8 @@ fn int main()
|
||||
%Bar = type { i32, i32 }
|
||||
%"Bar[]" = type { %Bar*, i64 }
|
||||
|
||||
@introspect.Baz = linkonce constant i8 1, align 1
|
||||
@introspect.Bar = linkonce constant i8 1, align 1
|
||||
@.typeid.statics.Baz = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8
|
||||
@.typeid.statics.Bar = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@.taddr = private global [1 x %Bar] [%Bar { i32 1, i32 2 }], align 8
|
||||
@test.c = internal unnamed_addr global %"Bar[]" { %Bar* getelementptr inbounds ([1 x %Bar], [1 x %Bar]* @.taddr, i32 0, i32 0), i64 1 }, align 8
|
||||
@.str = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// #target: macos-x64
|
||||
|
||||
import std::io;
|
||||
import std::mem;
|
||||
import std::core::mem;
|
||||
import libc;
|
||||
union Baz
|
||||
{
|
||||
@@ -51,8 +51,8 @@ fn int main()
|
||||
%"int[]" = type { i32*, i64 }
|
||||
%Baz = type { double }
|
||||
|
||||
@introspect.Baz = linkonce constant i8 1, align 1
|
||||
@introspect.Bar = linkonce constant i8 1, align 1
|
||||
@.typeid.subarrays.Baz = linkonce constant { i8, i64 } { i8 11, i64 2 }, align 8
|
||||
@.typeid.subarrays.Bar = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@.taddr = private global [2 x %Bar] [%Bar { i32 3, i32 4 }, %Bar { i32 8, i32 9 }], align 8
|
||||
@subarrays.arrbar = local_unnamed_addr global %"Bar[]" { %Bar* getelementptr inbounds ([2 x %Bar], [2 x %Bar]* @.taddr, i32 0, i32 0), i64 2 }, align 8
|
||||
@.taddr.3 = private global [2 x i32] [i32 1, i32 2], align 4
|
||||
|
||||
@@ -78,7 +78,7 @@ fn void main()
|
||||
|
||||
%Foo = type { i16, i8, i8, i16, i16 }
|
||||
|
||||
@introspect.Foo = linkonce constant i8 1
|
||||
@.typeid.userland_bitcast.Foo = linkonce constant { i8, i64 } { i8 10, i64 5 }, align 8
|
||||
@.str = private unnamed_addr constant [16 x i8] c"%f => %d => %f\0A\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [18 x i8] c"%e => %llu => %e\0A\00", align 1
|
||||
|
||||
@@ -104,7 +104,6 @@ entry:
|
||||
store i16 %0, i16* %6, align 2
|
||||
%7 = load %Foo, %Foo* %z, align 2
|
||||
store %Foo %7, %Foo* %expr, align 2
|
||||
store i64 0, i64* %x, align 8
|
||||
%ptrptr = bitcast %Foo* %expr to i16*
|
||||
store i16* %ptrptr, i16** %b, align 8
|
||||
%ptrptr1 = bitcast i64* %x to i16*
|
||||
@@ -145,14 +144,6 @@ entry:
|
||||
%i = alloca i64, align 8
|
||||
%tempcoerce = alloca i32, align 4
|
||||
store float %0, float* %expr, align 4
|
||||
%1 = getelementptr inbounds [4 x i8], [4 x i8]* %x, i64 0, i64 0
|
||||
store i8 0, i8* %1, align 1
|
||||
%2 = getelementptr inbounds [4 x i8], [4 x i8]* %x, i64 0, i64 1
|
||||
store i8 0, i8* %2, align 1
|
||||
%3 = getelementptr inbounds [4 x i8], [4 x i8]* %x, i64 0, i64 2
|
||||
store i8 0, i8* %3, align 1
|
||||
%4 = getelementptr inbounds [4 x i8], [4 x i8]* %x, i64 0, i64 3
|
||||
store i8 0, i8* %4, align 1
|
||||
%ptrptr = bitcast float* %expr to i8*
|
||||
store i8* %ptrptr, i8** %b, align 8
|
||||
%ptrptr1 = bitcast [4 x i8]* %x to i8*
|
||||
@@ -161,30 +152,30 @@ entry:
|
||||
br label %loop.cond
|
||||
|
||||
loop.cond: ; preds = %loop.body, %entry
|
||||
%5 = load i64, i64* %i, align 8
|
||||
%lt = icmp ult i64 %5, 4
|
||||
%1 = load i64, i64* %i, align 8
|
||||
%lt = icmp ult i64 %1, 4
|
||||
br i1 %lt, label %loop.body, label %loop.exit
|
||||
|
||||
loop.body: ; preds = %loop.cond
|
||||
%6 = load i8*, i8** %to, align 8
|
||||
%2 = load i8*, i8** %to, align 8
|
||||
%3 = load i64, i64* %i, align 8
|
||||
%ptroffset = getelementptr inbounds i8, i8* %2, i64 %3
|
||||
%4 = load i8*, i8** %b, align 8
|
||||
%5 = load i64, i64* %i, align 8
|
||||
%ptroffset2 = getelementptr inbounds i8, i8* %4, i64 %5
|
||||
%6 = load i8, i8* %ptroffset2, align 1
|
||||
store i8 %6, i8* %ptroffset, align 1
|
||||
%7 = load i64, i64* %i, align 8
|
||||
%ptroffset = getelementptr inbounds i8, i8* %6, i64 %7
|
||||
%8 = load i8*, i8** %b, align 8
|
||||
%9 = load i64, i64* %i, align 8
|
||||
%ptroffset2 = getelementptr inbounds i8, i8* %8, i64 %9
|
||||
%10 = load i8, i8* %ptroffset2, align 1
|
||||
store i8 %10, i8* %ptroffset, align 1
|
||||
%11 = load i64, i64* %i, align 8
|
||||
%add = add i64 %11, 1
|
||||
%add = add i64 %7, 1
|
||||
store i64 %add, i64* %i, align 8
|
||||
br label %loop.cond
|
||||
|
||||
loop.exit: ; preds = %loop.cond
|
||||
%12 = bitcast i32* %tempcoerce to i8*
|
||||
%13 = bitcast [4 x i8]* %x to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %12, i8* align 1 %13, i32 4, i1 false)
|
||||
%14 = load i32, i32* %tempcoerce, align 4
|
||||
ret i32 %14
|
||||
%8 = bitcast i32* %tempcoerce to i8*
|
||||
%9 = bitcast [4 x i8]* %x to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %8, i8* align 1 %9, i32 4, i1 false)
|
||||
%10 = load i32, i32* %tempcoerce, align 4
|
||||
ret i32 %10
|
||||
}
|
||||
|
||||
define void @userland_bitcast.main() #0 {
|
||||
@@ -218,7 +209,6 @@ entry:
|
||||
store float 0x4028B4BC60000000, float* %f, align 4
|
||||
%0 = load float, float* %f, align 4
|
||||
store float %0, float* %expr, align 4
|
||||
store i32 0, i32* %x, align 4
|
||||
%ptrptr = bitcast float* %expr to i32*
|
||||
store i32* %ptrptr, i32** %b, align 8
|
||||
store i32* %x, i32** %to, align 8
|
||||
@@ -249,7 +239,6 @@ loop.exit: ; preds = %loop.cond
|
||||
store i32 %8, i32* %i, align 4
|
||||
%9 = load i32, i32* %i, align 4
|
||||
store i32 %9, i32* %expr3, align 4
|
||||
store float 0.000000e+00, float* %x4, align 4
|
||||
store i32* %expr3, i32** %b5, align 8
|
||||
%ptrptr7 = bitcast float* %x4 to i32*
|
||||
store i32* %ptrptr7, i32** %to6, align 8
|
||||
@@ -287,7 +276,6 @@ loop.exit15: ; preds = %loop.cond9
|
||||
store double 1.235300e+268, double* %d, align 8
|
||||
%21 = load double, double* %d, align 8
|
||||
store double %21, double* %expr17, align 8
|
||||
store i64 0, i64* %x18, align 8
|
||||
%ptrptr20 = bitcast double* %expr17 to i64*
|
||||
store i64* %ptrptr20, i64** %b19, align 8
|
||||
store i64* %x18, i64** %to21, align 8
|
||||
@@ -318,7 +306,6 @@ loop.exit29: ; preds = %loop.cond23
|
||||
store i64 %29, i64* %l, align 8
|
||||
%30 = load double, double* %d, align 8
|
||||
store double %30, double* %expr30, align 8
|
||||
store double 0.000000e+00, double* %x31, align 8
|
||||
%ptrptr33 = bitcast double* %expr30 to i64*
|
||||
store i64* %ptrptr33, i64** %b32, align 8
|
||||
%ptrptr35 = bitcast double* %x31 to i64*
|
||||
|
||||
@@ -26,6 +26,11 @@ fn void main()
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
%variant = type { i8*, i64 }
|
||||
%"int[]" = type { i32*, i64 }
|
||||
|
||||
@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2
|
||||
|
||||
define void @foo.test1(i64 %0, i8* %1) #0 {
|
||||
entry:
|
||||
%z = alloca %variant, align 8
|
||||
@@ -76,7 +81,7 @@ entry:
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([2 x i32]* @.__const to i8*), i32 8, i1 false)
|
||||
%1 = bitcast i32* %x to i8*
|
||||
%2 = insertvalue %variant undef, i8* %1, 0
|
||||
%3 = insertvalue %variant %2, i64 5, 1
|
||||
%3 = insertvalue %variant %2, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
store %variant %3, %variant* %taddr, align 8
|
||||
%4 = bitcast %variant* %taddr to { i64, i8* }*
|
||||
%5 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %4, i32 0, i32 0
|
||||
|
||||
29
test/test_suite/safe/deref.c3t
Normal file
29
test/test_suite/safe/deref.c3t
Normal file
@@ -0,0 +1,29 @@
|
||||
// #safe: yes
|
||||
module foo;
|
||||
|
||||
fn void main()
|
||||
{
|
||||
int* x;
|
||||
int y = *x;
|
||||
}
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
define void @foo.main() #0 {
|
||||
entry:
|
||||
%x = alloca i32*, align 8
|
||||
%y = alloca i32, align 4
|
||||
store i32* null, i32** %x, align 8
|
||||
%0 = load i32*, i32** %x, align 8
|
||||
%checknull = icmp eq i32* %0, null
|
||||
br i1 %checknull, label %panic, label %checkok
|
||||
|
||||
panic: ; preds = %entry
|
||||
call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.2, i64 0, i64 0), i32 6)
|
||||
br label %checkok
|
||||
|
||||
checkok: ; preds = %panic, %entry
|
||||
%1 = load i32, i32* %0, align 8
|
||||
store i32 %1, i32* %y, align 4
|
||||
ret void
|
||||
}
|
||||
@@ -86,7 +86,7 @@ fn void main()
|
||||
|
||||
%Foo = type { [3 x i32] }
|
||||
|
||||
@introspect.Foo = linkonce constant i8 1
|
||||
@.typeid.foo.Foo = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8
|
||||
@.str = private unnamed_addr constant [11 x i8] c"getFields\0A\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [11 x i8] c"Call made\0A\00", align 1
|
||||
@.__const = private unnamed_addr constant %Foo { [3 x i32] [i32 1, i32 5, i32 7] }, align 4
|
||||
|
||||
@@ -13,15 +13,14 @@ fn Event test(int x)
|
||||
return x ? foo : bar;
|
||||
}
|
||||
|
||||
// #expect: test.ll
|
||||
/* #expect: test.ll
|
||||
|
||||
%Event = type { i32 }
|
||||
|
||||
@introspect.Event = linkonce constant i8 1
|
||||
@.typeid.test.Event = linkonce constant { i8, i64 } { i8 10, i64 1 }, align 8
|
||||
@.__const = private unnamed_addr constant %Event { i32 1 }, align 4
|
||||
@.__const.1 = private unnamed_addr constant %Event { i32 2 }, align 4
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @test.test(i32 %0) #0 {
|
||||
entry:
|
||||
%foo = alloca %Event, align 4
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
|
||||
struct Point
|
||||
@@ -12,11 +12,11 @@ fn void test1()
|
||||
Point p = { 5, 6 };
|
||||
}
|
||||
|
||||
// #expect: test.ll
|
||||
/* #expect: test.ll
|
||||
|
||||
%Point = type { i32, i32 }
|
||||
|
||||
@introspect.Point = linkonce constant i8 1
|
||||
@.typeid.test.Point = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@.__const = private unnamed_addr constant %Point { i32 5, i32 6 }, align 4
|
||||
|
||||
define void @test.test1() #0 {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// #target: macos-x64
|
||||
struct StructA
|
||||
{
|
||||
int a;
|
||||
@@ -20,7 +21,7 @@ fn void test()
|
||||
StructB b3 = { .b = { } };
|
||||
}
|
||||
|
||||
// #expect: struct_codegen_empty.ll
|
||||
/* #expect: struct_codegen_empty.ll
|
||||
|
||||
%a = alloca %StructA, align 4
|
||||
%a2 = alloca %StructA, align 4
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// #target: macos-x64
|
||||
module structo;
|
||||
|
||||
struct Foo
|
||||
@@ -21,7 +22,7 @@ private Foo foo8 = FOO7;
|
||||
|
||||
%Foo = type { i32, i64 }
|
||||
|
||||
@introspect.Foo = linkonce constant i8 1
|
||||
@.typeid.structo.Foo = linkonce constant { i8, i64 } { i8 10, i64 2 }, align 8
|
||||
@structo.x = protected unnamed_addr global i64 16, align 8
|
||||
@structo.foo1 = protected unnamed_addr global %Foo { i32 1, i64 2 }, align 8
|
||||
@structo.foo2 = protected unnamed_addr global %Foo { i32 2, i64 0 }, align 8
|
||||
@@ -30,4 +31,4 @@ private Foo foo8 = FOO7;
|
||||
@structo.foo5 = protected unnamed_addr global %Foo zeroinitializer, align 8
|
||||
@structo.foo6 = protected unnamed_addr global %Foo zeroinitializer, align 8
|
||||
@structo.FOO7 = protected unnamed_addr constant %Foo { i32 1, i64 2 }, align 8
|
||||
@structo.foo8 = protected unnamed_addr global %Foo { i32 1, i64 2 }, align 8
|
||||
@structo.foo8 = protected unnamed_addr global %Foo { i32 1, i64 2 }, align 8
|
||||
@@ -58,6 +58,10 @@ fn int main()
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2
|
||||
@.typeid.double = linkonce constant { i8, i16 } { i8 4, i16 64 }, align 2
|
||||
@.typeid.bool = linkonce constant { i8 } { i8 1 }, align 1
|
||||
|
||||
define void @foo.test(i64 %0, i8* %1) #0 {
|
||||
entry:
|
||||
%z = alloca %variant, align 8
|
||||
@@ -76,7 +80,7 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%6 = load i64, i64* %switch, align 8
|
||||
%eq = icmp eq i64 5, %6
|
||||
%eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %6
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
@@ -90,7 +94,7 @@ switch.case: ; preds = %switch.entry
|
||||
br label %switch.exit
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq2 = icmp eq i64 15, %6
|
||||
%eq2 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %6
|
||||
br i1 %eq2, label %switch.case3, label %next_if5
|
||||
|
||||
switch.case3: ; preds = %next_if
|
||||
@@ -130,14 +134,14 @@ entry:
|
||||
%4 = bitcast %variant* %anon to i8*
|
||||
%5 = bitcast %variant* %y to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %4, i8* align 8 %5, i32 16, i1 false)
|
||||
%6 = getelementptr inbounds %variant, %variant* %anon, i32 0, i32 1
|
||||
%6 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1
|
||||
%7 = load i64, i64* %6, align 8
|
||||
store i64 %7, i64* %switch, align 8
|
||||
br label %switch.entry
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%8 = load i64, i64* %switch, align 8
|
||||
%eq = icmp eq i64 5, %8
|
||||
%eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %8
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
@@ -148,7 +152,7 @@ switch.case: ; preds = %switch.entry
|
||||
store i32 12, i32* %taddr, align 4
|
||||
%12 = bitcast i32* %taddr to i8*
|
||||
%13 = insertvalue %variant undef, i8* %12, 0
|
||||
%14 = insertvalue %variant %13, i64 5, 1
|
||||
%14 = insertvalue %variant %13, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
store %variant %14, %variant* %y, align 8
|
||||
%15 = load i32*, i32** %z, align 8
|
||||
%16 = load i32, i32* %15, align 8
|
||||
@@ -156,7 +160,7 @@ switch.case: ; preds = %switch.entry
|
||||
br label %switch.exit
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq1 = icmp eq i64 15, %8
|
||||
%eq1 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %8
|
||||
br i1 %eq1, label %switch.case2, label %next_if4
|
||||
|
||||
switch.case2: ; preds = %next_if
|
||||
@@ -195,14 +199,14 @@ entry:
|
||||
%4 = bitcast %variant* %anon to i8*
|
||||
%5 = bitcast %variant* %y to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %4, i8* align 8 %5, i32 16, i1 false)
|
||||
%6 = getelementptr inbounds %variant, %variant* %anon, i32 0, i32 1
|
||||
%6 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1
|
||||
%7 = load i64, i64* %6, align 8
|
||||
store i64 %7, i64* %switch, align 8
|
||||
br label %switch.entry
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%8 = load i64, i64* %switch, align 8
|
||||
%eq = icmp eq i64 5, %8
|
||||
%eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %8
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
@@ -216,7 +220,7 @@ switch.case: ; preds = %switch.entry
|
||||
br label %switch.exit
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq1 = icmp eq i64 15, %8
|
||||
%eq1 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %8
|
||||
br i1 %eq1, label %switch.case2, label %next_if4
|
||||
|
||||
switch.case2: ; preds = %next_if
|
||||
@@ -263,7 +267,7 @@ entry:
|
||||
store double 1.230000e+02, double* %taddr, align 8
|
||||
%0 = bitcast double* %taddr to i8*
|
||||
%1 = insertvalue %variant undef, i8* %0, 0
|
||||
%2 = insertvalue %variant %1, i64 15, 1
|
||||
%2 = insertvalue %variant %1, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1
|
||||
store %variant %2, %variant* %taddr1, align 8
|
||||
%3 = bitcast %variant* %taddr1 to { i64, i8* }*
|
||||
%4 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %3, i32 0, i32 0
|
||||
@@ -274,7 +278,7 @@ entry:
|
||||
store i32 1, i32* %taddr2, align 4
|
||||
%6 = bitcast i32* %taddr2 to i8*
|
||||
%7 = insertvalue %variant undef, i8* %6, 0
|
||||
%8 = insertvalue %variant %7, i64 5, 1
|
||||
%8 = insertvalue %variant %7, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
store %variant %8, %variant* %taddr3, align 8
|
||||
%9 = bitcast %variant* %taddr3 to { i64, i8* }*
|
||||
%10 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %9, i32 0, i32 0
|
||||
@@ -284,7 +288,7 @@ entry:
|
||||
call void @foo.test(i64 %lo4, i8* %hi5)
|
||||
store i8 1, i8* %taddr6, align 1
|
||||
%12 = insertvalue %variant undef, i8* %taddr6, 0
|
||||
%13 = insertvalue %variant %12, i64 2, 1
|
||||
%13 = insertvalue %variant %12, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1
|
||||
store %variant %13, %variant* %taddr7, align 8
|
||||
%14 = bitcast %variant* %taddr7 to { i64, i8* }*
|
||||
%15 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %14, i32 0, i32 0
|
||||
@@ -295,7 +299,7 @@ entry:
|
||||
store double 1.235000e+02, double* %taddr10, align 8
|
||||
%17 = bitcast double* %taddr10 to i8*
|
||||
%18 = insertvalue %variant undef, i8* %17, 0
|
||||
%19 = insertvalue %variant %18, i64 15, 1
|
||||
%19 = insertvalue %variant %18, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1
|
||||
store %variant %19, %variant* %taddr11, align 8
|
||||
%20 = bitcast %variant* %taddr11 to { i64, i8* }*
|
||||
%21 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %20, i32 0, i32 0
|
||||
@@ -306,7 +310,7 @@ entry:
|
||||
store i32 1, i32* %taddr14, align 4
|
||||
%23 = bitcast i32* %taddr14 to i8*
|
||||
%24 = insertvalue %variant undef, i8* %23, 0
|
||||
%25 = insertvalue %variant %24, i64 5, 1
|
||||
%25 = insertvalue %variant %24, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
store %variant %25, %variant* %taddr15, align 8
|
||||
%26 = bitcast %variant* %taddr15 to { i64, i8* }*
|
||||
%27 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %26, i32 0, i32 0
|
||||
@@ -316,7 +320,7 @@ entry:
|
||||
call void @foo.test2(i64 %lo16, i8* %hi17)
|
||||
store i8 1, i8* %taddr18, align 1
|
||||
%29 = insertvalue %variant undef, i8* %taddr18, 0
|
||||
%30 = insertvalue %variant %29, i64 2, 1
|
||||
%30 = insertvalue %variant %29, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1
|
||||
store %variant %30, %variant* %taddr19, align 8
|
||||
%31 = bitcast %variant* %taddr19 to { i64, i8* }*
|
||||
%32 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %31, i32 0, i32 0
|
||||
@@ -327,7 +331,7 @@ entry:
|
||||
store double 1.240000e+02, double* %taddr22, align 8
|
||||
%34 = bitcast double* %taddr22 to i8*
|
||||
%35 = insertvalue %variant undef, i8* %34, 0
|
||||
%36 = insertvalue %variant %35, i64 15, 1
|
||||
%36 = insertvalue %variant %35, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1
|
||||
store %variant %36, %variant* %taddr23, align 8
|
||||
%37 = bitcast %variant* %taddr23 to { i64, i8* }*
|
||||
%38 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %37, i32 0, i32 0
|
||||
@@ -338,7 +342,7 @@ entry:
|
||||
store i32 2, i32* %taddr26, align 4
|
||||
%40 = bitcast i32* %taddr26 to i8*
|
||||
%41 = insertvalue %variant undef, i8* %40, 0
|
||||
%42 = insertvalue %variant %41, i64 5, 1
|
||||
%42 = insertvalue %variant %41, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
store %variant %42, %variant* %taddr27, align 8
|
||||
%43 = bitcast %variant* %taddr27 to { i64, i8* }*
|
||||
%44 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %43, i32 0, i32 0
|
||||
@@ -348,7 +352,7 @@ entry:
|
||||
call void @foo.test3(i64 %lo28, i8* %hi29)
|
||||
store i8 1, i8* %taddr30, align 1
|
||||
%46 = insertvalue %variant undef, i8* %taddr30, 0
|
||||
%47 = insertvalue %variant %46, i64 2, 1
|
||||
%47 = insertvalue %variant %46, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1
|
||||
store %variant %47, %variant* %taddr31, align 8
|
||||
%48 = bitcast %variant* %taddr31 to { i64, i8* }*
|
||||
%49 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %48, i32 0, i32 0
|
||||
|
||||
@@ -30,6 +30,10 @@ fn int main()
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2
|
||||
@.typeid.double = linkonce constant { i8, i16 } { i8 4, i16 64 }, align 2
|
||||
@.typeid.bool = linkonce constant { i8 } { i8 1 }, align 1
|
||||
|
||||
define void @foo.test(i64 %0, i8* %1) #0 {
|
||||
entry:
|
||||
%z = alloca %variant, align 8
|
||||
@@ -48,7 +52,7 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%6 = load i64, i64* %switch, align 8
|
||||
%eq = icmp eq i64 5, %6
|
||||
%eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %6
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
@@ -64,7 +68,7 @@ switch.case: ; preds = %switch.entry
|
||||
br label %switch.exit
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq2 = icmp eq i64 15, %6
|
||||
%eq2 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %6
|
||||
br i1 %eq2, label %switch.case3, label %next_if5
|
||||
|
||||
switch.case3: ; preds = %next_if
|
||||
@@ -87,7 +91,7 @@ switch.default: ; preds = %next_if5
|
||||
switch.exit: ; preds = %switch.default, %switch.case3, %switch.case
|
||||
%18 = getelementptr inbounds %variant, %variant* %z, i32 0, i32 1
|
||||
%19 = load i64, i64* %18, align 8
|
||||
%eq6 = icmp eq i64 %19, 5
|
||||
%eq6 = icmp eq i64 %19, ptrtoint ({ i8, i16 }* @.typeid.int to i64)
|
||||
br i1 %eq6, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %switch.exit
|
||||
@@ -114,7 +118,7 @@ entry:
|
||||
store double 1.230000e+02, double* %taddr, align 8
|
||||
%0 = bitcast double* %taddr to i8*
|
||||
%1 = insertvalue %variant undef, i8* %0, 0
|
||||
%2 = insertvalue %variant %1, i64 15, 1
|
||||
%2 = insertvalue %variant %1, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1
|
||||
store %variant %2, %variant* %taddr1, align 8
|
||||
%3 = bitcast %variant* %taddr1 to { i64, i8* }*
|
||||
%4 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %3, i32 0, i32 0
|
||||
@@ -125,7 +129,7 @@ entry:
|
||||
store i32 1, i32* %taddr2, align 4
|
||||
%6 = bitcast i32* %taddr2 to i8*
|
||||
%7 = insertvalue %variant undef, i8* %6, 0
|
||||
%8 = insertvalue %variant %7, i64 5, 1
|
||||
%8 = insertvalue %variant %7, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
store %variant %8, %variant* %taddr3, align 8
|
||||
%9 = bitcast %variant* %taddr3 to { i64, i8* }*
|
||||
%10 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %9, i32 0, i32 0
|
||||
@@ -135,7 +139,7 @@ entry:
|
||||
call void @foo.test(i64 %lo4, i8* %hi5)
|
||||
store i8 1, i8* %taddr6, align 1
|
||||
%12 = insertvalue %variant undef, i8* %taddr6, 0
|
||||
%13 = insertvalue %variant %12, i64 2, 1
|
||||
%13 = insertvalue %variant %12, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1
|
||||
store %variant %13, %variant* %taddr7, align 8
|
||||
%14 = bitcast %variant* %taddr7 to { i64, i8* }*
|
||||
%15 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %14, i32 0, i32 0
|
||||
|
||||
@@ -67,7 +67,11 @@ fn void main()
|
||||
%variant = type { i8*, i64 }
|
||||
%"variant[]" = type { %variant*, i64 }
|
||||
|
||||
@"int*" = weak constant i8 1
|
||||
@.typeid.int = linkonce constant { i8, i16 } { i8 2, i16 32 }, align 2
|
||||
@.typeid.double = linkonce constant { i8, i16 } { i8 4, i16 64 }, align 2
|
||||
@.typeid.variant = linkonce constant { i8 } { i8 7 }, align 1
|
||||
@".typeid.int*" = linkonce constant { i8, i64 } { i8 15, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64) }, align 8
|
||||
@.typeid.bool = linkonce constant { i8 } { i8 1 }, align 1
|
||||
|
||||
define void @foo.test(i64 %0, i8* %1) #0 {
|
||||
entry:
|
||||
@@ -85,7 +89,7 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%6 = load i64, i64* %switch, align 8
|
||||
%eq = icmp eq i64 5, %6
|
||||
%eq = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), %6
|
||||
br i1 %eq, label %switch.case, label %next_if
|
||||
|
||||
switch.case: ; preds = %switch.entry
|
||||
@@ -93,7 +97,7 @@ switch.case: ; preds = %switch.entry
|
||||
br label %switch.exit
|
||||
|
||||
next_if: ; preds = %switch.entry
|
||||
%eq1 = icmp eq i64 15, %6
|
||||
%eq1 = icmp eq i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), %6
|
||||
br i1 %eq1, label %switch.case2, label %next_if3
|
||||
|
||||
switch.case2: ; preds = %next_if
|
||||
@@ -101,7 +105,7 @@ switch.case2: ; preds = %next_if
|
||||
br label %switch.exit
|
||||
|
||||
next_if3: ; preds = %next_if
|
||||
%eq4 = icmp eq i64 17, %6
|
||||
%eq4 = icmp eq i64 ptrtoint ({ i8 }* @.typeid.variant to i64), %6
|
||||
br i1 %eq4, label %switch.case5, label %next_if6
|
||||
|
||||
switch.case5: ; preds = %next_if3
|
||||
@@ -109,7 +113,7 @@ switch.case5: ; preds = %next_if3
|
||||
br label %switch.exit
|
||||
|
||||
next_if6: ; preds = %next_if3
|
||||
%eq7 = icmp eq i64 ptrtoint (i8* @"int*" to i64), %6
|
||||
%eq7 = icmp eq i64 ptrtoint ({ i8, i64 }* @".typeid.int*" to i64), %6
|
||||
br i1 %eq7, label %switch.case8, label %next_if9
|
||||
|
||||
switch.case8: ; preds = %next_if6
|
||||
@@ -197,12 +201,12 @@ entry:
|
||||
store i32 1, i32* %taddr, align 4
|
||||
%0 = bitcast i32* %taddr to i8*
|
||||
%1 = insertvalue %variant undef, i8* %0, 0
|
||||
%2 = insertvalue %variant %1, i64 5, 1
|
||||
%2 = insertvalue %variant %1, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
store %variant %2, %variant* %x, align 8
|
||||
store i32 0, i32* %z, align 4
|
||||
%3 = bitcast i32* %z to i8*
|
||||
%4 = insertvalue %variant undef, i8* %3, 0
|
||||
%5 = insertvalue %variant %4, i64 5, 1
|
||||
%5 = insertvalue %variant %4, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
store %variant %5, %variant* %y, align 8
|
||||
%6 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1
|
||||
%7 = load i64, i64* %6, align 8
|
||||
@@ -212,7 +216,7 @@ entry:
|
||||
store i64 %9, i64* %h, align 8
|
||||
%10 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1
|
||||
%11 = load i64, i64* %10, align 8
|
||||
%eq = icmp eq i64 %11, 5
|
||||
%eq = icmp eq i64 %11, ptrtoint ({ i8, i16 }* @.typeid.int to i64)
|
||||
br i1 %eq, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %entry
|
||||
@@ -222,7 +226,7 @@ if.then: ; preds = %entry
|
||||
if.exit: ; preds = %if.then, %entry
|
||||
%12 = getelementptr inbounds %variant, %variant* %x, i32 0, i32 1
|
||||
%13 = load i64, i64* %12, align 8
|
||||
%eq1 = icmp eq i64 %13, 5
|
||||
%eq1 = icmp eq i64 %13, ptrtoint ({ i8, i16 }* @.typeid.int to i64)
|
||||
br i1 %eq1, label %if.then2, label %if.exit3
|
||||
|
||||
if.then2: ; preds = %if.exit
|
||||
@@ -233,15 +237,15 @@ if.exit3: ; preds = %if.then2, %if.exit
|
||||
store double 1.000000e+00, double* %taddr4, align 8
|
||||
%14 = bitcast double* %taddr4 to i8*
|
||||
%15 = insertvalue %variant undef, i8* %14, 0
|
||||
%16 = insertvalue %variant %15, i64 15, 1
|
||||
%16 = insertvalue %variant %15, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1
|
||||
store %variant %16, %variant* %y, align 8
|
||||
%17 = bitcast %variant* %x to i8*
|
||||
%18 = insertvalue %variant undef, i8* %17, 0
|
||||
%19 = insertvalue %variant %18, i64 17, 1
|
||||
%19 = insertvalue %variant %18, i64 ptrtoint ({ i8 }* @.typeid.variant to i64), 1
|
||||
store %variant %19, %variant* %x, align 8
|
||||
%20 = getelementptr inbounds %variant, %variant* %y, i32 0, i32 1
|
||||
%21 = load i64, i64* %20, align 8
|
||||
%eq5 = icmp eq i64 %21, 5
|
||||
%eq5 = icmp eq i64 %21, ptrtoint ({ i8, i16 }* @.typeid.int to i64)
|
||||
br i1 %eq5, label %if.then6, label %if.exit7
|
||||
|
||||
if.then6: ; preds = %if.exit3
|
||||
@@ -251,7 +255,7 @@ if.then6: ; preds = %if.exit3
|
||||
if.exit7: ; preds = %if.then6, %if.exit3
|
||||
%22 = getelementptr inbounds %variant, %variant* %x, i32 0, i32 1
|
||||
%23 = load i64, i64* %22, align 8
|
||||
%eq8 = icmp eq i64 %23, 5
|
||||
%eq8 = icmp eq i64 %23, ptrtoint ({ i8, i16 }* @.typeid.int to i64)
|
||||
br i1 %eq8, label %if.then9, label %if.exit10
|
||||
|
||||
if.then9: ; preds = %if.exit7
|
||||
@@ -268,7 +272,7 @@ if.exit10: ; preds = %if.then9, %if.exit7
|
||||
store double 1.000000e+00, double* %taddr11, align 8
|
||||
%27 = bitcast double* %taddr11 to i8*
|
||||
%28 = insertvalue %variant undef, i8* %27, 0
|
||||
%29 = insertvalue %variant %28, i64 15, 1
|
||||
%29 = insertvalue %variant %28, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1
|
||||
store %variant %29, %variant* %taddr12, align 8
|
||||
%30 = bitcast %variant* %taddr12 to { i64, i8* }*
|
||||
%31 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %30, i32 0, i32 0
|
||||
@@ -279,7 +283,7 @@ if.exit10: ; preds = %if.then9, %if.exit7
|
||||
store i32 1, i32* %taddr15, align 4
|
||||
%33 = bitcast i32* %taddr15 to i8*
|
||||
%34 = insertvalue %variant undef, i8* %33, 0
|
||||
%35 = insertvalue %variant %34, i64 5, 1
|
||||
%35 = insertvalue %variant %34, i64 ptrtoint ({ i8, i16 }* @.typeid.int to i64), 1
|
||||
store %variant %35, %variant* %taddr16, align 8
|
||||
%36 = bitcast %variant* %taddr16 to { i64, i8* }*
|
||||
%37 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %36, i32 0, i32 0
|
||||
@@ -289,7 +293,7 @@ if.exit10: ; preds = %if.then9, %if.exit7
|
||||
call void @foo.test(i64 %lo17, i8* %hi18)
|
||||
store i8 1, i8* %taddr19, align 1
|
||||
%39 = insertvalue %variant undef, i8* %taddr19, 0
|
||||
%40 = insertvalue %variant %39, i64 2, 1
|
||||
%40 = insertvalue %variant %39, i64 ptrtoint ({ i8 }* @.typeid.bool to i64), 1
|
||||
store %variant %40, %variant* %taddr20, align 8
|
||||
%41 = bitcast %variant* %taddr20 to { i64, i8* }*
|
||||
%42 = getelementptr inbounds { i64, i8* }, { i64, i8* }* %41, i32 0, i32 0
|
||||
@@ -310,17 +314,17 @@ if.exit10: ; preds = %if.then9, %if.exit7
|
||||
store double 1.000000e+00, double* %taddr23, align 8
|
||||
%50 = bitcast double* %taddr23 to i8*
|
||||
%51 = insertvalue %variant undef, i8* %50, 0
|
||||
%52 = insertvalue %variant %51, i64 15, 1
|
||||
%52 = insertvalue %variant %51, i64 ptrtoint ({ i8, i16 }* @.typeid.double to i64), 1
|
||||
%53 = getelementptr inbounds [5 x %variant], [5 x %variant]* %varargslots, i64 0, i64 2
|
||||
store %variant %52, %variant* %53, align 16
|
||||
%54 = bitcast %variant* %x to i8*
|
||||
%55 = insertvalue %variant undef, i8* %54, 0
|
||||
%56 = insertvalue %variant %55, i64 17, 1
|
||||
%56 = insertvalue %variant %55, i64 ptrtoint ({ i8 }* @.typeid.variant to i64), 1
|
||||
%57 = getelementptr inbounds [5 x %variant], [5 x %variant]* %varargslots, i64 0, i64 3
|
||||
store %variant %56, %variant* %57, align 16
|
||||
%58 = bitcast i32** %df to i8*
|
||||
%59 = insertvalue %variant undef, i8* %58, 0
|
||||
%60 = insertvalue %variant %59, i64 ptrtoint (i8* @"int*" to i64), 1
|
||||
%60 = insertvalue %variant %59, i64 ptrtoint ({ i8, i64 }* @".typeid.int*" to i64), 1
|
||||
%61 = getelementptr inbounds [5 x %variant], [5 x %variant]* %varargslots, i64 0, i64 4
|
||||
store %variant %60, %variant* %61, align 16
|
||||
%62 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1
|
||||
|
||||
@@ -149,7 +149,7 @@ entry:
|
||||
br i1 %zero, label %panic, label %checkok
|
||||
|
||||
panic: ; preds = %entry
|
||||
call void @"std::builtin.panic"(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.2, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.3, i64 0, i64 0), i32 12)
|
||||
call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.2, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.3, i64 0, i64 0), i32 12)
|
||||
br label %checkok
|
||||
|
||||
checkok: ; preds = %panic, %entry
|
||||
@@ -433,7 +433,7 @@ entry:
|
||||
br i1 %zero, label %panic, label %checkok
|
||||
|
||||
panic: ; preds = %entry
|
||||
call void @"std::builtin.panic"(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.zstr.20, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.21, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.22, i64 0, i64 0), i32 56)
|
||||
call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.zstr.20, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.21, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.22, i64 0, i64 0), i32 56)
|
||||
br label %checkok
|
||||
|
||||
checkok: ; preds = %panic, %entry
|
||||
@@ -468,7 +468,7 @@ checkok: ; preds = %panic, %entry
|
||||
br i1 %shift_underflow, label %panic1, label %checkok2
|
||||
|
||||
panic1: ; preds = %checkok
|
||||
call void @"std::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.25, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.26, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.27, i64 0, i64 0), i32 60)
|
||||
call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.25, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.26, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.27, i64 0, i64 0), i32 60)
|
||||
br label %checkok2
|
||||
|
||||
checkok2: ; preds = %panic1, %checkok
|
||||
@@ -477,7 +477,7 @@ checkok2: ; preds = %panic1, %checkok
|
||||
br i1 %shift_exceeds, label %panic3, label %checkok4
|
||||
|
||||
panic3: ; preds = %checkok2
|
||||
call void @"std::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.28, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.29, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.30, i64 0, i64 0), i32 60)
|
||||
call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.28, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.29, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.30, i64 0, i64 0), i32 60)
|
||||
br label %checkok4
|
||||
|
||||
checkok4: ; preds = %panic3, %checkok2
|
||||
@@ -500,7 +500,7 @@ checkok4: ; preds = %panic3, %checkok2
|
||||
br i1 %shift_underflow5, label %panic6, label %checkok7
|
||||
|
||||
panic6: ; preds = %checkok4
|
||||
call void @"std::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.32, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.33, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.34, i64 0, i64 0), i32 62)
|
||||
call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.32, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.33, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.34, i64 0, i64 0), i32 62)
|
||||
br label %checkok7
|
||||
|
||||
checkok7: ; preds = %panic6, %checkok4
|
||||
@@ -509,7 +509,7 @@ checkok7: ; preds = %panic6, %checkok4
|
||||
br i1 %shift_exceeds8, label %panic9, label %checkok10
|
||||
|
||||
panic9: ; preds = %checkok7
|
||||
call void @"std::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.35, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.36, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.37, i64 0, i64 0), i32 62)
|
||||
call void @"std::core::builtin.panic"(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.zstr.35, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.zstr.36, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.zstr.37, i64 0, i64 0), i32 62)
|
||||
br label %checkok10
|
||||
|
||||
checkok10: ; preds = %panic9, %checkok7
|
||||
|
||||
29
test/test_suite2/abi/aarch64_args.c3t
Normal file
29
test/test_suite2/abi/aarch64_args.c3t
Normal file
@@ -0,0 +1,29 @@
|
||||
// #target: macos-aarch64
|
||||
module test;
|
||||
|
||||
struct Large {
|
||||
void*[8] pointers;
|
||||
}
|
||||
|
||||
extern fn void pass_large(Large);
|
||||
|
||||
fn void example() {
|
||||
Large l = {};
|
||||
pass_large(l);
|
||||
pass_large(l);
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define void @test.example() #0 {
|
||||
entry:
|
||||
%l = alloca %Large, align 8
|
||||
%indirectarg = alloca %Large, align 8
|
||||
%indirectarg1 = alloca %Large, align 8
|
||||
call void @llvm.memset.p0.i64(ptr align 8 %l, i8 0, i64 64, i1 false)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 8 %l, i32 64, i1 false)
|
||||
call void @pass_large(ptr align 8 %indirectarg)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg1, ptr align 8 %l, i32 64, i1 false)
|
||||
call void @pass_large(ptr align 8 %indirectarg1)
|
||||
ret void
|
||||
}
|
||||
32
test/test_suite2/abi/aarch64_hfa_args.c3t
Normal file
32
test/test_suite2/abi/aarch64_hfa_args.c3t
Normal file
@@ -0,0 +1,32 @@
|
||||
// #target: macos-aarch64
|
||||
module test;
|
||||
define Int8x16 = ichar[<16>];
|
||||
define Float32x3 = float[<3>];
|
||||
|
||||
struct HFAv3
|
||||
{
|
||||
Float32x3[4] arr;
|
||||
}
|
||||
|
||||
struct MixedHFAv3
|
||||
{
|
||||
Float32x3[3] arr;
|
||||
Int8x16 b;
|
||||
}
|
||||
|
||||
fn HFAv3 test(HFAv3 a0, HFAv3 a1, HFAv3 a2) {
|
||||
return a2;
|
||||
}
|
||||
|
||||
fn MixedHFAv3 test_mixed(MixedHFAv3 a0, MixedHFAv3 a1, MixedHFAv3 a2) {
|
||||
return a2;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
|
||||
%HFAv3 = type { [4 x <3 x float>] }
|
||||
%MixedHFAv3 = type { [3 x <3 x float>], <16 x i8> }
|
||||
|
||||
define %HFAv3 @test.test([4 x <4 x float>] %0, [4 x <4 x float>] %1, [4 x <4 x float>] %2)
|
||||
define %MixedHFAv3 @test.test_mixed([4 x <4 x float>] %0, [4 x <4 x float>] %1, [4 x <4 x float>] %2) #0 {
|
||||
141
test/test_suite2/abi/darwin64_avx.c3t
Normal file
141
test/test_suite2/abi/darwin64_avx.c3t
Normal file
@@ -0,0 +1,141 @@
|
||||
// #target: macos-x64
|
||||
// #opt: --x86vec=avx
|
||||
module test;
|
||||
|
||||
define Mm256 = float[<8>];
|
||||
struct St256 {
|
||||
Mm256 m;
|
||||
}
|
||||
|
||||
St256 x38;
|
||||
Mm256 x37;
|
||||
|
||||
extern fn void f38(St256 x);
|
||||
extern fn void f37(Mm256 x);
|
||||
fn void f39() { f38(x38); f37(x37); }
|
||||
|
||||
// The two next tests make sure that the struct below is passed
|
||||
// in the same way regardless of avx being used
|
||||
|
||||
// CHECK: declare void @func40(%struct.t128* byval(%struct.t128) align 16)
|
||||
|
||||
define Mm128 = float[<4>];
|
||||
struct Two128 {
|
||||
Mm128 m;
|
||||
Mm128 n;
|
||||
}
|
||||
|
||||
extern fn void func40(Two128 s);
|
||||
fn void func41(Two128 s) {
|
||||
func40(s);
|
||||
}
|
||||
|
||||
struct Atwo128 {
|
||||
Mm128[2] array;
|
||||
}
|
||||
|
||||
struct Sa {
|
||||
Atwo128 x;
|
||||
}
|
||||
|
||||
extern fn void func42(Sa s);
|
||||
fn void func43(Sa s) {
|
||||
func42(s);
|
||||
}
|
||||
|
||||
|
||||
define Vec46 = float[<2>];
|
||||
extern fn void f46(Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46);
|
||||
fn void test46() { Vec46 x = {1,2}; f46(x,x,x,x,x,x,x,x,x,x); }
|
||||
|
||||
struct Vec47 { uint a; }
|
||||
extern fn void f47(int,int,int,int,int,int,Vec47);
|
||||
fn void test47(int a, Vec47 b) { f47(a, a, a, a, a, a, b); }
|
||||
|
||||
fn void test49_helper(double, ...);
|
||||
fn void test49(double d, double e) { test49_helper(d, e); }
|
||||
|
||||
struct Complex { double i; double c; }
|
||||
extern fn void test52_helper(int, ...);
|
||||
Mm256 x52;
|
||||
fn void test52() {
|
||||
test52_helper(0, x52, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 0, 1.0 });
|
||||
}
|
||||
|
||||
extern fn void test54_helper(Mm256, ...);
|
||||
Mm256 x54;
|
||||
fn void test54() {
|
||||
test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 0, 1.0 });
|
||||
test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 0, 1.0 });
|
||||
}
|
||||
|
||||
define Mm512 = float[<16>];
|
||||
struct St512 {
|
||||
Mm512 m;
|
||||
}
|
||||
|
||||
St512 x55;
|
||||
Mm512 x56;
|
||||
|
||||
extern fn void f55(St512 x);
|
||||
|
||||
extern fn void f56(Mm512 x);
|
||||
fn void f57() { f55(x55); f56(x56); }
|
||||
|
||||
struct Two256 {
|
||||
Mm256 m;
|
||||
Mm256 n;
|
||||
}
|
||||
|
||||
extern fn void f58(Two256 s);
|
||||
fn void f59(Two256 s) {
|
||||
f58(s);
|
||||
}
|
||||
|
||||
struct Atwo256 {
|
||||
Mm256[2] array;
|
||||
}
|
||||
|
||||
struct SAtwo256 {
|
||||
Atwo256 x;
|
||||
}
|
||||
|
||||
extern fn void f60(SAtwo256 s);
|
||||
fn void f61(SAtwo256 s) {
|
||||
f60(s);
|
||||
}
|
||||
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
declare void @f38(<8 x float>)
|
||||
declare void @f37(<8 x float>)
|
||||
|
||||
declare void @func40(ptr byval(%Two128) align 16)
|
||||
define void @test.func41(ptr byval(%Two128) align 16 %0)
|
||||
|
||||
declare void @func42(ptr byval(%Sa) align 16)
|
||||
define void @test.func43(ptr byval(%Sa) align 16 %0)
|
||||
|
||||
declare void @f46(double, double, double, double, double, double, double, double, ptr byval(<2 x float>) align 8, ptr byval(<2 x float>) align 8) #0
|
||||
declare void @f47(i32, i32, i32, i32, i32, i32, i32)
|
||||
|
||||
declare void @test.test49_helper(double, ...)
|
||||
define void @test.test49(double %0, double %1)
|
||||
entry:
|
||||
call void (double, ...) @test.test49_helper(double %0, double %1)
|
||||
ret void
|
||||
|
||||
call void (i32, ...) @test52_helper(i32 0, <8 x float> %0, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double %lo, double %hi)
|
||||
call void (<8 x float>, ...) @test54_helper(<8 x float> %0, <8 x float> %1, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double %lo, double %hi)
|
||||
call void (<8 x float>, ...) @test54_helper(<8 x float> %6, <8 x float> %7, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, ptr byval(%Complex) align 8 %indirectarg)
|
||||
|
||||
declare void @f55(ptr byval(%St512) align 64)
|
||||
declare void @f56(ptr byval(<16 x float>) align 64)
|
||||
|
||||
declare void @f58(ptr byval(%Two256) align 32)
|
||||
define void @test.f59(ptr byval(%Two256) align 32 %0)
|
||||
|
||||
declare void @f60(ptr byval(%SAtwo256) align 32)
|
||||
|
||||
define void @test.f61(ptr byval(%SAtwo256) align 32 %0) #0 {
|
||||
74
test/test_suite2/abi/darwin64_avx512.c3t
Normal file
74
test/test_suite2/abi/darwin64_avx512.c3t
Normal file
@@ -0,0 +1,74 @@
|
||||
// #target: macos-x64
|
||||
// #opt: --x86vec=avx512
|
||||
module test;
|
||||
|
||||
define Mm256 = float[<8>];
|
||||
define Mm512 = float[<16>];
|
||||
struct St512 {
|
||||
Mm512 m;
|
||||
}
|
||||
|
||||
St512 x55;
|
||||
Mm512 x56;
|
||||
|
||||
extern fn void f55(St512 x);
|
||||
|
||||
extern fn void f56(Mm512 x);
|
||||
fn void f57() { f55(x55); f56(x56); }
|
||||
|
||||
struct Two256 {
|
||||
Mm256 m;
|
||||
Mm256 n;
|
||||
}
|
||||
|
||||
extern fn void f58(Two256 s);
|
||||
fn void f59(Two256 s) {
|
||||
f58(s);
|
||||
}
|
||||
|
||||
struct Atwo256 {
|
||||
Mm256[2] array;
|
||||
}
|
||||
|
||||
struct SAtwo256 {
|
||||
Atwo256 x;
|
||||
}
|
||||
|
||||
extern fn void f60(SAtwo256 s);
|
||||
fn void f61(SAtwo256 s) {
|
||||
f60(s);
|
||||
}
|
||||
|
||||
struct Complex { double i; double c; }
|
||||
|
||||
// AVX512: @f62_helper(i32 0, <16 x float> {{%[a-zA-Z0-9]+}}, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double {{%[a-zA-Z0-9]+}}, double {{%[a-zA-Z0-9]+}})
|
||||
fn void f62_helper(int, ...);
|
||||
Mm512 x62;
|
||||
fn void f62() {
|
||||
f62_helper(0, x62, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 1.0, 1.0 });
|
||||
}
|
||||
|
||||
fn void f64_helper(Mm512, ...);
|
||||
Mm512 x64;
|
||||
fn void f64() {
|
||||
f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 1.0, 1.0 });
|
||||
f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 1.0, 1.0 });
|
||||
}
|
||||
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
declare void @f55(<16 x float>) #0
|
||||
declare void @f56(<16 x float>) #0
|
||||
|
||||
declare void @f58(ptr byval(%Two256) align 32) #0
|
||||
define void @test.f59(ptr byval(%Two256) align 32 %0) #0 {
|
||||
|
||||
declare void @f60(ptr byval(%SAtwo256) align 32) #0
|
||||
define void @test.f61(ptr byval(%SAtwo256) align 32 %0) #0 {
|
||||
|
||||
define void @test.f62() #0 {
|
||||
call void (i32, ...) @test.f62_helper(i32 0, <16 x float> %0, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double %lo, double %hi)
|
||||
define void @test.f64() #0 {
|
||||
call void (<16 x float>, ...) @test.f64_helper(<16 x float> %0, <16 x float> %1, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double %lo, double %hi)
|
||||
call void (<16 x float>, ...) @test.f64_helper(<16 x float> %6, <16 x float> %7, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, ptr byval(%Complex) align 8 %indirectarg)
|
||||
56
test/test_suite2/abi/darwin64_sse.c3t
Normal file
56
test/test_suite2/abi/darwin64_sse.c3t
Normal file
@@ -0,0 +1,56 @@
|
||||
// #target: macos-x64
|
||||
// #opt: --x86vec=sse
|
||||
module test;
|
||||
|
||||
define Mm256 = float[<8>];
|
||||
struct St256 {
|
||||
Mm256 m;
|
||||
}
|
||||
|
||||
St256 x38;
|
||||
Mm256 x37;
|
||||
|
||||
extern fn void f38(St256 x);
|
||||
extern fn void f37(Mm256 x);
|
||||
fn void f39() { f38(x38); f37(x37); }
|
||||
|
||||
// The two next tests make sure that the struct below is passed
|
||||
// in the same way regardless of avx being used
|
||||
|
||||
// CHECK: declare void @func40(%struct.t128* byval(%struct.t128) align 16)
|
||||
|
||||
define Mm128 = float[<4>];
|
||||
struct Two128 {
|
||||
Mm128 m;
|
||||
Mm128 n;
|
||||
}
|
||||
|
||||
extern fn void func40(Two128 s);
|
||||
fn void func41(Two128 s) {
|
||||
func40(s);
|
||||
}
|
||||
|
||||
struct Atwo128 {
|
||||
Mm128[2] array;
|
||||
}
|
||||
|
||||
struct Sa {
|
||||
Atwo128 x;
|
||||
}
|
||||
|
||||
extern fn void func42(Sa s);
|
||||
fn void func43(Sa s) {
|
||||
func42(s);
|
||||
}
|
||||
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
declare void @f38(ptr byval(%St256) align 32)
|
||||
declare void @f37(ptr byval(<8 x float>) align 32)
|
||||
|
||||
declare void @func40(ptr byval(%Two128) align 16)
|
||||
define void @test.func41(ptr byval(%Two128) align 16 %0)
|
||||
|
||||
declare void @func42(ptr byval(%Sa) align 16)
|
||||
define void @test.func43(ptr byval(%Sa) align 16 %0)
|
||||
48
test/test_suite2/abi/darwinx64_1.c3t
Normal file
48
test/test_suite2/abi/darwinx64_1.c3t
Normal file
@@ -0,0 +1,48 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
|
||||
fn char f0() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn short f1() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn int f2() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn float f3() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn double f4() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn void f6(char a0, short a1, int a2, long a3, void *a4) {}
|
||||
|
||||
enum Enum7 : int { A, B, C }
|
||||
fn void f7(Enum7 a0) {}
|
||||
|
||||
struct Struct8
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
}
|
||||
|
||||
fn Struct8 f8_1() { while (1) {} return Struct8 {}; }
|
||||
fn void f8_2(Struct8 a0) {}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define zeroext i8 @test.f0()
|
||||
define signext i16 @test.f1()
|
||||
define i32 @test.f2()
|
||||
define float @test.f3()
|
||||
define double @test.f4()
|
||||
define void @test.f6(i8 zeroext %0, i16 signext %1, i32 %2, i64 %3, ptr %4)
|
||||
define void @test.f7(i32 %0)
|
||||
define i64 @test.f8_1()
|
||||
define void @test.f8_2(i64 %0) #0 {
|
||||
186
test/test_suite2/abi/darwinx64_2.c3t
Normal file
186
test/test_suite2/abi/darwinx64_2.c3t
Normal file
@@ -0,0 +1,186 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
import std;
|
||||
|
||||
struct St12
|
||||
{
|
||||
int a @align(16);
|
||||
}
|
||||
fn St12 f12_0(void) { while (1) {}; unreachable(); }
|
||||
fn void f12_1(St12 a0) {}
|
||||
|
||||
struct St13_0 { long[3] f0; }
|
||||
struct St13_1 { long[2] f0; }
|
||||
fn St13_0 f13(int a, int b, int c, int d,
|
||||
St13_1 e, int f) { while (1) {}; unreachable(); }
|
||||
|
||||
fn void f14(int a, int b, int c, int d, int e, int f, ichar x) {}
|
||||
|
||||
fn void f15(int a, int b, int c, int d, int e, int f, void *x) {}
|
||||
|
||||
fn void f16(float a, float b, float c, float d, float e, float f, float g, float h,
|
||||
float x) {}
|
||||
|
||||
struct Fl18_s0 { int f0; }
|
||||
fn void fl18(int a, Fl18_s0 f18_arg1) { while (1) {} }
|
||||
|
||||
struct St20 @align(32) {
|
||||
int x;
|
||||
int y;
|
||||
}
|
||||
fn void f20(St20 x) {}
|
||||
|
||||
struct StringRef
|
||||
{
|
||||
int x;
|
||||
char* ptr;
|
||||
}
|
||||
fn char *f21(StringRef s) { return s.x+s.ptr; }
|
||||
|
||||
struct St22s @align(16)
|
||||
{ ulong[2] x; }
|
||||
fn void f22(St22s x, St22s y) { }
|
||||
|
||||
|
||||
|
||||
struct St23S {
|
||||
short f0;
|
||||
uint f1;
|
||||
int f2;
|
||||
}
|
||||
|
||||
|
||||
fn void f23(int a, St23S b) {
|
||||
}
|
||||
|
||||
struct St24s { int a; int b; }
|
||||
|
||||
fn St23S f24(St23S *x, St24s *p2)
|
||||
{
|
||||
return *x;
|
||||
|
||||
}
|
||||
|
||||
fn float[<4>] f25(float[<4>] x) {
|
||||
return x+x;
|
||||
}
|
||||
|
||||
struct Foo26 {
|
||||
int *x;
|
||||
float *y;
|
||||
}
|
||||
|
||||
fn Foo26 f26(Foo26 *p) {
|
||||
return *p;
|
||||
}
|
||||
|
||||
|
||||
struct V4f32wrapper {
|
||||
float[<4>] v;
|
||||
}
|
||||
|
||||
fn V4f32wrapper f27(V4f32wrapper x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
// PR22563 - We should unwrap simple structs and arrays to pass
|
||||
// and return them in the appropriate vector registers if possible.
|
||||
|
||||
define V8f32 = float[<8>];
|
||||
struct V8f32wrapper {
|
||||
V8f32 v;
|
||||
}
|
||||
|
||||
fn V8f32wrapper f27a(V8f32wrapper x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
struct V8f32wrapper_wrapper {
|
||||
V8f32[1] v;
|
||||
}
|
||||
|
||||
fn V8f32wrapper_wrapper f27b(V8f32wrapper_wrapper x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
struct F28c {
|
||||
double x;
|
||||
int y;
|
||||
}
|
||||
fn void f28(F28c c) {
|
||||
}
|
||||
|
||||
struct Inner
|
||||
{
|
||||
double x;
|
||||
int y;
|
||||
}
|
||||
struct F29a
|
||||
{
|
||||
Inner[1] c;
|
||||
}
|
||||
|
||||
fn void f29a(F29a a) {
|
||||
}
|
||||
|
||||
struct St0 {
|
||||
char[8] f0; char f2; char f3; char f4; }
|
||||
fn void f30(St0 p_4) {
|
||||
}
|
||||
|
||||
struct F31foo { float a, b, c; }
|
||||
fn float f31(F31foo x) {
|
||||
return x.c;
|
||||
}
|
||||
|
||||
define V1i64 = ulong[<1>];
|
||||
|
||||
fn V1i64 f34(V1i64 arg) { return arg; }
|
||||
|
||||
|
||||
define V1i64_2 = uint[<2>];
|
||||
fn V1i64_2 f35(V1i64_2 arg) { return arg+arg; }
|
||||
|
||||
define V2i32 = float[<2>];
|
||||
fn V2i32 f36(V2i32 arg) { return arg; }
|
||||
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define i32 @test.f12_0()
|
||||
define void @test.f12_1(i32 %0)
|
||||
define void @test.f13(ptr noalias sret(%St13_0) align 8 %0, i32 %1, i32 %2, i32 %3, i32 %4, ptr byval(%St13_1) align 8 %5, i32 %6) #0 {
|
||||
define void @test.f14(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i8 signext %6) #0 {
|
||||
define void @test.f15(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, ptr %6)
|
||||
|
||||
define void @test.f16(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, float %8)
|
||||
|
||||
define void @test.fl18(i32 %0, i32 %1)
|
||||
define void @test.f20(ptr byval(%St20) align 32 %0)
|
||||
define ptr @test.f21(i64 %0, ptr %1)
|
||||
|
||||
define void @test.f22(i64 %0, i64 %1, i64 %2, i64 %3)
|
||||
entry:
|
||||
%x = alloca %St22s, align 16
|
||||
%y = alloca %St22s, align 16
|
||||
|
||||
define void @test.f23(i32 %0, i64 %1, i32 %2)
|
||||
define { i64, i32 } @test.f24(ptr %0, ptr %1)
|
||||
|
||||
define <4 x float> @test.f25(<4 x float> %0) #0 {
|
||||
entry:
|
||||
%fadd = fadd <4 x float> %0, %0
|
||||
ret <4 x float> %fadd
|
||||
}
|
||||
|
||||
define { ptr, ptr } @test.f26(ptr %0)
|
||||
define <4 x float> @test.f27(<4 x float> %0)
|
||||
define <8 x float> @test.f27a(<8 x float> %0)
|
||||
define <8 x float> @test.f27b(<8 x float> %0)
|
||||
define void @test.f28(double %0, i32 %1)
|
||||
define void @test.f29a(double %0, i32 %1)
|
||||
define void @test.f30(i64 %0, i24 %1)
|
||||
define float @test.f31(<2 x float> %0, float %1)
|
||||
define double @test.f34(double %0)
|
||||
define double @test.f35(double %0)
|
||||
define double @test.f36(double %0)
|
||||
32
test/test_suite2/abi/literal_load.c3t
Normal file
32
test/test_suite2/abi/literal_load.c3t
Normal file
@@ -0,0 +1,32 @@
|
||||
// #target: macos-x64
|
||||
|
||||
struct Test
|
||||
{
|
||||
int x;
|
||||
}
|
||||
|
||||
Test foo = {};
|
||||
|
||||
extern fn void blorg(Test t);
|
||||
|
||||
fn Test creator()
|
||||
{
|
||||
blorg(Test{});
|
||||
return Test{};
|
||||
}
|
||||
|
||||
/* #expect: literal_load.ll
|
||||
|
||||
define i32 @literal_load.creator() #0 {
|
||||
entry:
|
||||
%literal = alloca %Test, align 4
|
||||
%literal1 = alloca %Test, align 4
|
||||
store i32 0, ptr %literal, align 4
|
||||
%0 = getelementptr inbounds %Test, ptr %literal, i32 0, i32 0
|
||||
%1 = load i32, ptr %0, align 4
|
||||
call void @blorg(i32 %1)
|
||||
store i32 0, ptr %literal1, align 4
|
||||
%2 = getelementptr inbounds %Test, ptr %literal1, i32 0, i32 0
|
||||
%3 = load i32, ptr %2, align 4
|
||||
ret i32 %3
|
||||
}
|
||||
36
test/test_suite2/abi/literal_load_aarch64.c3t
Normal file
36
test/test_suite2/abi/literal_load_aarch64.c3t
Normal file
@@ -0,0 +1,36 @@
|
||||
// #target: linux-aarch64
|
||||
module literal_load;
|
||||
|
||||
struct Test
|
||||
{
|
||||
int x;
|
||||
}
|
||||
|
||||
Test foo = {};
|
||||
|
||||
extern fn void blorg(Test t);
|
||||
|
||||
fn Test creator()
|
||||
{
|
||||
blorg(Test{});
|
||||
return Test{};
|
||||
}
|
||||
|
||||
/* #expect: literal_load.ll
|
||||
|
||||
declare void @blorg(i64) #0
|
||||
|
||||
define i32 @literal_load.creator() #0 {
|
||||
entry:
|
||||
%literal = alloca %Test, align 4
|
||||
%literal1 = alloca %Test, align 4
|
||||
store i32 0, ptr %literal, align 4
|
||||
%0 = getelementptr inbounds %Test, ptr %literal, i32 0, i32 0
|
||||
%1 = load i32, ptr %0, align 4
|
||||
%2 = zext i32 %1 to i64
|
||||
call void @blorg(i64 %2)
|
||||
store i32 0, ptr %literal1, align 4
|
||||
%3 = getelementptr inbounds %Test, ptr %literal1, i32 0, i32 0
|
||||
%4 = load i32, ptr %3, align 4
|
||||
ret i32 %4
|
||||
}
|
||||
33
test/test_suite2/abi/literal_load_mingw.c3t
Normal file
33
test/test_suite2/abi/literal_load_mingw.c3t
Normal file
@@ -0,0 +1,33 @@
|
||||
// #target: mingw-x64
|
||||
module literal_load;
|
||||
|
||||
struct Test
|
||||
{
|
||||
int x;
|
||||
}
|
||||
|
||||
Test foo = {};
|
||||
|
||||
extern fn void blorg(Test t);
|
||||
|
||||
fn Test creator()
|
||||
{
|
||||
blorg(Test{});
|
||||
return Test{};
|
||||
}
|
||||
|
||||
/* #expect: literal_load.ll
|
||||
|
||||
define i32 @literal_load.creator() #0 {
|
||||
entry:
|
||||
%literal = alloca %Test, align 4
|
||||
%literal1 = alloca %Test, align 4
|
||||
store i32 0, ptr %literal, align 4
|
||||
%0 = getelementptr inbounds %Test, ptr %literal, i32 0, i32 0
|
||||
%1 = load i32, ptr %0, align 4
|
||||
call void @blorg(i32 %1)
|
||||
store i32 0, ptr %literal1, align 4
|
||||
%2 = getelementptr inbounds %Test, ptr %literal1, i32 0, i32 0
|
||||
%3 = load i32, ptr %2, align 4
|
||||
ret i32 %3
|
||||
}
|
||||
8
test/test_suite2/abi/macho_section_attributes.c3
Normal file
8
test/test_suite2/abi/macho_section_attributes.c3
Normal file
@@ -0,0 +1,8 @@
|
||||
// #target: macos-x64
|
||||
|
||||
int foo @section("foo, 12345678901234567 "); // #error: Mach-o requires the section to be at the most 16 characters
|
||||
int bar @section("foo, "); // #error: Mach-o requires 'segment,section' as the format, did you type it correctly?
|
||||
int baz @section("foo"); // #error: Mach-o requires 'segment,section' as the format, did you type it correctly?
|
||||
int abc @section("foo,b,c,d,e,f"); // #error: Too many parts to the Mach-o section description.
|
||||
int def @section("foo,b,c,d");
|
||||
|
||||
32
test/test_suite2/abi/pass_large_aarch.c3t
Normal file
32
test/test_suite2/abi/pass_large_aarch.c3t
Normal file
@@ -0,0 +1,32 @@
|
||||
// #target: linux-aarch64
|
||||
|
||||
module pass_large;
|
||||
|
||||
|
||||
struct Large
|
||||
{
|
||||
void*[8] pointers;
|
||||
}
|
||||
|
||||
extern fn void pass_large(Large large);
|
||||
|
||||
fn void example()
|
||||
{
|
||||
Large l = {};
|
||||
pass_large(l);
|
||||
pass_large(l);
|
||||
}
|
||||
|
||||
/* #expect: pass_large.ll
|
||||
|
||||
define void @pass_large.example()
|
||||
entry:
|
||||
%l = alloca %Large, align 8
|
||||
%indirectarg = alloca %Large, align 8
|
||||
%indirectarg1 = alloca %Large, align 8
|
||||
call void @llvm.memset.p0.i64(ptr align 8 %l, i8 0, i64 64, i1 false)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 8 %l, i32 64, i1 false)
|
||||
call void @pass_large(ptr align 8 %indirectarg)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg1, ptr align 8 %l, i32 64, i1 false)
|
||||
call void @pass_large(ptr align 8 %indirectarg1)
|
||||
ret void
|
||||
57
test/test_suite2/abi/regcall_expand.c3t
Normal file
57
test/test_suite2/abi/regcall_expand.c3t
Normal file
@@ -0,0 +1,57 @@
|
||||
// #target: mingw-x64
|
||||
module test;
|
||||
|
||||
extern fn void printf(char*, ...);
|
||||
|
||||
struct Foo
|
||||
{
|
||||
float[2] x;
|
||||
}
|
||||
fn void test(Foo x) @regcall
|
||||
{
|
||||
}
|
||||
|
||||
fn int main()
|
||||
{
|
||||
test(Foo { });
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
%Foo = type { [2 x float] }
|
||||
|
||||
$.typeid.test.Foo = comdat any
|
||||
|
||||
@.typeid.test.Foo = linkonce constant { i8, i64 } { i8 10, i64 1 }, comdat, align 8
|
||||
|
||||
declare void @printf(ptr, ...) #0
|
||||
|
||||
define x86_regcallcc void @test.test(float %0, float %1) #0 {
|
||||
entry:
|
||||
%x = alloca %Foo, align 4
|
||||
%2 = getelementptr inbounds %Foo, ptr %x, i32 0, i32 0
|
||||
%3 = getelementptr inbounds [2 x float], ptr %2, i64 0, i64 0
|
||||
store float %0, ptr %3, align 4
|
||||
%4 = getelementptr inbounds [2 x float], ptr %2, i64 0, i64 1
|
||||
store float %1, ptr %4, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
%literal = alloca %Foo, align 4
|
||||
%0 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 0
|
||||
%1 = getelementptr inbounds [2 x float], ptr %0, i64 0, i64 0
|
||||
store float 0.000000e+00, ptr %1, align 4
|
||||
%2 = getelementptr inbounds [2 x float], ptr %0, i64 0, i64 1
|
||||
store float 0.000000e+00, ptr %2, align 4
|
||||
%3 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 0
|
||||
%4 = getelementptr inbounds [2 x float], ptr %3, i64 0, i64 0
|
||||
%loadexpanded = load float, ptr %4, align 4
|
||||
%5 = getelementptr inbounds [2 x float], ptr %3, i64 0, i64 1
|
||||
%loadexpanded1 = load float, ptr %5, align 4
|
||||
call x86_regcallcc void @test.test(float %loadexpanded, float %loadexpanded1)
|
||||
ret i32 0
|
||||
}
|
||||
51
test/test_suite2/abi/riscv64-lp64-abi.c3t
Normal file
51
test/test_suite2/abi/riscv64-lp64-abi.c3t
Normal file
@@ -0,0 +1,51 @@
|
||||
// #target: linux-riscv64
|
||||
module test;
|
||||
|
||||
struct Large {
|
||||
long a, b, c, d;
|
||||
}
|
||||
|
||||
define V32i8 = char[<32>];
|
||||
|
||||
fn int f_scalar_stack_1(int a, int128 b, float c, float128 d, V32i8 e,
|
||||
char f, char g, char h) {
|
||||
return g + h;
|
||||
}
|
||||
|
||||
fn Large f_scalar_stack_2(double a, int128 b, float128 c, V32i8 d,
|
||||
char e, ichar f, char g) {
|
||||
return Large {(long)(a), e, f, g};
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define signext i32 @test.f_scalar_stack_1(i32 signext %0, i128 %1, float %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) #0 {
|
||||
entry:
|
||||
%e = alloca <32 x i8>, align 32
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 32 %e, ptr align 32 %4, i32 32, i1 false)
|
||||
%uisiext = zext i8 %6 to i32
|
||||
%uisiext1 = zext i8 %7 to i32
|
||||
%add = add i32 %uisiext, %uisiext1
|
||||
ret i32 %add
|
||||
}
|
||||
|
||||
define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 8 %0, double %1, i128 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) #0 {
|
||||
entry:
|
||||
%d = alloca <32 x i8>, align 32
|
||||
%literal = alloca %Large, align 8
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 32 %d, ptr align 32 %4, i32 32, i1 false)
|
||||
%8 = getelementptr inbounds %Large, ptr %literal, i32 0, i32 0
|
||||
%fpsi = fptosi double %1 to i64
|
||||
store i64 %fpsi, ptr %8, align 8
|
||||
%9 = getelementptr inbounds %Large, ptr %literal, i32 0, i32 1
|
||||
%uisiext = zext i8 %5 to i64
|
||||
store i64 %uisiext, ptr %9, align 8
|
||||
%10 = getelementptr inbounds %Large, ptr %literal, i32 0, i32 2
|
||||
%sisiext = sext i8 %6 to i64
|
||||
store i64 %sisiext, ptr %10, align 8
|
||||
%11 = getelementptr inbounds %Large, ptr %literal, i32 0, i32 3
|
||||
%uisiext1 = zext i8 %7 to i64
|
||||
store i64 %uisiext1, ptr %11, align 8
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 32, i1 false)
|
||||
ret void
|
||||
}
|
||||
66
test/test_suite2/abi/small_struct_x64.c3t
Normal file
66
test/test_suite2/abi/small_struct_x64.c3t
Normal file
@@ -0,0 +1,66 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
struct Foo
|
||||
{
|
||||
char a;
|
||||
char b;
|
||||
char c;
|
||||
}
|
||||
|
||||
fn int testing()
|
||||
{
|
||||
Foo y = getFoo(Foo { 4, 5, 6 });
|
||||
return y.a + y.c;
|
||||
}
|
||||
|
||||
fn Foo getFoo(Foo f)
|
||||
{
|
||||
return Foo { 1, 2, 3 };
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define i32 @test.testing() #0 {
|
||||
entry:
|
||||
%y = alloca %Foo, align 1
|
||||
%literal = alloca %Foo, align 1
|
||||
%tempcoerce = alloca i24, align 4
|
||||
%result = alloca %Foo, align 1
|
||||
%0 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 0
|
||||
store i8 4, ptr %0, align 1
|
||||
%1 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 1
|
||||
store i8 5, ptr %1, align 1
|
||||
%2 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 2
|
||||
store i8 6, ptr %2, align 1
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %tempcoerce, ptr align 1 %literal, i32 3, i1 false)
|
||||
%3 = load i24, ptr %tempcoerce, align 4
|
||||
%4 = call i24 @test.getFoo(i24 %3)
|
||||
store i24 %4, ptr %result, align 1
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 %result, i32 3, i1 false)
|
||||
%5 = getelementptr inbounds %Foo, ptr %y, i32 0, i32 0
|
||||
%6 = load i8, ptr %5, align 1
|
||||
%uisiext = zext i8 %6 to i32
|
||||
%7 = getelementptr inbounds %Foo, ptr %y, i32 0, i32 2
|
||||
%8 = load i8, ptr %7, align 1
|
||||
%uisiext1 = zext i8 %8 to i32
|
||||
%add = add i32 %uisiext, %uisiext1
|
||||
ret i32 %add
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i24 @test.getFoo(i24 %0) #0 {
|
||||
entry:
|
||||
%f = alloca %Foo, align 1
|
||||
%literal = alloca %Foo, align 1
|
||||
%tempcoerce = alloca i24, align 4
|
||||
store i24 %0, ptr %f, align 1
|
||||
%1 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 0
|
||||
store i8 1, ptr %1, align 1
|
||||
%2 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 1
|
||||
store i8 2, ptr %2, align 1
|
||||
%3 = getelementptr inbounds %Foo, ptr %literal, i32 0, i32 2
|
||||
store i8 3, ptr %3, align 1
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %tempcoerce, ptr align 1 %literal, i32 3, i1 false)
|
||||
%4 = load i24, ptr %tempcoerce, align 4
|
||||
ret i24 %4
|
||||
}
|
||||
43
test/test_suite2/abi/sysv_direct_coerce.c3t
Normal file
43
test/test_suite2/abi/sysv_direct_coerce.c3t
Normal file
@@ -0,0 +1,43 @@
|
||||
// #target: macos-x64
|
||||
module foo;
|
||||
|
||||
struct Rectangle
|
||||
{
|
||||
float x; // Rectangle top-left corner position x
|
||||
float y; // Rectangle top-left corner position y
|
||||
float width; // Rectangle width
|
||||
float height; // Rectangle height
|
||||
}
|
||||
|
||||
fn void test(Rectangle r)
|
||||
{
|
||||
test(Rectangle { 1, 2, 3, 4 });
|
||||
}
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
define void @foo.test(<2 x float> %0, <2 x float> %1) #0 {
|
||||
entry:
|
||||
%r = alloca %Rectangle, align 4
|
||||
%literal = alloca %Rectangle, align 4
|
||||
%coerce = alloca %Rectangle, align 8
|
||||
%2 = getelementptr inbounds { <2 x float>, <2 x float> }, ptr %r, i32 0, i32 0
|
||||
store <2 x float> %0, ptr %2, align 4
|
||||
%3 = getelementptr inbounds { <2 x float>, <2 x float> }, ptr %r, i32 0, i32 1
|
||||
store <2 x float> %1, ptr %3, align 4
|
||||
%4 = getelementptr inbounds %Rectangle, ptr %literal, i32 0, i32 0
|
||||
store float 1.000000e+00, ptr %4, align 4
|
||||
%5 = getelementptr inbounds %Rectangle, ptr %literal, i32 0, i32 1
|
||||
store float 2.000000e+00, ptr %5, align 4
|
||||
%6 = getelementptr inbounds %Rectangle, ptr %literal, i32 0, i32 2
|
||||
store float 3.000000e+00, ptr %6, align 4
|
||||
%7 = getelementptr inbounds %Rectangle, ptr %literal, i32 0, i32 3
|
||||
store float 4.000000e+00, ptr %7, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %coerce, ptr align 4 %literal, i32 16, i1 false)
|
||||
%8 = getelementptr inbounds { <2 x float>, <2 x float> }, ptr %coerce, i32 0, i32 0
|
||||
%lo = load <2 x float>, ptr %8, align 8
|
||||
%9 = getelementptr inbounds { <2 x float>, <2 x float> }, ptr %coerce, i32 0, i32 1
|
||||
%hi = load <2 x float>, ptr %9, align 8
|
||||
call void @foo.test(<2 x float> %lo, <2 x float> %hi)
|
||||
ret void
|
||||
}
|
||||
38
test/test_suite2/abi/test_sret.c3t
Normal file
38
test/test_suite2/abi/test_sret.c3t
Normal file
@@ -0,0 +1,38 @@
|
||||
// #target: macos-x64
|
||||
|
||||
struct Abc {
|
||||
long a;
|
||||
long b;
|
||||
long c;
|
||||
long d;
|
||||
long e;
|
||||
}
|
||||
|
||||
extern fn Abc foo1();
|
||||
extern fn Abc foo2();
|
||||
|
||||
fn void bar() {
|
||||
Abc dummy1 = foo1();
|
||||
Abc dummy2 = foo2();
|
||||
}
|
||||
|
||||
// Cleanup for this result, since it's creating an unnecessary sret.
|
||||
|
||||
/* #expect: test_sret.ll
|
||||
|
||||
declare void @foo1(ptr noalias sret(%Abc) align 8) #0
|
||||
|
||||
declare void @foo2(ptr noalias sret(%Abc) align 8) #0
|
||||
|
||||
define void @test_sret.bar() #0 {
|
||||
entry:
|
||||
%dummy1 = alloca %Abc, align 8
|
||||
%sretparam = alloca %Abc, align 8
|
||||
%dummy2 = alloca %Abc, align 8
|
||||
%sretparam1 = alloca %Abc, align 8
|
||||
call void @foo1(ptr sret(%Abc) align 8 %sretparam)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %dummy1, ptr align 8 %sretparam, i32 40, i1 false)
|
||||
call void @foo2(ptr sret(%Abc) align 8 %sretparam1)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %dummy2, ptr align 8 %sretparam1, i32 40, i1 false)
|
||||
ret void
|
||||
}
|
||||
37
test/test_suite2/abi/union_x64.c3t
Normal file
37
test/test_suite2/abi/union_x64.c3t
Normal file
@@ -0,0 +1,37 @@
|
||||
// #target: macos-x64
|
||||
|
||||
module unionx64;
|
||||
|
||||
union Foo
|
||||
{
|
||||
long a;
|
||||
char[12] b;
|
||||
}
|
||||
extern fn void hello2(Foo f);
|
||||
|
||||
fn void hello(Foo f)
|
||||
{
|
||||
hello2(f);
|
||||
}
|
||||
|
||||
/* #expect: unionx64.ll
|
||||
|
||||
%Foo = type { i64, [8 x i8] }
|
||||
|
||||
declare void @hello2(i64, i64) #0
|
||||
|
||||
define void @unionx64.hello(i64 %0, i64 %1) #0 {
|
||||
entry:
|
||||
%f = alloca %Foo, align 8
|
||||
%2 = getelementptr inbounds { i64, i64 }, ptr %f, i32 0, i32 0
|
||||
store i64 %0, ptr %2, align 8
|
||||
%3 = getelementptr inbounds { i64, i64 }, ptr %f, i32 0, i32 1
|
||||
store i64 %1, ptr %3, align 8
|
||||
%4 = getelementptr inbounds { i64, i64 }, ptr %f, i32 0, i32 0
|
||||
%lo = load i64, ptr %4, align 8
|
||||
%5 = getelementptr inbounds { i64, i64 }, ptr %f, i32 0, i32 1
|
||||
%hi = load i64, ptr %5, align 8
|
||||
call void @hello2(i64 %lo, i64 %hi)
|
||||
ret void
|
||||
}
|
||||
|
||||
95
test/test_suite2/abi/vec2_aarch64.c3t
Normal file
95
test/test_suite2/abi/vec2_aarch64.c3t
Normal file
@@ -0,0 +1,95 @@
|
||||
// #target: linux-aarch64
|
||||
module abi;
|
||||
|
||||
struct Vector2 {
|
||||
float x;
|
||||
float y;
|
||||
}
|
||||
extern fn Vector2 vector2_zero() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_one() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add_value(Vector2 v, float add) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract_value(Vector2 v, float sub) { return Vector2 {}; }
|
||||
|
||||
/* #expect: abi.ll
|
||||
|
||||
%Vector2 = type { float, float }
|
||||
|
||||
define %Vector2 @vector2_zero() #0 {
|
||||
entry:
|
||||
%literal = alloca %Vector2, align 4
|
||||
%0 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %0, align 4
|
||||
%1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %1, align 4
|
||||
%2 = load %Vector2, ptr %literal, align 4
|
||||
ret %Vector2 %2
|
||||
}
|
||||
|
||||
define %Vector2 @vector2_one() #0 {
|
||||
entry:
|
||||
%literal = alloca %Vector2, align 4
|
||||
%0 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %0, align 4
|
||||
%1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %1, align 4
|
||||
%2 = load %Vector2, ptr %literal, align 4
|
||||
ret %Vector2 %2
|
||||
}
|
||||
|
||||
define %Vector2 @vector2_add([2 x float] %0, [2 x float] %1) #0 {
|
||||
entry:
|
||||
%v1 = alloca %Vector2, align 4
|
||||
%v2 = alloca %Vector2, align 4
|
||||
%literal = alloca %Vector2, align 4
|
||||
store [2 x float] %0, ptr %v1, align 4
|
||||
store [2 x float] %1, ptr %v2, align 4
|
||||
%2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %2, align 4
|
||||
%3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %3, align 4
|
||||
%4 = load %Vector2, ptr %literal, align 4
|
||||
ret %Vector2 %4
|
||||
}
|
||||
|
||||
define %Vector2 @vector2_add_value([2 x float] %0, float %1) #0 {
|
||||
entry:
|
||||
%v = alloca %Vector2, align 4
|
||||
%literal = alloca %Vector2, align 4
|
||||
store [2 x float] %0, ptr %v, align 4
|
||||
%2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %2, align 4
|
||||
%3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %3, align 4
|
||||
%4 = load %Vector2, ptr %literal, align 4
|
||||
ret %Vector2 %4
|
||||
}
|
||||
|
||||
define %Vector2 @vector2_subtract([2 x float] %0, [2 x float] %1) #0 {
|
||||
entry:
|
||||
%v1 = alloca %Vector2, align 4
|
||||
%v2 = alloca %Vector2, align 4
|
||||
%literal = alloca %Vector2, align 4
|
||||
store [2 x float] %0, ptr %v1, align 4
|
||||
store [2 x float] %1, ptr %v2, align 4
|
||||
%2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %2, align 4
|
||||
%3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %3, align 4
|
||||
%4 = load %Vector2, ptr %literal, align 4
|
||||
ret %Vector2 %4
|
||||
}
|
||||
|
||||
define %Vector2 @vector2_subtract_value([2 x float] %0, float %1) #0 {
|
||||
entry:
|
||||
%v = alloca %Vector2, align 4
|
||||
%literal = alloca %Vector2, align 4
|
||||
store [2 x float] %0, ptr %v, align 4
|
||||
%2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %2, align 4
|
||||
%3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %3, align 4
|
||||
%4 = load %Vector2, ptr %literal, align 4
|
||||
ret %Vector2 %4
|
||||
}
|
||||
98
test/test_suite2/abi/vec2_wasm.c3t
Normal file
98
test/test_suite2/abi/vec2_wasm.c3t
Normal file
@@ -0,0 +1,98 @@
|
||||
// #target: wasm32
|
||||
module abi;
|
||||
|
||||
struct Vector2 {
|
||||
float x;
|
||||
float y;
|
||||
}
|
||||
extern fn Vector2 vector2_zero() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_one() { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_add_value(Vector2 v, float add) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) { return Vector2 {}; }
|
||||
extern fn Vector2 vector2_subtract_value(Vector2 v, float sub) { return Vector2 {}; }
|
||||
|
||||
/* #expect: abi.ll
|
||||
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
%Vector2 = type { float, float }
|
||||
|
||||
define void @vector2_zero(ptr noalias sret(%Vector2) align 4 %0) #0 {
|
||||
entry:
|
||||
%literal = alloca %Vector2, align 4
|
||||
%1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %1, align 4
|
||||
%2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %2, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @vector2_one(ptr noalias sret(%Vector2) align 4 %0) #0 {
|
||||
entry:
|
||||
%literal = alloca %Vector2, align 4
|
||||
%1 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %1, align 4
|
||||
%2 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %2, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @vector2_add(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, ptr byval(%Vector2) align 4 %2) #0 {
|
||||
entry:
|
||||
%v1 = alloca %Vector2, align 4
|
||||
%v2 = alloca %Vector2, align 4
|
||||
%literal = alloca %Vector2, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v1, ptr align 4 %1, i32 8, i1 false)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v2, ptr align 4 %2, i32 8, i1 false)
|
||||
%3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %3, align 4
|
||||
%4 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %4, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @vector2_add_value(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, float %2) #0 {
|
||||
entry:
|
||||
%v = alloca %Vector2, align 4
|
||||
%literal = alloca %Vector2, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v, ptr align 4 %1, i32 8, i1 false)
|
||||
%3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %3, align 4
|
||||
%4 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %4, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @vector2_subtract(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, ptr byval(%Vector2) align 4 %2) #0 {
|
||||
entry:
|
||||
%v1 = alloca %Vector2, align 4
|
||||
%v2 = alloca %Vector2, align 4
|
||||
%literal = alloca %Vector2, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v1, ptr align 4 %1, i32 8, i1 false)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v2, ptr align 4 %2, i32 8, i1 false)
|
||||
%3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %3, align 4
|
||||
%4 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %4, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @vector2_subtract_value(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, float %2) #0 {
|
||||
entry:
|
||||
%v = alloca %Vector2, align 4
|
||||
%literal = alloca %Vector2, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %v, ptr align 4 %1, i32 8, i1 false)
|
||||
%3 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 0
|
||||
store float 0.000000e+00, ptr %3, align 4
|
||||
%4 = getelementptr inbounds %Vector2, ptr %literal, i32 0, i32 1
|
||||
store float 0.000000e+00, ptr %4, align 4
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user