mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Compare commits
14 Commits
0.4
...
0.4stripun
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0de47d7c83 | ||
|
|
cfd21f8ca2 | ||
|
|
d0e8944c56 | ||
|
|
3e54d13b62 | ||
|
|
b30d130d92 | ||
|
|
4cf98dab93 | ||
|
|
ea1a5435bb | ||
|
|
275e3c6a09 | ||
|
|
9de02efa01 | ||
|
|
e0cfb39d79 | ||
|
|
d4259368a2 | ||
|
|
07b107ff5e | ||
|
|
b794c893d6 | ||
|
|
2e498a426e |
126
.github/workflows/main.yml
vendored
126
.github/workflows/main.yml
vendored
@@ -283,6 +283,111 @@ jobs:
|
||||
name: c3-linux-${{matrix.build_type}}
|
||||
path: c3-linux-${{matrix.build_type}}.tar.gz
|
||||
|
||||
build-linux-ubuntu20:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
# Don't abort runners if a single one fails
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
llvm_version: [16]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install common deps
|
||||
run: |
|
||||
sudo apt-get install zlib1g zlib1g-dev python3 ninja-build curl
|
||||
|
||||
- name: Install Clang ${{matrix.llvm_version}}
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
if [[ "${{matrix.llvm_version}}" < 17 ]]; then
|
||||
sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${{matrix.llvm_version}} main"
|
||||
else
|
||||
sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal main"
|
||||
fi
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang-${{matrix.llvm_version}} llvm-${{matrix.llvm_version}} llvm-${{matrix.llvm_version}}-dev lld-${{matrix.llvm_version}} liblld-${{matrix.llvm_version}}-dev
|
||||
sudo apt-get install -y libmlir-${{matrix.llvm_version}} libmlir-${{matrix.llvm_version}}-dev mlir-${{matrix.llvm_version}}-tools
|
||||
sudo apt-get install -y libpolly-${{matrix.llvm_version}}-dev
|
||||
- name: CMake
|
||||
run: |
|
||||
cmake -B build \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
|
||||
-DCMAKE_C_COMPILER=clang-${{matrix.llvm_version}} \
|
||||
-DCMAKE_CXX_COMPILER=clang++-${{matrix.llvm_version}} \
|
||||
-DCMAKE_LINKER=lld-link-${{matrix.llvm_version}} \
|
||||
-DCMAKE_OBJCOPY=llvm-objcopy-${{matrix.llvm_version}} \
|
||||
-DCMAKE_STRIP=llvm-strip-${{matrix.llvm_version}} \
|
||||
-DCMAKE_DLLTOOL=llvm-dlltool-${{matrix.llvm_version}} \
|
||||
-DC3_LLVM_VERSION=${{matrix.llvm_version}}
|
||||
cmake --build build
|
||||
|
||||
- name: Compile and run some examples
|
||||
run: |
|
||||
cd resources
|
||||
../build/c3c compile examples/base64.c3
|
||||
../build/c3c compile examples/binarydigits.c3
|
||||
../build/c3c compile examples/brainfk.c3
|
||||
../build/c3c compile examples/factorial_macro.c3
|
||||
../build/c3c compile examples/fasta.c3
|
||||
../build/c3c compile examples/gameoflife.c3
|
||||
../build/c3c compile examples/hash.c3
|
||||
../build/c3c compile examples/levenshtein.c3
|
||||
../build/c3c compile examples/load_world.c3
|
||||
../build/c3c compile examples/map.c3
|
||||
../build/c3c compile examples/mandelbrot.c3
|
||||
../build/c3c compile examples/plus_minus.c3
|
||||
../build/c3c compile examples/nbodies.c3
|
||||
../build/c3c compile examples/spectralnorm.c3
|
||||
../build/c3c compile examples/swap.c3
|
||||
../build/c3c compile examples/contextfree/boolerr.c3
|
||||
../build/c3c compile examples/contextfree/dynscope.c3
|
||||
../build/c3c compile examples/contextfree/guess_number.c3
|
||||
../build/c3c compile examples/contextfree/multi.c3
|
||||
../build/c3c compile examples/contextfree/cleanup.c3
|
||||
../build/c3c compile-run examples/hello_world_many.c3
|
||||
../build/c3c compile-run examples/time.c3
|
||||
../build/c3c compile-run examples/fannkuch-redux.c3
|
||||
../build/c3c compile-run examples/contextfree/boolerr.c3
|
||||
../build/c3c compile-run examples/load_world.c3
|
||||
|
||||
- name: Compile run unit tests
|
||||
run: |
|
||||
cd test
|
||||
../build/c3c compile-test unit -g1 --safe
|
||||
|
||||
- name: Build testproject
|
||||
run: |
|
||||
cd resources/testproject
|
||||
../../build/c3c run --debug-log
|
||||
|
||||
- name: Build testproject direct linker
|
||||
run: |
|
||||
cd resources/testproject
|
||||
../../build/c3c run --debug-log --forcelinker
|
||||
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
cd test
|
||||
python3 src/tester.py ../build/c3c test_suite/
|
||||
|
||||
- name: bundle_output
|
||||
if: matrix.llvm_version == 16
|
||||
run: |
|
||||
mkdir linux
|
||||
cp -r lib linux
|
||||
cp msvc_build_libraries.py linux
|
||||
cp build/c3c linux
|
||||
tar czf c3-ubuntu-20-${{matrix.build_type}}.tar.gz linux
|
||||
|
||||
- name: upload artifacts
|
||||
if: matrix.llvm_version == 16
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: c3-ubuntu-20-${{matrix.build_type}}
|
||||
path: c3-ubuntu-20-${{matrix.build_type}}.tar.gz
|
||||
|
||||
build-mac:
|
||||
runs-on: macos-latest
|
||||
@@ -450,6 +555,27 @@ jobs:
|
||||
asset_name: c3-linux-debug.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
|
||||
- name: upload ubuntu 20
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
|
||||
asset_path: c3-ubuntu-20-Release/c3-ubuntu-20-Release.tar.gz
|
||||
asset_name: c3-ubuntu-20.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
|
||||
- name: upload ubuntu 20 debug
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: c3-ubuntu-20-Debug/c3-ubuntu-20-Debug.tar.gz
|
||||
asset_name: c3-ubuntu-20-debug.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
|
||||
- name: upload macos
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
|
||||
@@ -79,9 +79,9 @@ import stack;
|
||||
|
||||
// Define our new types, the first will implicitly create
|
||||
// a complete copy of the entire Stack module with "Type" set to "int"
|
||||
typedef IntStack = Stack<int>;
|
||||
def IntStack = Stack<int>;
|
||||
// The second creates another copy with "Type" set to "double"
|
||||
typedef DoubleStack = Stack<double>;
|
||||
def DoubleStack = Stack<double>;
|
||||
|
||||
// If we had added "define IntStack2 = Stack<int>"
|
||||
// no additional copy would have been made (since we already
|
||||
@@ -92,7 +92,7 @@ typedef DoubleStack = Stack<double>;
|
||||
// here is an example of importing libc's printf:
|
||||
extern fn int printf(char* format, ...);
|
||||
|
||||
fn void test()
|
||||
fn void main()
|
||||
{
|
||||
IntStack stack;
|
||||
// Note that C3 uses zero initialization by default
|
||||
@@ -112,7 +112,7 @@ fn void test()
|
||||
dstack.push(2.3);
|
||||
dstack.push(3.141);
|
||||
dstack.push(1.1235);
|
||||
// Prints pop: 1.1235
|
||||
// Prints pop: 1.123500
|
||||
printf("pop: %f\n", dstack.pop());
|
||||
}
|
||||
```
|
||||
|
||||
@@ -26,12 +26,8 @@ struct Object
|
||||
}
|
||||
}
|
||||
|
||||
static initialize
|
||||
{
|
||||
io::formatter_register_type(Object);
|
||||
}
|
||||
|
||||
fn void! Object.to_format(Object* o, Formatter* formatter)
|
||||
fn void! Object.to_format(Object* o, Formatter* formatter) @dynamic
|
||||
{
|
||||
switch (o.type)
|
||||
{
|
||||
|
||||
@@ -22,10 +22,11 @@ fault FormattingFault
|
||||
}
|
||||
|
||||
def OutputFn = fn void!(char c, void* buffer);
|
||||
def ToStringFunction = fn String(void* value, Allocator *using);
|
||||
def ToFormatFunction = fn void!(void* value, Formatter* formatter);
|
||||
def FloatType = double;
|
||||
|
||||
fn String any.to_string(void* value, Allocator *using) @interface;
|
||||
fn void! any.to_format(void* value, Formatter* formatter) @interface;
|
||||
|
||||
fn usz! printf(String format, args...) @maydiscard
|
||||
{
|
||||
Formatter formatter;
|
||||
@@ -102,41 +103,6 @@ fn void Formatter.init(Formatter* this, OutputFn out_fn, void* data = null)
|
||||
*this = { .data = data, .out_fn = out_fn};
|
||||
}
|
||||
|
||||
/**
|
||||
* @require $checks($Type a, a.to_string()) || $checks($Type a, a.to_format(&&Formatter{})) "Expected a type with 'to_string' or 'to_format' defined"
|
||||
* @require !$checks($Type a, a.to_string()) || $checks($Type a, a.to_string(&&Allocator{})) "Expected 'to_string' to take an allocator as argument."
|
||||
* @require !$checks($Type a, a.to_format(&&Formatter{})) || $checks($Type a, Formatter b, a.to_format(&b)) "Expected 'to_format' to take a Formatter as argument."
|
||||
*/
|
||||
macro void formatter_register_type($Type)
|
||||
{
|
||||
$if $checks($Type a, a.to_format(&&Formatter {})):
|
||||
if (!toformat_functions.table.len)
|
||||
{
|
||||
toformat_functions.init(64);
|
||||
}
|
||||
toformat_functions.set($Type.typeid, (ToFormatFunction)&$Type.to_format);
|
||||
$else
|
||||
if (!tostring_functions.table.len)
|
||||
{
|
||||
tostring_functions.init(64);
|
||||
}
|
||||
tostring_functions.set($Type.typeid, (ToStringFunction)&$Type.to_string);
|
||||
$endif
|
||||
}
|
||||
|
||||
|
||||
static initialize @priority(101)
|
||||
{
|
||||
if (!toformat_functions.table.len)
|
||||
{
|
||||
toformat_functions.init(64);
|
||||
}
|
||||
if (!tostring_functions.table.len)
|
||||
{
|
||||
tostring_functions.init(64);
|
||||
}
|
||||
}
|
||||
|
||||
fn void! Formatter.out(Formatter* this, char c) @private
|
||||
{
|
||||
this.out_fn(c, this.data)!;
|
||||
@@ -144,7 +110,7 @@ fn void! Formatter.out(Formatter* this, char c) @private
|
||||
|
||||
macro bool! Formatter.print_with_function(Formatter* this, any arg)
|
||||
{
|
||||
if (try to_format = toformat_functions.get(arg.type))
|
||||
if (&arg.to_format)
|
||||
{
|
||||
PrintFlags old = this.flags;
|
||||
uint old_width = this.width;
|
||||
@@ -155,10 +121,10 @@ macro bool! Formatter.print_with_function(Formatter* this, any arg)
|
||||
this.width = old_width;
|
||||
this.prec = old_prec;
|
||||
}
|
||||
to_format(arg.ptr, this)!;
|
||||
arg.to_format(this)!;
|
||||
return true;
|
||||
}
|
||||
if (try to_string = tostring_functions.get(arg.type))
|
||||
}
|
||||
if (&arg.to_string)
|
||||
{
|
||||
PrintFlags old = this.flags;
|
||||
uint old_width = this.width;
|
||||
@@ -171,7 +137,7 @@ macro bool! Formatter.print_with_function(Formatter* this, any arg)
|
||||
}
|
||||
@pool()
|
||||
{
|
||||
this.out_substr(to_string(arg.ptr, mem::temp()))!;
|
||||
this.out_substr(arg.to_string(mem::temp()))!;
|
||||
return true;
|
||||
};
|
||||
}
|
||||
@@ -277,21 +243,8 @@ fn void! Formatter.out_str(Formatter* this, any arg) @private
|
||||
}
|
||||
this.out(']')!;
|
||||
case BOOL:
|
||||
if (*(bool*)arg.ptr)
|
||||
{
|
||||
return this.out_substr("true");
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.out_substr("false");
|
||||
}
|
||||
return this.out_substr(*(bool*)arg.ptr ? "true" : "false");
|
||||
default:
|
||||
switch (arg)
|
||||
{
|
||||
case Object:
|
||||
arg.to_format(this)!;
|
||||
return;
|
||||
}
|
||||
if (this.print_with_function(arg)!) return;
|
||||
return this.out_substr("Invalid type");
|
||||
}
|
||||
@@ -472,8 +425,3 @@ fn usz! Formatter.vprintf(Formatter* this, String format, any[] anys)
|
||||
return this.idx;
|
||||
}
|
||||
|
||||
def StringFunctionMap @private = HashMap<typeid, ToStringFunction>;
|
||||
def FormatterFunctionMap @private = HashMap<typeid, ToFormatFunction>;
|
||||
|
||||
FormatterFunctionMap toformat_functions @private;
|
||||
StringFunctionMap tostring_functions @private;
|
||||
|
||||
@@ -37,12 +37,8 @@ struct InetAddress
|
||||
}
|
||||
}
|
||||
|
||||
static initialize
|
||||
{
|
||||
io::formatter_register_type(InetAddress);
|
||||
}
|
||||
|
||||
fn void! InetAddress.to_format(InetAddress* addr, Formatter* formatter)
|
||||
fn void! InetAddress.to_format(InetAddress* addr, Formatter* formatter) @dynamic
|
||||
{
|
||||
if (addr.is_ipv6)
|
||||
{
|
||||
@@ -54,7 +50,7 @@ fn void! InetAddress.to_format(InetAddress* addr, Formatter* formatter)
|
||||
formatter.printf("%d.%d.%d.%d", addr.ipv4.a, addr.ipv4.b, addr.ipv4.c, addr.ipv4.d)!;
|
||||
}
|
||||
|
||||
fn String! InetAddress.to_string(InetAddress* addr, Allocator* using = mem::heap())
|
||||
fn String! InetAddress.to_string(InetAddress* addr, Allocator* using = mem::heap()) @dynamic
|
||||
{
|
||||
if (addr.is_ipv6)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ module std::thread::os;
|
||||
|
||||
$if thread::THREAD_MODEL == ThreadModel.WIN32:
|
||||
|
||||
typedef NativeThread = Win32_HANDLE;
|
||||
def NativeThread = Win32_HANDLE;
|
||||
|
||||
struct NativeMutex
|
||||
{
|
||||
|
||||
@@ -8,8 +8,8 @@ struct Darwin_mach_timebase_info
|
||||
uint denom;
|
||||
}
|
||||
|
||||
typedef Darwin_mach_timebase_info_t = Darwin_mach_timebase_info;
|
||||
typedef Darwin_mach_timebase_info_data_t = Darwin_mach_timebase_info;
|
||||
def Darwin_mach_timebase_info_t = Darwin_mach_timebase_info;
|
||||
def Darwin_mach_timebase_info_data_t = Darwin_mach_timebase_info;
|
||||
|
||||
extern fn void mach_timebase_info(Darwin_mach_timebase_info_data_t* timebase);
|
||||
extern fn ulong mach_absolute_time();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
module std::time;
|
||||
|
||||
typedef Time @inline = distinct long;
|
||||
typedef TimeDuration @inline = distinct long;
|
||||
typedef Clock @inline = distinct ulong;
|
||||
typedef NanoDuration @inline = distinct long;
|
||||
def Time @inline = distinct long;
|
||||
def TimeDuration @inline = distinct long;
|
||||
def Clock @inline = distinct ulong;
|
||||
def NanoDuration @inline = distinct long;
|
||||
|
||||
const TimeDuration MICROSECONDS_PER_SECOND = 1_000_000;
|
||||
const TimeDuration MICROSECONDS_PER_MINUTE = MICROSECONDS_PER_SECOND * 60;
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
## 0.5.0 Change List
|
||||
|
||||
### Changes / improvements
|
||||
- `@dynamic` and `@interface` for dynamic dispatch.
|
||||
- `$if` now uses `$if <expr>:` syntax.
|
||||
- `$assert` now uses `$assert <expr> : <optional message>`
|
||||
- `$error` is syntax sugar for `$assert false : "Some message"`
|
||||
- `$include`, `$echo` no longer has mandatory `()` around the arguments.
|
||||
- Updated cpu arguments for x86
|
||||
- Dropped support for LLVM 13-14.
|
||||
- Updated grammar and lexer definition.
|
||||
- Removal of `$elif`.
|
||||
@@ -22,7 +24,7 @@
|
||||
- Allow getting the underlying type of anyfault.
|
||||
- De-duplicate string constants.
|
||||
- Change @extname => @extern.
|
||||
- `define Type = int` is replaced by `typedef Type = int`.
|
||||
- `define` is replaced by `def`.
|
||||
- LLVM "wrapper" library compilation is exception free.
|
||||
- `private` is replaced by attribute `@private`.
|
||||
- Addition of `@local` for file local visibility.
|
||||
|
||||
@@ -95,9 +95,9 @@ int comment_level = 0;
|
||||
"char" { count(); return(CHAR); }
|
||||
"const" { count(); return(CONST); }
|
||||
"continue" { count(); return(CONTINUE); }
|
||||
"def" { count(); return(DEF); }
|
||||
"default" { count(); return(DEFAULT); }
|
||||
"defer" { count(); return(DEFER); }
|
||||
"define" { count(); return(DEFINE); }
|
||||
"distinct" { count(); return(DISTINCT); }
|
||||
"do" { count(); return(DO); }
|
||||
"double" { count(); return(DOUBLE); }
|
||||
@@ -137,7 +137,6 @@ int comment_level = 0;
|
||||
"tlocal" { count(); return(TLOCAL); }
|
||||
"true" { count(); return(TRUE); }
|
||||
"try" { count(); return(TRY); }
|
||||
"typedef" { count(); return(TYPEDEF); }
|
||||
"typeid" { count(); return(TYPEID); }
|
||||
"uint" { count(); return(UINT); }
|
||||
"uint128" { count(); return(UINT128); }
|
||||
|
||||
@@ -17,7 +17,7 @@ void yyerror(char *s);
|
||||
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
|
||||
%token SUB_ASSIGN SHL_ASSIGN SHR_ASSIGN AND_ASSIGN
|
||||
%token XOR_ASSIGN OR_ASSIGN VAR NUL ELVIS NEXTCASE ANYFAULT
|
||||
%token TYPEDEF MODULE IMPORT DEFINE EXTERN
|
||||
%token MODULE IMPORT DEF EXTERN
|
||||
%token CHAR SHORT INT LONG FLOAT DOUBLE CONST VOID USZ ISZ UPTR IPTR ANY
|
||||
%token ICHAR USHORT UINT ULONG BOOL INT128 UINT128 FLOAT16 FLOAT128 BFLOAT16
|
||||
%token TYPEID BITSTRUCT STATIC BANGBANG AT_CONST_IDENT HASH_TYPE_IDENT
|
||||
@@ -1110,9 +1110,6 @@ typedef_type
|
||||
| type opt_generic_parameters
|
||||
;
|
||||
|
||||
typedef_declaration
|
||||
: TYPEDEF TYPE_IDENT opt_attributes '=' opt_distinct_inline typedef_type ';'
|
||||
;
|
||||
|
||||
|
||||
multi_declaration
|
||||
@@ -1166,8 +1163,9 @@ define_ident
|
||||
;
|
||||
|
||||
define_declaration
|
||||
: DEFINE define_ident ';'
|
||||
| DEFINE define_attribute ';'
|
||||
: DEF define_ident ';'
|
||||
| DEF define_attribute ';'
|
||||
| DEF TYPE_IDENT opt_attributes '=' opt_distinct_inline typedef_type ';'
|
||||
;
|
||||
|
||||
tl_ct_if
|
||||
@@ -1233,7 +1231,6 @@ top_level
|
||||
| fault_declaration
|
||||
| enum_declaration
|
||||
| macro_declaration
|
||||
| typedef_declaration
|
||||
| define_declaration
|
||||
| static_declaration
|
||||
| bitstruct_declaration
|
||||
|
||||
@@ -231,8 +231,8 @@ fn void hello() throws Errors
|
||||
return;
|
||||
}
|
||||
|
||||
typedef Foo* as Bar;
|
||||
typedef fn void(int, Foo*) as Zoo;
|
||||
def Foo* as Bar;
|
||||
def fn void(int, Foo*) as Zoo;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ const uint SDL_WINDOWPOS_UNDEFINED = UndefinedDisplay(x);
|
||||
#define SDL_WINDOWPOS_ISCENTERED(X) \
|
||||
(((X)&0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK)
|
||||
|
||||
typedef enum
|
||||
def enum
|
||||
{
|
||||
SDL_ORIENTATION_UNKNOWN, /**< The display orientation can't be determined */
|
||||
SDL_ORIENTATION_LANDSCAPE, /**< The display is in landscape mode, with the right side up, relative to portrait mode */
|
||||
@@ -115,7 +115,7 @@ typedef enum
|
||||
/**
|
||||
* \brief An opaque handle to an OpenGL context.
|
||||
*/
|
||||
typedef void *SDL_GLContext;
|
||||
def void *SDL_GLContext;
|
||||
|
||||
|
||||
enum GLAttr
|
||||
@@ -149,14 +149,14 @@ enum GLAttr
|
||||
GL_CONTEXT_NO_ERROR
|
||||
}
|
||||
|
||||
typedef enum
|
||||
def enum
|
||||
{
|
||||
SDL_GL_CONTEXT_PROFILE_CORE = 0x0001,
|
||||
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002,
|
||||
SDL_GL_CONTEXT_PROFILE_ES = 0x0004 /**< GLX_CONTEXT_ES2_PROFILE_BIT_EXT */
|
||||
} SDL_GLprofile;
|
||||
|
||||
typedef enum
|
||||
def enum
|
||||
{
|
||||
SDL_GL_CONTEXT_DEBUG_FLAG = 0x0001,
|
||||
SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002,
|
||||
@@ -164,13 +164,13 @@ typedef enum
|
||||
SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008
|
||||
} SDL_GLcontextFlag;
|
||||
|
||||
typedef enum
|
||||
def enum
|
||||
{
|
||||
SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE = 0x0000,
|
||||
SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH = 0x0001
|
||||
} SDL_GLcontextReleaseFlag;
|
||||
|
||||
typedef enum
|
||||
def enum
|
||||
{
|
||||
SDL_GL_CONTEXT_RESET_NO_NOTIFICATION = 0x0000,
|
||||
SDL_GL_CONTEXT_RESET_LOSE_CONTEXT = 0x0001
|
||||
@@ -810,7 +810,7 @@ extern DECLSPEC int SDLCALL SDL_GetWindowGammaRamp(SDL_Window * window,
|
||||
*
|
||||
* \sa SDL_HitTest
|
||||
*/
|
||||
typedef enum
|
||||
def enum
|
||||
{
|
||||
SDL_HITTEST_NORMAL, /**< Region is normal. No special properties. */
|
||||
SDL_HITTEST_DRAGGABLE, /**< Region can drag entire window. */
|
||||
@@ -829,7 +829,7 @@ typedef enum
|
||||
*
|
||||
* \sa SDL_SetWindowHitTest
|
||||
*/
|
||||
typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win,
|
||||
def SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win,
|
||||
const SDL_Point *area,
|
||||
void *data);
|
||||
|
||||
|
||||
@@ -130,7 +130,8 @@ static void usage(void)
|
||||
OUTPUT(" --forcelinker - Force built in linker usage when doing non-cross linking.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --reloc=<option> - Relocation model: none, pic, PIC, pie, PIE.");
|
||||
OUTPUT(" --x86vec=<option> - Set max level of vector instructions: none, native, mmx, sse, avx, avx512.");
|
||||
OUTPUT(" --x86cpu=<option> - Set general level of x64 cpu: baseline, ssse3, sse4, avx1, avx2-v1, avx2-v2 (Skylake/Zen1+), avx512 (Icelake/Zen4+), native.");
|
||||
OUTPUT(" --x86vec=<option> - Set max type of vector use: none, mmx, sse, avx, avx512, native.");
|
||||
OUTPUT(" --riscvfloat=<option> - Set type of RISC-V float support: none, float, double");
|
||||
OUTPUT(" --memory-env=<option> - Set the memory environment: normal, small, tiny, none.");
|
||||
OUTPUT(" --strip-unused - Strip unused code and globals from the output (experimental)");
|
||||
@@ -158,7 +159,11 @@ static void usage(void)
|
||||
OUTPUT(" --wincrt=<option> - Windows CRT linking: none, static, dynamic (default).");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --macossdk <dir> - Set the directory for the MacOS SDK for cross compilation.");
|
||||
|
||||
OUTPUT(" --macos-min-version <ver> - Set the minimum MacOS version to compile for.");
|
||||
OUTPUT(" --macos-sdk-version <ver> - Set the MacOS SDK compiled for.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --linux-crt <dir> - Set the directory to use for finding crt1.o and related files.");
|
||||
OUTPUT(" --linux-crtbegin <dir> - Set the directory to use for finding crtbegin.o and related files.");
|
||||
}
|
||||
|
||||
|
||||
@@ -551,7 +556,12 @@ static void parse_option(BuildOptions *options)
|
||||
}
|
||||
if ((argopt = match_argopt("x86vec")))
|
||||
{
|
||||
options->x86_vector_capability = (X86VectorCapability)parse_multi_option(argopt, 6, vector_capability);
|
||||
options->x86_vector_capability = (X86VectorCapability)parse_multi_option(argopt, 6, x86_vector_capability);
|
||||
return;
|
||||
}
|
||||
if ((argopt = match_argopt("x86cpu")))
|
||||
{
|
||||
options->x86_cpu_set = (X86CpuSet)parse_multi_option(argopt, 8, x86_cpu_set);
|
||||
return;
|
||||
}
|
||||
if ((argopt = match_argopt("riscvfloat")))
|
||||
@@ -801,6 +811,18 @@ static void parse_option(BuildOptions *options)
|
||||
options->path = check_dir(next_arg());
|
||||
return;
|
||||
}
|
||||
if (match_longopt("linux-crt"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --linux-crt needs a directory.");
|
||||
options->linuxpaths.crt = check_dir(next_arg());
|
||||
return;
|
||||
}
|
||||
if (match_longopt("linux-crtbegin"))
|
||||
{
|
||||
if (at_end() || next_is_opt()) error_exit("error: --linux-crtbegin needs a directory.");
|
||||
options->linuxpaths.crtbegin = check_dir(next_arg());
|
||||
return;
|
||||
}
|
||||
if (match_longopt("safe"))
|
||||
{
|
||||
options->safe_mode = 1;
|
||||
@@ -858,6 +880,7 @@ BuildOptions parse_arguments(int argc, const char *argv[])
|
||||
.reloc_model = RELOC_DEFAULT,
|
||||
.backend = BACKEND_LLVM,
|
||||
.x86_vector_capability = X86VECTOR_DEFAULT,
|
||||
.x86_cpu_set = X86CPU_DEFAULT,
|
||||
.riscv_float_capability = RISCVFLOAT_DEFAULT,
|
||||
.memory_environment = MEMORY_ENV_NOT_SET,
|
||||
.win.crt_linking = WIN_CRT_DEFAULT,
|
||||
|
||||
@@ -141,6 +141,18 @@ typedef enum
|
||||
X86VECTOR_NATIVE = 5,
|
||||
} X86VectorCapability;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
X86CPU_DEFAULT = -1,
|
||||
X86CPU_BASELINE = 0,
|
||||
X86CPU_SSSE3 = 1,
|
||||
X86CPU_SSE4 = 2,
|
||||
X86CPU_AVX1 = 3,
|
||||
X86CPU_AVX2_V1 = 4,
|
||||
X86CPU_AVX2_V2 = 5,
|
||||
X86CPU_AVX512 = 6,
|
||||
X86CPU_NATIVE = 7,
|
||||
} X86CpuSet;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -151,7 +163,7 @@ typedef enum
|
||||
} RiscvFloatCapability;
|
||||
|
||||
|
||||
static const char *vector_capability[6] = {
|
||||
static const char *x86_vector_capability[6] = {
|
||||
[X86VECTOR_NONE] = "none",
|
||||
[X86VECTOR_MMX] = "mmx",
|
||||
[X86VECTOR_SSE] = "sse",
|
||||
@@ -160,6 +172,17 @@ static const char *vector_capability[6] = {
|
||||
[X86VECTOR_NATIVE] = "native"
|
||||
};
|
||||
|
||||
static const char *x86_cpu_set[8] = {
|
||||
[X86CPU_BASELINE] = "baseline",
|
||||
[X86CPU_SSSE3] = "ssse3",
|
||||
[X86CPU_SSE4] = "sse4",
|
||||
[X86CPU_AVX1] = "avx1",
|
||||
[X86CPU_AVX2_V1] = "avx2-v1",
|
||||
[X86CPU_AVX2_V2] = "avx2-v2",
|
||||
[X86CPU_AVX512] = "avx512",
|
||||
[X86CPU_NATIVE] = "native"
|
||||
};
|
||||
|
||||
static const char *riscv_capability[3] = {
|
||||
[RISCVFLOAT_NONE] = "none",
|
||||
[RISCVFLOAT_FLOAT] = "float",
|
||||
@@ -274,6 +297,10 @@ typedef struct BuildOptions_
|
||||
const char *min_version;
|
||||
const char *sdk_version;
|
||||
} macos;
|
||||
struct {
|
||||
const char *crt;
|
||||
const char *crtbegin;
|
||||
} linuxpaths;
|
||||
int build_threads;
|
||||
const char** libraries_to_fetch;
|
||||
const char** files;
|
||||
@@ -310,6 +337,7 @@ typedef struct BuildOptions_
|
||||
const char *obj_out;
|
||||
RelocModel reloc_model;
|
||||
X86VectorCapability x86_vector_capability;
|
||||
X86CpuSet x86_cpu_set;
|
||||
RiscvFloatCapability riscv_float_capability;
|
||||
MemoryEnvironment memory_environment;
|
||||
bool strip_unused;
|
||||
@@ -354,6 +382,7 @@ typedef struct
|
||||
LibraryTarget **targets;
|
||||
} Library;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TargetType type;
|
||||
@@ -417,6 +446,7 @@ typedef struct
|
||||
RiscvFloatCapability riscv_float_capability : 4;
|
||||
bool trap_on_wrap : 1;
|
||||
bool safe_mode : 1;
|
||||
X86CpuSet x86_cpu_set;
|
||||
} feature;
|
||||
struct
|
||||
{
|
||||
@@ -430,6 +460,11 @@ typedef struct
|
||||
WinCrtLinking crt_linking;
|
||||
bool use_win_subsystem;
|
||||
} win;
|
||||
struct
|
||||
{
|
||||
const char *crt;
|
||||
const char *crtbegin;
|
||||
} linuxpaths;
|
||||
} BuildTarget;
|
||||
|
||||
|
||||
|
||||
@@ -243,10 +243,16 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
|
||||
if (options->macos.min_version) target->macos.min_version = options->macos.min_version;
|
||||
if (options->macos.sdk_version) target->macos.sdk_version = options->macos.sdk_version;
|
||||
if (options->win.crt_linking != WIN_CRT_DEFAULT) target->win.crt_linking = options->win.crt_linking;
|
||||
if (options->linuxpaths.crt) target->linuxpaths.crt = options->linuxpaths.crt;
|
||||
if (options->linuxpaths.crtbegin) target->linuxpaths.crtbegin = options->linuxpaths.crtbegin;
|
||||
if (options->x86_vector_capability != X86VECTOR_DEFAULT)
|
||||
{
|
||||
target->feature.x86_vector_capability = options->x86_vector_capability;
|
||||
}
|
||||
if (options->x86_cpu_set != X86CPU_DEFAULT)
|
||||
{
|
||||
target->feature.x86_cpu_set = options->x86_cpu_set;
|
||||
}
|
||||
if (options->riscv_float_capability != RISCVFLOAT_DEFAULT)
|
||||
{
|
||||
target->feature.riscv_float_capability = options->riscv_float_capability;
|
||||
@@ -322,6 +328,7 @@ void init_default_build_target(BuildTarget *target, BuildOptions *options)
|
||||
.arch_os_target = ARCH_OS_TARGET_DEFAULT,
|
||||
.reloc_model = RELOC_DEFAULT,
|
||||
.feature.x86_vector_capability = X86VECTOR_DEFAULT,
|
||||
.feature.x86_cpu_set = X86CPU_DEFAULT,
|
||||
.feature.riscv_float_capability = RISCVFLOAT_DEFAULT,
|
||||
.win.crt_linking = WIN_CRT_DEFAULT,
|
||||
.feature.safe_mode = true,
|
||||
|
||||
@@ -351,9 +351,13 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
|
||||
if (wincrt > -1) target->win.crt_linking = (WinCrtLinking)wincrt;
|
||||
|
||||
// x86vec
|
||||
int x86vec = get_valid_string_setting(json, "x86vec", type, vector_capability, 0, 6, "none, native, mmx, sse, avx or avx512");
|
||||
int x86vec = get_valid_string_setting(json, "x86vec", type, x86_vector_capability, 0, 6, "none, native, mmx, sse, avx or avx512");
|
||||
if (x86vec > -1) target->feature.x86_vector_capability = x86vec;
|
||||
|
||||
// x86vec
|
||||
int x86cpu = get_valid_string_setting(json, "x86cpu", type, x86_cpu_set, 0, 8, "baseline, ssse3, sse4, avx1, avx2-v1, avx2-v2, avx512 or native");
|
||||
if (x86cpu > -1) target->feature.x86_cpu_set = x86cpu;
|
||||
|
||||
// riscvfloat
|
||||
int riscv_float = get_valid_string_setting(json, "riscvfloat", type, riscv_capability, 0, 3, "none, float or double");
|
||||
if (riscv_float > -1) target->feature.riscv_float_capability = riscv_float;
|
||||
@@ -370,6 +374,12 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
|
||||
// macos-sdk-version
|
||||
target->macos.sdk_version = get_valid_string(json, "macos-sdk-version", type, false);
|
||||
|
||||
// Linux crt
|
||||
target->linuxpaths.crt = get_valid_string(json, "linux-crt", type, false);
|
||||
|
||||
// Linux crtbegin
|
||||
target->linuxpaths.crtbegin = get_valid_string(json, "linux-crtbegin", type, false);
|
||||
|
||||
// version
|
||||
const char *version = get_valid_string(json, "version", type, false);
|
||||
if (version) target->version = version;
|
||||
@@ -450,6 +460,7 @@ static void project_add_targets(Project *project, JSONObject *project_data)
|
||||
.feature.soft_float = SOFT_FLOAT_DEFAULT,
|
||||
.feature.trap_on_wrap = false,
|
||||
.feature.x86_vector_capability = X86VECTOR_DEFAULT,
|
||||
.feature.x86_cpu_set = X86CPU_DEFAULT,
|
||||
.feature.safe_mode = true,
|
||||
.win.crt_linking = WIN_CRT_DEFAULT,
|
||||
};
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
enum IntrospectIndex
|
||||
{
|
||||
INTROSPECT_INDEX_KIND = 0,
|
||||
INTROSPECT_INDEX_SIZEOF = 1,
|
||||
INTROSPECT_INDEX_INNER = 2,
|
||||
INTROSPECT_INDEX_LEN = 3,
|
||||
INTROSPECT_INDEX_ADDITIONAL = 4,
|
||||
INTROSPECT_INDEX_DTABLE = 1,
|
||||
INTROSPECT_INDEX_SIZEOF = 2,
|
||||
INTROSPECT_INDEX_INNER = 3,
|
||||
INTROSPECT_INDEX_LEN = 4,
|
||||
INTROSPECT_INDEX_ADDITIONAL = 5,
|
||||
INTROSPECT_INDEX_TOTAL,
|
||||
};
|
||||
|
||||
|
||||
@@ -432,8 +432,7 @@ void compiler_compile(void)
|
||||
}
|
||||
else if (task_count > 1)
|
||||
{
|
||||
TaskQueueRef queue = taskqueue_create(active_target.build_threads > task_count ? task_count : active_target.build_threads, tasks);
|
||||
taskqueue_wait_for_completion(queue);
|
||||
taskqueue_run(active_target.build_threads > task_count ? task_count : active_target.build_threads, tasks);
|
||||
}
|
||||
|
||||
if (active_target.print_output)
|
||||
|
||||
@@ -558,8 +558,10 @@ typedef struct
|
||||
bool attr_naked : 1;
|
||||
bool attr_test : 1;
|
||||
bool attr_winmain : 1;
|
||||
bool has_faults : 1;
|
||||
Decl** generated_lambda;
|
||||
bool attr_dynamic : 1;
|
||||
bool attr_interface : 1;
|
||||
DeclId any_prototype;
|
||||
Decl **generated_lambda;
|
||||
};
|
||||
struct
|
||||
{
|
||||
@@ -650,7 +652,6 @@ typedef struct
|
||||
} InitializerDecl;
|
||||
|
||||
|
||||
|
||||
typedef struct Decl_
|
||||
{
|
||||
const char *name;
|
||||
@@ -793,6 +794,7 @@ typedef struct
|
||||
bool attr_pure : 1;
|
||||
bool result_unused : 1;
|
||||
bool no_return : 1;
|
||||
bool is_dynamic_dispatch : 1;
|
||||
AstId body;
|
||||
union
|
||||
{
|
||||
|
||||
@@ -762,10 +762,12 @@ typedef enum
|
||||
ATTRIBUTE_BUILTIN,
|
||||
ATTRIBUTE_CDECL,
|
||||
ATTRIBUTE_DEPRECATED,
|
||||
ATTRIBUTE_DYNAMIC,
|
||||
ATTRIBUTE_EXPORT,
|
||||
ATTRIBUTE_EXTERN,
|
||||
ATTRIBUTE_EXTNAME,
|
||||
ATTRIBUTE_INLINE,
|
||||
ATTRIBUTE_INTERFACE,
|
||||
ATTRIBUTE_LITTLEENDIAN,
|
||||
ATTRIBUTE_LOCAL,
|
||||
ATTRIBUTE_MAYDISCARD,
|
||||
|
||||
@@ -286,6 +286,11 @@ static void linker_setup_macos(const char ***args_ref, LinkerType linker_type)
|
||||
}
|
||||
add_arg("-arch");
|
||||
add_arg(arch_to_linker_arch(platform_target.arch));
|
||||
if (active_target.strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
|
||||
{
|
||||
add_arg("-no_exported_symbols");
|
||||
add_arg("-dead_strip");
|
||||
}
|
||||
|
||||
// Skip if no libc.
|
||||
if (active_target.no_libc) return;
|
||||
@@ -335,6 +340,7 @@ static const char *find_freebsd_crt(void)
|
||||
|
||||
static const char *find_linux_crt(void)
|
||||
{
|
||||
if (active_target.linuxpaths.crt) return active_target.linuxpaths.crt;
|
||||
#if PLATFORM_POSIX
|
||||
glob_t globbuf;
|
||||
if (!glob("/usr/lib/*/crt1.o", 0, NULL, &globbuf) && globbuf.gl_pathc)
|
||||
@@ -357,6 +363,7 @@ static const char *find_linux_crt(void)
|
||||
|
||||
static const char *find_linux_crt_begin(void)
|
||||
{
|
||||
if (active_target.linuxpaths.crtbegin) return active_target.linuxpaths.crtbegin;
|
||||
#if PLATFORM_POSIX
|
||||
glob_t globbuf;
|
||||
if (!glob("/usr/lib/gcc/*/*/crtbegin.o", 0, NULL, &globbuf) && globbuf.gl_pathc)
|
||||
@@ -379,13 +386,23 @@ static const char *find_linux_crt_begin(void)
|
||||
|
||||
static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
|
||||
{
|
||||
if (linker_type == LINKER_CC) return;
|
||||
if (linker_type == LINKER_CC)
|
||||
{
|
||||
add_arg("-pthread");
|
||||
return;
|
||||
}
|
||||
if (is_no_pie(platform_target.reloc_model)) add_arg("-no-pie");
|
||||
if (is_pie(platform_target.reloc_model)) add_arg("-pie");
|
||||
if (platform_target.arch == ARCH_TYPE_X86_64) add_arg("--eh-frame-hdr");
|
||||
if (active_target.no_libc) return;
|
||||
const char *crt_begin_dir = find_linux_crt_begin();
|
||||
const char *crt_dir = find_linux_crt();
|
||||
|
||||
if (active_target.strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
|
||||
{
|
||||
add_arg("-dead_strip");
|
||||
}
|
||||
|
||||
if (!crt_begin_dir || !crt_dir)
|
||||
{
|
||||
error_exit("Failed to find the C runtime at link time.");
|
||||
@@ -408,9 +425,9 @@ static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
|
||||
add_arg2(crt_dir, "crtn.o");
|
||||
add_arg2("-L", crt_dir);
|
||||
add_arg("--dynamic-linker=/lib64/ld-linux-x86-64.so.2");
|
||||
add_arg("-lc");
|
||||
add_arg("-lm");
|
||||
add_arg("-lpthread");
|
||||
add_arg("-lc");
|
||||
add_arg("-L/usr/lib/");
|
||||
add_arg("-L/lib/");
|
||||
add_arg("-m");
|
||||
@@ -431,6 +448,11 @@ static void linker_setup_freebsd(const char ***args_ref, LinkerType linker_type)
|
||||
{
|
||||
error_exit("Failed to find the C runtime at link time.");
|
||||
}
|
||||
if (active_target.strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
|
||||
{
|
||||
add_arg("-dead_strip");
|
||||
}
|
||||
|
||||
if (is_pie_pic(platform_target.reloc_model))
|
||||
{
|
||||
add_arg("-pie");
|
||||
|
||||
@@ -724,6 +724,7 @@ static void llvm_codegen_setup()
|
||||
attribute_id.uwtable = lookup_attribute("uwtable");
|
||||
attribute_id.writeonly = lookup_attribute("writeonly");
|
||||
attribute_id.zext = lookup_attribute("zeroext");
|
||||
attribute_id.target_features = lookup_attribute("target-features");
|
||||
intrinsics_setup = true;
|
||||
}
|
||||
|
||||
@@ -755,14 +756,11 @@ void llvm_value_set_int(GenContext *c, BEValue *value, Type *type, uint64_t i)
|
||||
llvm_value_set(value, llvm_const_int(c, type, i), type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool llvm_value_is_const(BEValue *value)
|
||||
{
|
||||
return LLVMIsConstant(value->value);
|
||||
}
|
||||
|
||||
|
||||
void llvm_value_set_decl(GenContext *c, BEValue *value, Decl *decl)
|
||||
{
|
||||
decl = decl_flatten(decl);
|
||||
@@ -775,11 +773,6 @@ void llvm_value_set_decl(GenContext *c, BEValue *value, Decl *decl)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LLVMBasicBlockRef llvm_basic_block_new(GenContext *c, const char *name)
|
||||
{
|
||||
return LLVMCreateBasicBlockInContext(c->context, name);
|
||||
@@ -1042,10 +1035,29 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl)
|
||||
}
|
||||
assert(decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST);
|
||||
llvm_add_global_decl(c, decl);
|
||||
if (decl->is_export && platform_target.os == OS_TYPE_WIN32)
|
||||
{
|
||||
LLVMSetDLLStorageClass(decl->backend_ref, LLVMDLLExportStorageClass);
|
||||
}
|
||||
return decl->backend_ref;
|
||||
case DECL_FUNC:
|
||||
if (decl->func_decl.attr_interface)
|
||||
{
|
||||
size_t name_len = strlen(decl->name);
|
||||
LLVMTypeRef char_array_type = LLVMArrayType(c->byte_type, name_len + 1);
|
||||
LLVMValueRef selector = llvm_add_global_raw(c, decl_get_extname(decl), char_array_type, 0);
|
||||
LLVMSetGlobalConstant(selector, 1);
|
||||
LLVMSetInitializer(selector, llvm_get_zstring(c, decl->name, name_len));
|
||||
LLVMSetLinkage(selector, LLVMLinkOnceODRLinkage);
|
||||
llvm_set_comdat(c, selector);
|
||||
return decl->backend_ref = selector;
|
||||
}
|
||||
backend_ref = decl->backend_ref = LLVMAddFunction(c->module, decl_get_extname(decl), llvm_get_type(c, decl->type));
|
||||
llvm_append_function_attributes(c, decl);
|
||||
if (decl->is_export && platform_target.os == OS_TYPE_WIN32 && decl->name != kw_main && decl->name != kw_mainstub)
|
||||
{
|
||||
LLVMSetDLLStorageClass(backend_ref, LLVMDLLExportStorageClass);
|
||||
}
|
||||
if (decl_is_local(decl))
|
||||
{
|
||||
assert(decl->unit->module == c->code_module);
|
||||
@@ -1301,6 +1313,7 @@ static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context
|
||||
llvm_emit_function_decl(gen_context, func);
|
||||
FOREACH_END();
|
||||
|
||||
|
||||
FOREACH_BEGIN(Decl *func, unit->lambdas)
|
||||
if (only_used && !func->is_live) continue;
|
||||
has_elements = true;
|
||||
@@ -1367,6 +1380,8 @@ static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context
|
||||
|
||||
FOREACH_END();
|
||||
|
||||
llvm_emit_dynamic_functions(gen_context, gen_context->dynamic_functions);
|
||||
|
||||
llvm_emit_constructors_and_destructors(gen_context);
|
||||
|
||||
// EmitDeferred()
|
||||
|
||||
@@ -116,7 +116,7 @@ INLINE void llvm_emit_compare_exchange(GenContext *c, BEValue *result_value, Exp
|
||||
llvm_value_set(result_value, llvm_emit_extract_value(c, result, 0), type);
|
||||
}
|
||||
|
||||
INLINE void llvm_emit_unreachable(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
INLINE void llvm_emit_unreachable_stmt(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
{
|
||||
llvm_value_set(result_value, LLVMBuildUnreachable(c->builder), type_void);
|
||||
c->current_block = NULL;
|
||||
@@ -622,7 +622,7 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
switch (func)
|
||||
{
|
||||
case BUILTIN_UNREACHABLE:
|
||||
llvm_emit_unreachable(c, result_value, expr);
|
||||
llvm_emit_unreachable_stmt(c, result_value, expr);
|
||||
return;
|
||||
case BUILTIN_SWIZZLE:
|
||||
llvm_emit_swizzle(c, result_value, expr, false);
|
||||
|
||||
@@ -13,7 +13,7 @@ static inline LLVMValueRef llvm_emit_expr_to_rvalue(GenContext *c, Expr *expr);
|
||||
static inline LLVMValueRef llvm_emit_exprid_to_rvalue(GenContext *c, ExprId expr_id);
|
||||
static inline LLVMValueRef llvm_update_vector(GenContext *c, LLVMValueRef vector, LLVMValueRef value, MemberIndex index);
|
||||
static inline void llvm_emit_expression_list_expr(GenContext *c, BEValue *be_value, Expr *expr);
|
||||
|
||||
static LLVMValueRef llvm_emit_dynamic_search(GenContext *c, LLVMValueRef type_id_ptr, LLVMValueRef selector);
|
||||
static inline void llvm_emit_bitassign_array(GenContext *c, BEValue *result, BEValue parent, Decl *parent_decl, Decl *member);
|
||||
static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Expr *expr);
|
||||
static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr);
|
||||
@@ -35,6 +35,7 @@ static inline void llvm_emit_try_unwrap(GenContext *c, BEValue *value, Expr *exp
|
||||
static inline void llvm_emit_any(GenContext *c, BEValue *value, Expr *expr);
|
||||
static inline void llvm_emit_vector_initializer_list(GenContext *c, BEValue *value, Expr *expr);
|
||||
static inline void llvm_extract_bitvalue_from_array(GenContext *c, BEValue *be_value, Decl *member, Decl *parent_decl);
|
||||
static inline void llvm_emit_type_from_any(GenContext *c, BEValue *be_value);
|
||||
static void llvm_convert_vector_comparison(GenContext *c, BEValue *be_value, LLVMValueRef val, Type *vector_type,
|
||||
bool is_equals);
|
||||
static void llvm_emit_any_pointer(GenContext *c, BEValue *any, BEValue *pointer);
|
||||
@@ -2446,6 +2447,19 @@ static inline void llvm_emit_post_inc_dec(GenContext *c, BEValue *value, Expr *e
|
||||
llvm_emit_inc_dec_change(c, &addr, NULL, value, expr, diff);
|
||||
}
|
||||
|
||||
static void llvm_emit_dynamic_method_addr(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
llvm_emit_expr(c, value, expr->access_expr.parent);
|
||||
llvm_emit_type_from_any(c, value);
|
||||
llvm_value_rvalue(c, value);
|
||||
LLVMValueRef introspect = LLVMBuildIntToPtr(c->builder, value->value, c->ptr_type, "");
|
||||
|
||||
AlignSize align;
|
||||
Decl *dyn_fn = expr->access_expr.ref;
|
||||
LLVMValueRef func = llvm_emit_dynamic_search(c, introspect, llvm_get_ref(c, dyn_fn));
|
||||
|
||||
llvm_value_set(value, func, type_get_ptr(dyn_fn->type));
|
||||
}
|
||||
|
||||
static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
@@ -2553,8 +2567,14 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
}
|
||||
value->value = LLVMBuildNeg(c->builder, value->value, "neg");
|
||||
return;
|
||||
case UNARYOP_TADDR:
|
||||
case UNARYOP_ADDR:
|
||||
if (inner->expr_kind == EXPR_ACCESS && inner->access_expr.ref->decl_kind == DECL_FUNC)
|
||||
{
|
||||
llvm_emit_dynamic_method_addr(c, value, inner);
|
||||
return;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case UNARYOP_TADDR:
|
||||
llvm_emit_expr(c, value, inner);
|
||||
// Create an addr
|
||||
llvm_value_addr(c, value);
|
||||
@@ -4158,9 +4178,7 @@ static inline void llvm_emit_force_unwrap_expr(GenContext *c, BEValue *be_value,
|
||||
llvm_emit_any_from_value(c, &fault_arg, type_anyfault);
|
||||
vec_add(varargs, fault_arg);
|
||||
llvm_emit_panic(c, "Force unwrap failed!", loc, "Unexpected fault '%s' was unwrapped!", varargs);
|
||||
LLVMBuildUnreachable(c->builder);
|
||||
c->current_block = NULL;
|
||||
c->current_block_is_target = false;
|
||||
llvm_emit_unreachable(c);
|
||||
}
|
||||
llvm_emit_block(c, no_err_block);
|
||||
|
||||
@@ -4978,11 +4996,6 @@ static void llvm_emit_splatted_variadic_arg(GenContext *c, Expr *expr, Type *var
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void llvm_add_abi_call_attributes(GenContext *c, LLVMValueRef call_value, int count, ABIArgInfo **infos)
|
||||
{
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
@@ -5255,6 +5268,105 @@ void llvm_emit_raw_call(GenContext *c, BEValue *result_value, FunctionPrototype
|
||||
// 17i. The simple case here is where there is a normal return.
|
||||
// In this case be_value already holds the result
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_emit_dynamic_search(GenContext *c, LLVMValueRef type_id_ptr, LLVMValueRef selector)
|
||||
{
|
||||
LLVMTypeRef type = c->dyn_find_function_type;
|
||||
LLVMValueRef func = c->dyn_find_function;
|
||||
if (!c->dyn_find_function)
|
||||
{
|
||||
LLVMTypeRef types[2] = { c->ptr_type, c->ptr_type };
|
||||
type = c->dyn_find_function_type = LLVMFunctionType(c->ptr_type, types, 2, false);
|
||||
func = c->dyn_find_function = LLVMAddFunction(c->module, ".dyn_seach", c->dyn_find_function_type);
|
||||
|
||||
LLVMSetUnnamedAddress(func, LLVMGlobalUnnamedAddr);
|
||||
LLVMSetLinkage(func, LLVMWeakODRLinkage);
|
||||
|
||||
LLVMBuilderRef builder = LLVMCreateBuilderInContext(c->context);
|
||||
|
||||
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(c->context, func, "entry");
|
||||
LLVMPositionBuilderAtEnd(builder, entry);
|
||||
|
||||
AlignSize align;
|
||||
LLVMValueRef dtable_ptr_in = LLVMGetParam(func, 0);
|
||||
LLVMValueRef func_ref = LLVMGetParam(func, 1);
|
||||
|
||||
LLVMBasicBlockRef check = llvm_basic_block_new(c, "check");
|
||||
LLVMBasicBlockRef missing_function = llvm_basic_block_new(c, "missing_function");
|
||||
LLVMBasicBlockRef compare = llvm_basic_block_new(c, "compare");
|
||||
LLVMBasicBlockRef match = llvm_basic_block_new(c, "match");
|
||||
LLVMBasicBlockRef no_match = llvm_basic_block_new(c, "no_match");
|
||||
|
||||
LLVMBuildBr(builder, check);
|
||||
|
||||
// check: dtable_ptr = phi
|
||||
LLVMAppendExistingBasicBlock(func, check);
|
||||
LLVMPositionBuilderAtEnd(builder, check);
|
||||
LLVMValueRef dtable_ptr = LLVMBuildPhi(builder, c->ptr_type, "");
|
||||
|
||||
// dtable_ptr == null
|
||||
LLVMValueRef cmp = LLVMBuildICmp(builder, LLVMIntEQ, dtable_ptr, LLVMConstNull(c->ptr_type), "");
|
||||
|
||||
// if (cmp) goto missing_function else compare
|
||||
LLVMBuildCondBr(builder, cmp, missing_function, compare);
|
||||
|
||||
// missing_function: return null
|
||||
LLVMAppendExistingBasicBlock(func, missing_function);
|
||||
LLVMPositionBuilderAtEnd(builder, missing_function);
|
||||
LLVMBuildRet(builder, LLVMConstNull(c->ptr_type));
|
||||
|
||||
// function_type = dtable_ptr.function_type
|
||||
LLVMAppendExistingBasicBlock(func, compare);
|
||||
LLVMPositionBuilderAtEnd(builder, compare);
|
||||
|
||||
LLVMValueRef function_type = LLVMBuildStructGEP2(builder, c->dtable_type, dtable_ptr, 1, "");
|
||||
function_type = LLVMBuildLoad2(builder, c->ptr_type, function_type, "");
|
||||
LLVMSetAlignment(function_type, llvm_abi_alignment(c, c->ptr_type));
|
||||
|
||||
// function_type == func_ref
|
||||
cmp = LLVMBuildICmp(builder, LLVMIntEQ, function_type, func_ref, "");
|
||||
|
||||
// if (cmp) goto match else no_match
|
||||
LLVMBuildCondBr(builder, cmp, match, no_match);
|
||||
|
||||
// match: function_ptr = dtable_ptr.function_ptr
|
||||
LLVMAppendExistingBasicBlock(func, match);
|
||||
LLVMPositionBuilderAtEnd(builder, match);
|
||||
|
||||
// Offset = 0
|
||||
LLVMValueRef function_ptr = LLVMBuildLoad2(builder, c->ptr_type, dtable_ptr, "");
|
||||
LLVMSetAlignment(function_ptr, llvm_abi_alignment(c, c->ptr_type));
|
||||
LLVMBuildRet(builder, function_ptr);
|
||||
|
||||
// no match: next = dtable_ptr.next
|
||||
LLVMAppendExistingBasicBlock(func, no_match);
|
||||
LLVMPositionBuilderAtEnd(builder, no_match);
|
||||
LLVMValueRef next = LLVMBuildStructGEP2(builder, c->dtable_type, dtable_ptr, 2, "");
|
||||
next = LLVMBuildLoad2(builder, c->ptr_type, next, "");
|
||||
LLVMSetAlignment(next, llvm_abi_alignment(c, c->ptr_type));
|
||||
|
||||
// goto check
|
||||
LLVMBuildBr(builder, check);
|
||||
|
||||
LLVMBasicBlockRef block_in[2] = { entry, no_match };
|
||||
LLVMValueRef value_in[2] = { dtable_ptr_in, next };
|
||||
LLVMAddIncoming(dtable_ptr, value_in, block_in, 2);
|
||||
|
||||
LLVMDisposeBuilder(builder);
|
||||
}
|
||||
AlignSize align;
|
||||
LLVMValueRef dtable_ref = llvm_emit_struct_gep_raw(c,
|
||||
type_id_ptr,
|
||||
c->introspect_type,
|
||||
INTROSPECT_INDEX_DTABLE,
|
||||
llvm_abi_alignment(c, c->introspect_type),
|
||||
&align);
|
||||
LLVMValueRef dtable_ptr = llvm_load(c, c->ptr_type, dtable_ref, align, "");
|
||||
LLVMValueRef params[2] = { dtable_ptr, selector };
|
||||
LLVMValueRef call = LLVMBuildCall2(c->builder, type, func, params, 2, "");
|
||||
return call;
|
||||
}
|
||||
|
||||
static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr, BEValue *target)
|
||||
{
|
||||
if (expr->call_expr.is_builtin)
|
||||
@@ -5278,9 +5390,46 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
bool always_inline = false;
|
||||
|
||||
FunctionPrototype *prototype;
|
||||
// 1. Call through a pointer.
|
||||
if (!expr->call_expr.is_func_ref)
|
||||
Expr **args = expr->call_expr.arguments;
|
||||
|
||||
BEValue arg0_pointer = { .value = NULL };
|
||||
|
||||
// 1. Dynamic dispatch.
|
||||
if (expr->call_expr.is_dynamic_dispatch)
|
||||
{
|
||||
assert(vec_size(args));
|
||||
Expr *any_val = args[0];
|
||||
assert(any_val->expr_kind == EXPR_CAST);
|
||||
any_val = exprptr(any_val->cast_expr.expr)->unary_expr.expr;
|
||||
BEValue result;
|
||||
llvm_emit_expr(c, &result, any_val);
|
||||
BEValue typeid = result;
|
||||
llvm_emit_type_from_any(c, &typeid);
|
||||
llvm_value_rvalue(c, &typeid);
|
||||
llvm_emit_any_pointer(c, &result, &arg0_pointer);
|
||||
LLVMValueRef introspect = LLVMBuildIntToPtr(c->builder, typeid.value, c->ptr_type, "");
|
||||
|
||||
LLVMBasicBlockRef missing_function = llvm_basic_block_new(c, "missing_function");
|
||||
LLVMBasicBlockRef match = llvm_basic_block_new(c, "match");
|
||||
|
||||
AlignSize align;
|
||||
Decl *dyn_fn = declptr(expr->call_expr.func_ref);
|
||||
func = llvm_emit_dynamic_search(c, introspect, llvm_get_ref(c, dyn_fn));
|
||||
LLVMValueRef cmp = LLVMBuildICmp(c->builder, LLVMIntEQ, func, LLVMConstNull(c->ptr_type), "");
|
||||
llvm_emit_cond_br_raw(c, cmp, missing_function, match);
|
||||
llvm_emit_block(c, missing_function);
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_printf("No method '%s' could be found on target", dyn_fn->name);
|
||||
llvm_emit_panic(c, scratch_buffer_to_string(), expr->span, NULL, NULL);
|
||||
llvm_emit_unreachable(c);
|
||||
llvm_emit_block(c, match);
|
||||
|
||||
prototype = type_get_resolved_prototype(dyn_fn->type);
|
||||
func_type = llvm_get_type(c, dyn_fn->type);
|
||||
}
|
||||
else if (!expr->call_expr.is_func_ref)
|
||||
{
|
||||
// Call through a pointer.
|
||||
Expr *function = exprptr(expr->call_expr.function);
|
||||
|
||||
// 1a. Find the pointee type for the function pointer:
|
||||
@@ -5312,13 +5461,11 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
assert(func);
|
||||
func_type = llvm_get_type(c, function_decl->type);
|
||||
}
|
||||
|
||||
LLVMValueRef arg_values[512];
|
||||
unsigned arg_count = 0;
|
||||
Type **params = prototype->param_types;
|
||||
ABIArgInfo **abi_args = prototype->abi_args;
|
||||
unsigned param_count = vec_size(params);
|
||||
Expr **args = expr->call_expr.arguments;
|
||||
Expr **varargs = NULL;
|
||||
Expr *vararg_splat = NULL;
|
||||
if (expr->call_expr.splat_vararg)
|
||||
@@ -5428,7 +5575,14 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
|
||||
if (arg_expr)
|
||||
{
|
||||
llvm_emit_expr(c, &temp_value, arg_expr);
|
||||
if (i == 0 && arg0_pointer.value)
|
||||
{
|
||||
temp_value = arg0_pointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
llvm_emit_expr(c, &temp_value, arg_expr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5931,9 +6085,7 @@ static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *ex
|
||||
llvm_emit_block(c, next);
|
||||
}
|
||||
llvm_emit_panic(c, "Attempted to access 'inner' on non composite type", expr->span, NULL, NULL);
|
||||
c->current_block = NULL;
|
||||
c->current_block_is_target = false;
|
||||
LLVMBuildUnreachable(c->builder);
|
||||
llvm_emit_unreachable(c);
|
||||
llvm_emit_block(c, exit);
|
||||
}
|
||||
{
|
||||
@@ -5962,9 +6114,7 @@ static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *ex
|
||||
llvm_emit_block(c, next);
|
||||
}
|
||||
llvm_emit_panic(c, "Attempted to access 'names' on non enum/fault type.", expr->span, NULL, NULL);
|
||||
c->current_block = NULL;
|
||||
c->current_block_is_target = false;
|
||||
LLVMBuildUnreachable(c->builder);
|
||||
llvm_emit_unreachable(c);
|
||||
llvm_emit_block(c, exit);
|
||||
}
|
||||
{
|
||||
@@ -5997,9 +6147,7 @@ static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *ex
|
||||
llvm_emit_block(c, next);
|
||||
}
|
||||
llvm_emit_panic(c, "Attempted to access 'len' on non array type", expr->span, NULL, NULL);
|
||||
c->current_block = NULL;
|
||||
c->current_block_is_target = false;
|
||||
LLVMBuildUnreachable(c->builder);
|
||||
llvm_emit_unreachable(c);
|
||||
llvm_emit_block(c, exit);
|
||||
}
|
||||
{
|
||||
@@ -6101,6 +6249,25 @@ static inline void llvm_emit_any(GenContext *c, BEValue *value, Expr *expr)
|
||||
llvm_value_set(value, var, type_any);
|
||||
}
|
||||
|
||||
static inline void llvm_emit_type_from_any(GenContext *c, BEValue *be_value)
|
||||
{
|
||||
if (llvm_value_is_addr(be_value))
|
||||
{
|
||||
AlignSize alignment = 0;
|
||||
LLVMValueRef pointer_addr = llvm_emit_struct_gep_raw(c,
|
||||
be_value->value,
|
||||
llvm_get_type(c, type_any),
|
||||
1,
|
||||
be_value->alignment,
|
||||
&alignment);
|
||||
llvm_value_set_address(be_value, pointer_addr, type_typeid, alignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
llvm_value_set(be_value, llvm_emit_extract_value(c, be_value->value, 1), type_typeid);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
{
|
||||
Expr *inner = exprptr(expr->builtin_access_expr.inner);
|
||||
@@ -6204,21 +6371,7 @@ static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Ex
|
||||
return;
|
||||
}
|
||||
case ACCESS_TYPEOFANY:
|
||||
if (llvm_value_is_addr(be_value))
|
||||
{
|
||||
AlignSize alignment = 0;
|
||||
LLVMValueRef pointer_addr = llvm_emit_struct_gep_raw(c,
|
||||
be_value->value,
|
||||
llvm_get_type(c, type_any),
|
||||
1,
|
||||
be_value->alignment,
|
||||
&alignment);
|
||||
llvm_value_set_address(be_value, pointer_addr, type_typeid, alignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
llvm_value_set(be_value, llvm_emit_extract_value(c, be_value->value, 1), type_typeid);
|
||||
}
|
||||
llvm_emit_type_from_any(c, be_value);
|
||||
return;
|
||||
}
|
||||
UNREACHABLE
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "llvm_codegen_internal.h"
|
||||
|
||||
static LLVMValueRef llvm_add_xxlizer(GenContext *c, unsigned priority, bool is_finalizer);
|
||||
static void llvm_emit_param_attributes(GenContext *c, LLVMValueRef function, ABIArgInfo *info, bool is_return, int index, int last_index);
|
||||
static inline void llvm_emit_return_value(GenContext *context, LLVMValueRef value);
|
||||
static void llvm_expand_from_args(GenContext *c, Type *type, LLVMValueRef ref, unsigned *index, AlignSize alignment);
|
||||
@@ -404,6 +405,7 @@ void llvm_emit_return_implicit(GenContext *c)
|
||||
void llvm_emit_function_body(GenContext *c, Decl *decl)
|
||||
{
|
||||
DEBUG_LOG("Generating function %s.", decl->extname);
|
||||
if (decl->func_decl.attr_dynamic) vec_add(c->dynamic_functions, decl);
|
||||
assert(decl->backend_ref);
|
||||
llvm_emit_body(c,
|
||||
decl->backend_ref,
|
||||
@@ -568,6 +570,18 @@ void llvm_emit_body(GenContext *c, LLVMValueRef function, const char *module_nam
|
||||
c->function = prev_function;
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_add_xxlizer(GenContext *c, unsigned priority, bool is_initializer)
|
||||
{
|
||||
LLVMTypeRef initializer_type = LLVMFunctionType(LLVMVoidTypeInContext(c->context), NULL, 0, false);
|
||||
LLVMValueRef **array_ref = is_initializer ? &c->constructors : &c->destructors;
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_printf(is_initializer ? ".static_initialize.%u" : ".static_finalize.%u", vec_size(*array_ref));
|
||||
LLVMValueRef function = LLVMAddFunction(c->module, scratch_buffer_to_string(), initializer_type);
|
||||
LLVMSetLinkage(function, LLVMInternalLinkage);
|
||||
LLVMValueRef vals[3] = { llvm_const_int(c, type_int, priority), function, llvm_get_zero(c, type_voidptr) };
|
||||
vec_add(*array_ref, LLVMConstStructInContext(c->context, vals, 3, false));
|
||||
return function;
|
||||
}
|
||||
|
||||
void llvm_emit_xxlizer(GenContext *c, Decl *decl)
|
||||
{
|
||||
@@ -577,13 +591,8 @@ void llvm_emit_xxlizer(GenContext *c, Decl *decl)
|
||||
// Skip if it doesn't have a body.
|
||||
return;
|
||||
}
|
||||
LLVMTypeRef initializer_type = LLVMFunctionType(LLVMVoidTypeInContext(c->context), NULL, 0, false);
|
||||
bool is_finalizer = decl->decl_kind == DECL_FINALIZE;
|
||||
LLVMValueRef **array_ref = is_finalizer ? &c->destructors : &c->constructors;
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_printf(is_finalizer ? ".static_finalize.%u" : ".static_initialize.%u", vec_size(*array_ref));
|
||||
LLVMValueRef function = LLVMAddFunction(c->module, scratch_buffer_to_string(), initializer_type);
|
||||
LLVMSetLinkage(function, LLVMInternalLinkage);
|
||||
bool is_initializer = decl->decl_kind == DECL_INITIALIZE;
|
||||
LLVMValueRef function = llvm_add_xxlizer(c, decl->xxlizer.priority, is_initializer);
|
||||
if (llvm_use_debug(c))
|
||||
{
|
||||
uint32_t row = decl->span.row;
|
||||
@@ -607,16 +616,67 @@ void llvm_emit_xxlizer(GenContext *c, Decl *decl)
|
||||
llvm_emit_body(c,
|
||||
function,
|
||||
decl->unit->module->name->module,
|
||||
is_finalizer ? "[static finalizer]" : "[static initializer]",
|
||||
is_initializer ? "[static initializer]" : "[static finalizer]",
|
||||
decl->span.file_id,
|
||||
NULL,
|
||||
NULL,
|
||||
body);
|
||||
unsigned priority = decl->xxlizer.priority;
|
||||
LLVMValueRef vals[3] = { llvm_const_int(c, type_int, priority), function, llvm_get_zero(c, type_voidptr) };
|
||||
vec_add(*array_ref, LLVMConstStructInContext(c->context, vals, 3, false));
|
||||
}
|
||||
|
||||
static void llvm_generate_dyn_proto(GenContext *c, LLVMValueRef proto_ref)
|
||||
{
|
||||
LLVMBuilderRef builder = LLVMCreateBuilderInContext(c->context);
|
||||
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(c->context, proto_ref, "never");
|
||||
LLVMPositionBuilderAtEnd(builder, entry);
|
||||
LLVMBuildUnreachable(builder);
|
||||
LLVMDisposeBuilder(builder);
|
||||
}
|
||||
|
||||
void llvm_emit_dynamic_functions(GenContext *c, Decl **funcs)
|
||||
{
|
||||
if (!vec_size(funcs)) return;
|
||||
LLVMValueRef initializer = llvm_add_xxlizer(c, 1, true);
|
||||
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(c->context, initializer, "entry");
|
||||
LLVMBuilderRef builder = LLVMCreateBuilderInContext(c->context);
|
||||
LLVMPositionBuilderAtEnd(builder, entry);
|
||||
LLVMBasicBlockRef last_block = entry;
|
||||
FOREACH_BEGIN(Decl *decl, funcs)
|
||||
Type *type = typeinfotype(decl->func_decl.type_parent);
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append("$ct.dyn.");
|
||||
scratch_buffer_append(decl_get_extname(decl));
|
||||
LLVMValueRef global = llvm_add_global_raw(c, scratch_buffer_to_string(), c->dtable_type, 0);
|
||||
Decl *proto = declptr(decl->func_decl.any_prototype);
|
||||
LLVMValueRef proto_ref = llvm_get_ref(c, proto);
|
||||
LLVMValueRef vals[3] = { llvm_get_ref(c, decl), proto_ref, LLVMConstNull(c->ptr_type) };
|
||||
LLVMSetInitializer(global, LLVMConstNamedStruct(c->dtable_type, vals, 3));
|
||||
LLVMValueRef type_id_ptr = LLVMBuildIntToPtr(builder, llvm_get_typeid(c, type), c->ptr_type, "");
|
||||
LLVMValueRef dtable_ref = LLVMBuildStructGEP2(builder, c->introspect_type, type_id_ptr, INTROSPECT_INDEX_DTABLE, "");
|
||||
LLVMBasicBlockRef check = LLVMAppendBasicBlockInContext(c->context, initializer, "dtable_check");
|
||||
LLVMBuildBr(builder, check);
|
||||
LLVMPositionBuilderAtEnd(builder, check);
|
||||
LLVMValueRef phi = LLVMBuildPhi(builder, c->ptr_type, "dtable_ref");
|
||||
LLVMValueRef load_dtable = LLVMBuildLoad2(builder, c->ptr_type, phi, "dtable_ptr");
|
||||
LLVMValueRef is_not_null = LLVMBuildICmp(builder, LLVMIntEQ, load_dtable, LLVMConstNull(c->ptr_type), "");
|
||||
LLVMBasicBlockRef after_check = llvm_basic_block_new(c, "dtable_found");
|
||||
LLVMBasicBlockRef next = llvm_basic_block_new(c, "dtable_next");
|
||||
LLVMBuildCondBr(builder, is_not_null, after_check, next);
|
||||
LLVMAppendExistingBasicBlock(initializer, next);
|
||||
LLVMPositionBuilderAtEnd(builder, next);
|
||||
LLVMValueRef next_ptr = LLVMBuildStructGEP2(builder, c->dtable_type, load_dtable, 2, "next_dtable_ref");
|
||||
LLVMValueRef phi_in[2] = { dtable_ref, next_ptr };
|
||||
LLVMBasicBlockRef phi_in_block[2] = { last_block, next };
|
||||
LLVMAddIncoming(phi, phi_in, phi_in_block, 2);
|
||||
LLVMBuildBr(builder, check);
|
||||
LLVMAppendExistingBasicBlock(initializer, after_check);
|
||||
LLVMPositionBuilderAtEnd(builder, after_check);
|
||||
LLVMBuildStore(builder, global, phi);
|
||||
last_block = after_check;
|
||||
FOREACH_END();
|
||||
|
||||
LLVMBuildRet(builder, NULL);
|
||||
LLVMDisposeBuilder(builder);
|
||||
}
|
||||
void llvm_emit_function_decl(GenContext *c, Decl *decl)
|
||||
{
|
||||
assert(decl->decl_kind == DECL_FUNC);
|
||||
|
||||
@@ -102,6 +102,7 @@ typedef struct GenContext_
|
||||
LLVMTypeRef fault_type;
|
||||
LLVMTypeRef size_type;
|
||||
LLVMTypeRef typeid_type;
|
||||
LLVMTypeRef dtable_type;
|
||||
LLVMTypeRef char_ptr_type;
|
||||
LLVMTypeRef ptr_type;
|
||||
LLVMTypeRef chars_type;
|
||||
@@ -128,6 +129,9 @@ typedef struct GenContext_
|
||||
bool current_block_is_target : 1;
|
||||
LLVMTypeRef type_data_definitions[TYPE_KINDS];
|
||||
SourceSpan last_emitted_loc;
|
||||
Decl **dynamic_functions;
|
||||
LLVMValueRef dyn_find_function;
|
||||
LLVMTypeRef dyn_find_function_type;
|
||||
} GenContext;
|
||||
|
||||
// LLVM Intrinsics
|
||||
@@ -244,6 +248,7 @@ typedef struct
|
||||
unsigned uwtable;
|
||||
unsigned writeonly; // No writes on pointer
|
||||
unsigned zext; // zero extend
|
||||
unsigned target_features; // target-features for function compilation
|
||||
} LLVMAttributes;
|
||||
|
||||
extern LLVMAttributes attribute_id;
|
||||
@@ -462,6 +467,7 @@ void llvm_emit_panic_on_true(GenContext *c, LLVMValueRef value, const char *pani
|
||||
void llvm_emit_panic_if_true(GenContext *c, BEValue *value, const char *panic_name, SourceSpan loc, const char *fmt, BEValue *value_1,
|
||||
BEValue *value_2);
|
||||
void llvm_emit_panic(GenContext *c, const char *message, SourceSpan loc, const char *fmt, BEValue *args);
|
||||
void llvm_emit_unreachable(GenContext *c);
|
||||
|
||||
void llvm_emit_any_from_value(GenContext *c, BEValue *value, Type *type);
|
||||
void llvm_emit_subarray_len(GenContext *context, BEValue *subarray, BEValue *len);
|
||||
@@ -469,6 +475,7 @@ void llvm_emit_subarray_pointer(GenContext *context, BEValue *subarray, BEValue
|
||||
void llvm_emit_compound_stmt(GenContext *c, Ast *ast);
|
||||
LLVMValueRef llvm_emit_const_bitstruct(GenContext *c, ConstInitializer *initializer);
|
||||
void llvm_emit_function_body(GenContext *context, Decl *decl);
|
||||
void llvm_emit_dynamic_functions(GenContext *context, Decl **funcs);
|
||||
BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef optional);
|
||||
INLINE void llvm_emit_exprid(GenContext *c, BEValue *value, ExprId expr);
|
||||
INLINE void llvm_emit_statement_chain(GenContext *c, AstId current);
|
||||
|
||||
@@ -11,6 +11,7 @@ static inline LLVMTypeRef create_introspection_type(GenContext *c)
|
||||
LLVMTypeRef type = LLVMStructCreateNamed(c->context, ".introspect");
|
||||
LLVMTypeRef introspect_type[INTROSPECT_INDEX_TOTAL] = {
|
||||
[INTROSPECT_INDEX_KIND] = c->byte_type,
|
||||
[INTROSPECT_INDEX_DTABLE] = c->ptr_type,
|
||||
[INTROSPECT_INDEX_SIZEOF] = c->size_type,
|
||||
[INTROSPECT_INDEX_INNER] = c->typeid_type,
|
||||
[INTROSPECT_INDEX_LEN] = c->size_type,
|
||||
@@ -44,6 +45,7 @@ void gencontext_begin_module(GenContext *c)
|
||||
c->panicf = global_context.panicf;
|
||||
c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context);
|
||||
c->machine = llvm_target_machine_create();
|
||||
|
||||
c->target_data = LLVMCreateTargetDataLayout(c->machine);
|
||||
|
||||
LLVMSetModuleDataLayout(c->module, c->target_data);
|
||||
@@ -102,7 +104,7 @@ void gencontext_begin_module(GenContext *c)
|
||||
type->decl->backend_ref = NULL;
|
||||
break;
|
||||
case TYPE_FUNC:
|
||||
REMINDER("Clear func when it has reflection");
|
||||
//REMINDER("Clear func when it has reflection");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -113,6 +115,8 @@ void gencontext_begin_module(GenContext *c)
|
||||
c->ptr_type = LLVMPointerType(c->byte_type, 0);
|
||||
c->size_type = llvm_get_type(c, type_usz);
|
||||
c->typeid_type = llvm_get_type(c, type_typeid);
|
||||
LLVMTypeRef dtable_type[3] = { c->ptr_type, c->ptr_type, c->ptr_type };
|
||||
c->dtable_type = LLVMStructTypeInContext(c->context, dtable_type, 3, false);
|
||||
c->chars_type = llvm_get_type(c, type_chars);
|
||||
c->introspect_type = create_introspection_type(c);
|
||||
c->fault_type = create_fault_type(c);
|
||||
|
||||
@@ -470,10 +470,8 @@ void llvm_emit_for_stmt(GenContext *c, Ast *ast)
|
||||
SourceSpan loc = ast->span;
|
||||
|
||||
llvm_emit_panic(c, "Infinite loop found", loc, NULL, NULL);
|
||||
LLVMBuildUnreachable(c->builder);
|
||||
llvm_emit_unreachable(c);
|
||||
LLVMBasicBlockRef block = llvm_basic_block_new(c, "unreachable_block");
|
||||
c->current_block = NULL;
|
||||
c->current_block_is_target = false;
|
||||
llvm_emit_block(c, block);
|
||||
return;
|
||||
}
|
||||
@@ -1274,6 +1272,12 @@ LLVMValueRef llvm_emit_zstring_named(GenContext *c, const char *str, const char
|
||||
return string;
|
||||
}
|
||||
|
||||
void llvm_emit_unreachable(GenContext *c)
|
||||
{
|
||||
LLVMBuildUnreachable(c->builder);
|
||||
c->current_block = NULL;
|
||||
c->current_block_is_target = false;
|
||||
}
|
||||
|
||||
void llvm_emit_panic(GenContext *c, const char *message, SourceSpan loc, const char *fmt, BEValue *varargs)
|
||||
{
|
||||
|
||||
@@ -439,6 +439,7 @@ static inline LLVMValueRef llvm_generate_introspection_global(GenContext *c, LLV
|
||||
}
|
||||
LLVMValueRef values[INTROSPECT_INDEX_TOTAL] = {
|
||||
[INTROSPECT_INDEX_KIND] = LLVMConstInt(c->byte_type, introspect_type, false),
|
||||
[INTROSPECT_INDEX_DTABLE] = LLVMConstNull(c->ptr_type),
|
||||
[INTROSPECT_INDEX_SIZEOF] = LLVMConstInt(c->size_type, type_size(type), false),
|
||||
[INTROSPECT_INDEX_INNER] = inner ? llvm_get_typeid(c, inner) : llvm_get_zero(c, type_typeid),
|
||||
[INTROSPECT_INDEX_LEN] = LLVMConstInt(c->size_type,len, false),
|
||||
@@ -461,7 +462,7 @@ static inline LLVMValueRef llvm_generate_introspection_global(GenContext *c, LLV
|
||||
LLVMSetInitializer(global_name, strukt);
|
||||
}
|
||||
LLVMSetAlignment(global_name, llvm_abi_alignment(c, c->introspect_type));
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetGlobalConstant(global_name, 0);
|
||||
if (is_external)
|
||||
{
|
||||
LLVMSetLinkage(global_name, LLVMExternalLinkage);
|
||||
|
||||
@@ -1745,7 +1745,11 @@ static inline void decl_add_type(Decl *decl, TypeKind kind)
|
||||
*/
|
||||
static inline Decl *parse_typedef_declaration(ParseContext *c)
|
||||
{
|
||||
if (!try_consume(c, TOKEN_DEF)) advance_and_verify(c, TOKEN_TYPEDEF);
|
||||
if (!try_consume(c, TOKEN_DEF))
|
||||
{
|
||||
sema_warning_at(c->span, "The use of 'typedef' is deprecated, please use 'def'.");
|
||||
advance_and_verify(c, TOKEN_TYPEDEF);
|
||||
}
|
||||
|
||||
Decl *decl = decl_new(DECL_POISONED, symstr(c), c->span);
|
||||
DEBUG_LOG("Parse typedef %s", decl->name);
|
||||
@@ -1849,20 +1853,28 @@ static inline Decl *parse_typedef_declaration(ParseContext *c)
|
||||
static inline Decl *parse_define_ident(ParseContext *c)
|
||||
{
|
||||
// 1. Store the beginning of the "define".
|
||||
if (!try_consume(c, TOKEN_DEF)) advance_and_verify(c, TOKEN_DEFINE);
|
||||
if (!try_consume(c, TOKEN_DEF))
|
||||
{
|
||||
sema_warning_at(c->span, "The use of 'define' is deprecated, please use 'def'.");
|
||||
advance_and_verify(c, TOKEN_DEFINE);
|
||||
}
|
||||
|
||||
// 2. At this point we expect an ident or a const token.
|
||||
// since the Type is handled.
|
||||
TokenType alias_type = c->tok;
|
||||
if (alias_type != TOKEN_IDENT && alias_type != TOKEN_CONST_IDENT && alias_type != TOKEN_AT_IDENT)
|
||||
{
|
||||
if (alias_type == TOKEN_TYPE_IDENT)
|
||||
if (token_is_keyword_ident(alias_type) && alias_type != TOKEN_FN)
|
||||
{
|
||||
SEMA_ERROR_HERE("'%s' is a reserved keyword, try another name.", token_type_to_string(alias_type));
|
||||
}
|
||||
else if (alias_type == TOKEN_TYPE_IDENT)
|
||||
{
|
||||
SEMA_ERROR_HERE("A variable, constant or attribute name was expected here. If you want to define a new type, use 'typedef' instead.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SEMA_ERROR_HERE("A variable, constant or attribute name was expected here.");
|
||||
SEMA_ERROR_HERE("A type, variable, constant or attribute name was expected here.");
|
||||
}
|
||||
return poisoned_decl;
|
||||
}
|
||||
@@ -2306,10 +2318,9 @@ static inline Decl *parse_func_definition(ParseContext *c, AstId contracts, bool
|
||||
return func;
|
||||
}
|
||||
|
||||
if (tok_is(c, TOKEN_EOS))
|
||||
if (try_consume(c, TOKEN_EOS))
|
||||
{
|
||||
SEMA_ERROR_HERE("Expected a function body, if you want to declare an extern function use 'extern' or place it in an .c3i file.");
|
||||
return poisoned_decl;
|
||||
return func;
|
||||
}
|
||||
|
||||
if (tok_is(c, TOKEN_IMPLIES))
|
||||
|
||||
@@ -13,7 +13,7 @@ static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl);
|
||||
static inline bool sema_check_param_uniqueness_and_type(Decl **decls, Decl *current, unsigned current_index, unsigned count);
|
||||
|
||||
static inline bool sema_analyse_method(SemaContext *context, Decl *decl);
|
||||
static inline bool sema_is_valid_method_param(SemaContext *context, Decl *param, Type *parent_type);
|
||||
static inline bool sema_is_valid_method_param(SemaContext *context, Decl *param, Type *parent_type, bool is_dynamic, bool is_interface);
|
||||
static inline bool sema_analyse_macro_method(SemaContext *context, Decl *decl);
|
||||
static inline bool unit_add_base_extension_method(CompilationUnit *unit, Type *parent_type, Decl *method_like);
|
||||
static inline bool unit_add_method_like(CompilationUnit *unit, Type *parent_type, Decl *method_like);
|
||||
@@ -701,6 +701,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Check parameters
|
||||
for (unsigned i = 0; i < param_count; i++)
|
||||
{
|
||||
@@ -1417,13 +1418,15 @@ static inline bool sema_analyse_method(SemaContext *context, Decl *decl)
|
||||
if (!sema_resolve_type_info(context, parent_type)) return false;
|
||||
Type *type = parent_type->type->canonical;
|
||||
Decl **params = decl->func_decl.signature.params;
|
||||
if (!vec_size(params))
|
||||
bool is_dynamic = decl->func_decl.attr_dynamic;
|
||||
bool is_interface = decl->func_decl.attr_interface;
|
||||
if (is_interface && type != type_any) RETURN_SEMA_ERROR(decl, "Only 'any' methods may use '@interface'.");
|
||||
if (!sema_is_valid_method_param(context, params[0], type, is_dynamic, is_interface)) return false;
|
||||
if (is_dynamic)
|
||||
{
|
||||
SEMA_ERROR(decl, "A method must start with a parameter of type %s or %s.",
|
||||
type_quoted_error_string(parent_type->type), type_quoted_error_string(type_get_ptr(parent_type->type)));
|
||||
return false;
|
||||
if (is_interface) RETURN_SEMA_ERROR(decl, "An interface method cannot be '@dynamic'.");
|
||||
}
|
||||
if (!sema_is_valid_method_param(context, params[0], type)) return false;
|
||||
|
||||
return unit_add_method_like(context->unit, type, decl);
|
||||
}
|
||||
|
||||
@@ -1484,6 +1487,8 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
|
||||
[ATTRIBUTE_BUILTIN] = ATTR_MACRO | ATTR_FUNC,
|
||||
[ATTRIBUTE_CDECL] = ATTR_FUNC,
|
||||
[ATTRIBUTE_DEPRECATED] = USER_DEFINED_TYPES | ATTR_FUNC | ATTR_MACRO | ATTR_CONST | ATTR_GLOBAL | ATTR_MEMBER,
|
||||
[ATTRIBUTE_DYNAMIC] = ATTR_FUNC,
|
||||
[ATTRIBUTE_INTERFACE] = ATTR_FUNC,
|
||||
[ATTRIBUTE_EXPORT] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | EXPORTED_USER_DEFINED_TYPES,
|
||||
[ATTRIBUTE_NOSTRIP] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | EXPORTED_USER_DEFINED_TYPES,
|
||||
[ATTRIBUTE_EXTNAME] = (AttributeDomain)~(ATTR_CALL | ATTR_BITSTRUCT | ATTR_DEFINE | ATTR_MACRO | ATTR_XXLIZER),
|
||||
@@ -1579,6 +1584,12 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
|
||||
case ATTRIBUTE_TEST:
|
||||
decl->func_decl.attr_test = true;
|
||||
break;
|
||||
case ATTRIBUTE_INTERFACE:
|
||||
decl->func_decl.attr_interface = true;
|
||||
break;
|
||||
case ATTRIBUTE_DYNAMIC:
|
||||
decl->func_decl.attr_dynamic = true;
|
||||
break;
|
||||
case ATTRIBUTE_STDCALL:
|
||||
assert(decl->decl_kind == DECL_FUNC);
|
||||
if (platform_target.arch == ARCH_TYPE_ARM || platform_target.arch == ARCH_TYPE_ARMB)
|
||||
@@ -1828,12 +1839,8 @@ static bool sema_analyse_attributes_inner(SemaContext *context, Decl *decl, Attr
|
||||
|
||||
// Custom attributes.
|
||||
// First find it.
|
||||
Decl *attr_decl = sema_find_symbol(context, attr->name);
|
||||
if (!attr_decl || attr_decl->decl_kind != DECL_ATTRIBUTE)
|
||||
{
|
||||
SEMA_ERROR(attr, "The attribute '%s' could not be found.", attr->name);
|
||||
return false;
|
||||
}
|
||||
Decl *attr_decl = sema_resolve_symbol(context, attr->name, attr->path, attr->span);
|
||||
if (!attr_decl) return false;
|
||||
|
||||
// Detect direct cycles @Foo = @Bar @Bar = @Foo
|
||||
if (attr_decl == top)
|
||||
@@ -2377,6 +2384,16 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (decl->func_decl.attr_dynamic)
|
||||
{
|
||||
SEMA_ERROR(decl, "Only methods may be annotated '@dynamic'.");
|
||||
return decl_poison(decl);
|
||||
}
|
||||
if (decl->func_decl.attr_interface)
|
||||
{
|
||||
SEMA_ERROR(decl, "Only methods to 'any' may be annotated '@interface'.");
|
||||
return decl_poison(decl);
|
||||
}
|
||||
if (decl->name == kw_main)
|
||||
{
|
||||
if (is_test) SEMA_ERROR(decl, "Main functions may not be annotated @test.");
|
||||
@@ -2385,6 +2402,15 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl)
|
||||
decl_set_external_name(decl);
|
||||
}
|
||||
|
||||
bool is_any_interface = decl->func_decl.attr_interface && decl->func_decl.type_parent && typeinfotype(decl->func_decl.type_parent) == type_any;
|
||||
// Do we have fn void any.foo(void*) { ... }?
|
||||
if (decl->func_decl.body && is_any_interface) RETURN_SEMA_ERROR(decl, "Interface methods declarations may not have a body.");
|
||||
if (!decl->func_decl.body && !decl->is_extern && !decl->unit->is_interface_file && !is_any_interface)
|
||||
{
|
||||
SEMA_ERROR(decl, "Expected a function body, if you want to declare an extern function use 'extern' or place it in an .c3i file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pure = false;
|
||||
if (!sema_analyse_doc_header(decl->func_decl.docs, decl->func_decl.signature.params, NULL, &pure)) return decl_poison(decl);
|
||||
decl->func_decl.signature.attrs.is_pure = pure;
|
||||
@@ -2393,15 +2419,32 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_is_valid_method_param(SemaContext *context, Decl *param, Type *parent_type)
|
||||
static inline bool sema_is_valid_method_param(SemaContext *context, Decl *param, Type *parent_type, bool is_dynamic, bool is_interface)
|
||||
{
|
||||
assert(parent_type->canonical == parent_type && "Expected already the canonical version.");
|
||||
Type *param_type = param->type;
|
||||
|
||||
if (!param_type) goto ERROR;
|
||||
param_type = param_type->canonical;
|
||||
|
||||
if (is_interface)
|
||||
{
|
||||
if (param_type != type_voidptr) RETURN_SEMA_ERROR(param, "The first parameter of an interface must be of type 'void*'.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_dynamic)
|
||||
{
|
||||
if (param_type->type_kind != TYPE_POINTER || param_type->pointer != parent_type)
|
||||
{
|
||||
RETURN_SEMA_ERROR(param, "The fist parameter must be of type %s", type_quoted_error_string(type_get_ptr(parent_type)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1. Same type ok!
|
||||
if (param_type == parent_type) return true;
|
||||
|
||||
// 2. A pointer is ok!
|
||||
if (param_type->type_kind == TYPE_POINTER && param_type->pointer == parent_type) return true;
|
||||
ERROR:
|
||||
@@ -2433,7 +2476,7 @@ static bool sema_analyse_macro_method(SemaContext *context, Decl *decl)
|
||||
SEMA_ERROR(decl, "The first parameter to this method must be of type '%s'.", type_to_error_string(parent_type));
|
||||
return false;
|
||||
}
|
||||
if (!sema_is_valid_method_param(context, first_param, parent_type->canonical)) return false;
|
||||
if (!sema_is_valid_method_param(context, first_param, parent_type->canonical, false, false)) return false;
|
||||
|
||||
if (first_param->var.kind != VARDECL_PARAM_REF && first_param->var.kind != VARDECL_PARAM)
|
||||
{
|
||||
|
||||
@@ -1660,6 +1660,9 @@ static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr,
|
||||
}
|
||||
sema_display_deprecated_warning_on_use(context, decl, expr->span);
|
||||
|
||||
// Tag dynamic dispatch.
|
||||
if (struct_var && decl->func_decl.attr_interface) expr->call_expr.is_dynamic_dispatch = true;
|
||||
|
||||
return sema_call_analyse_func_invocation(context,
|
||||
decl->type,
|
||||
expr,
|
||||
@@ -5466,11 +5469,15 @@ static const char *sema_addr_check_may_take(Expr *inner)
|
||||
if (inner->unary_expr.operator == UNARYOP_DEREF) return NULL;
|
||||
break;
|
||||
case EXPR_ACCESS:
|
||||
if (inner->access_expr.ref->decl_kind == DECL_FUNC)
|
||||
{
|
||||
Decl *decl = inner->access_expr.ref;
|
||||
if (decl->decl_kind == DECL_FUNC)
|
||||
{
|
||||
if (decl->func_decl.attr_interface) return NULL;
|
||||
return "Taking the address of a method should be done through the type e.g. '&Foo.method' not through the value.";
|
||||
}
|
||||
return sema_addr_check_may_take(inner->access_expr.parent);
|
||||
}
|
||||
case EXPR_GROUP:
|
||||
return sema_addr_check_may_take(inner->inner_expr);
|
||||
case EXPR_SUBSCRIPT:
|
||||
|
||||
@@ -2916,6 +2916,19 @@ bool sema_analyse_contracts(SemaContext *context, AstId doc, AstId **asserts, So
|
||||
bool sema_analyse_function_body(SemaContext *context, Decl *func)
|
||||
{
|
||||
if (!decl_ok(func)) return false;
|
||||
if (func->func_decl.attr_dynamic)
|
||||
{
|
||||
Decl *ambiguous = NULL;
|
||||
Decl *private = NULL;
|
||||
Decl *any = sema_resolve_type_method(context->unit, type_any, func->name, &ambiguous, &private);
|
||||
if (!any)
|
||||
{
|
||||
SEMA_ERROR(func, "To define a '@dynamic' method, the prototype method 'any.%s(...)' must exist. Did you spell the method name right?",
|
||||
func->name);
|
||||
return false;
|
||||
}
|
||||
func->func_decl.any_prototype = declid(any);
|
||||
}
|
||||
Signature *signature = &func->func_decl.signature;
|
||||
FunctionPrototype *prototype = func->type->function.prototype;
|
||||
context->call_env = (CallEnv) {
|
||||
|
||||
@@ -261,6 +261,8 @@ static void assign_panicfn(void)
|
||||
error_exit("Expected panic function to have the signature fn void(String, String, String, uint).");
|
||||
}
|
||||
global_context.panic_var = decl;
|
||||
decl->no_strip = true;
|
||||
|
||||
if (active_target.no_stdlib) return;
|
||||
|
||||
const char *panicf = "std::core::builtin::panicf";
|
||||
@@ -275,6 +277,8 @@ static void assign_panicfn(void)
|
||||
return;
|
||||
}
|
||||
|
||||
panicf_decl->no_strip = true;
|
||||
|
||||
Type *panicf_fn_type = panicf_decl->type->canonical;
|
||||
if (panicf_decl->decl_kind != DECL_FUNC)
|
||||
{
|
||||
|
||||
@@ -297,10 +297,12 @@ void symtab_init(uint32_t capacity)
|
||||
attribute_list[ATTRIBUTE_BUILTIN] = KW_DEF("@builtin");
|
||||
attribute_list[ATTRIBUTE_CDECL] = KW_DEF("@cdecl");
|
||||
attribute_list[ATTRIBUTE_DEPRECATED] = KW_DEF("@deprecated");
|
||||
attribute_list[ATTRIBUTE_DYNAMIC] = KW_DEF("@dynamic");
|
||||
attribute_list[ATTRIBUTE_EXPORT] = KW_DEF("@export");
|
||||
attribute_list[ATTRIBUTE_EXTERN] = KW_DEF("@extern");
|
||||
attribute_list[ATTRIBUTE_EXTNAME] = KW_DEF("@extname");
|
||||
attribute_list[ATTRIBUTE_INLINE] = KW_DEF("@inline");
|
||||
attribute_list[ATTRIBUTE_INTERFACE] = KW_DEF("@interface");
|
||||
attribute_list[ATTRIBUTE_LITTLEENDIAN] = KW_DEF("@littleendian");
|
||||
attribute_list[ATTRIBUTE_LOCAL] = KW_DEF("@local");
|
||||
attribute_list[ATTRIBUTE_MAYDISCARD] = KW_DEF("@maydiscard");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -246,12 +246,18 @@ typedef enum
|
||||
BITSIZES_LEN
|
||||
} BitSizes;
|
||||
|
||||
typedef struct X86Features
|
||||
{
|
||||
unsigned long long bits[2];
|
||||
const char *as_string;
|
||||
} X86Features;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *target_triple;
|
||||
int llvm_opt_level;
|
||||
const char *features;
|
||||
const char *cpu;
|
||||
const char *features;
|
||||
ArchType arch;
|
||||
OsType os;
|
||||
VendorType vendor;
|
||||
@@ -277,8 +283,8 @@ typedef struct
|
||||
} x86;
|
||||
struct
|
||||
{
|
||||
X86Features features;
|
||||
unsigned align_simd_default : 16;
|
||||
X86VectorCapability x86_vector_capability : 4;
|
||||
bool soft_float : 1;
|
||||
bool is_win64 : 1;
|
||||
bool is_mingw64 : 1;
|
||||
@@ -373,4 +379,110 @@ static inline bool is_pie_pic(RelocModel reloc)
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
typedef enum X64Feature
|
||||
{
|
||||
X86_FEAT_CMOV,
|
||||
X86_FEAT_MMX,
|
||||
X86_FEAT_POPCNT,
|
||||
X86_FEAT_SSE,
|
||||
X86_FEAT_SSE2,
|
||||
X86_FEAT_SSE3,
|
||||
X86_FEAT_SSSE3,
|
||||
X86_FEAT_SSE4_1,
|
||||
X86_FEAT_SSE4_2,
|
||||
X86_FEAT_AVX,
|
||||
X86_FEAT_AVX2,
|
||||
X86_FEAT_SSE4_A,
|
||||
X86_FEAT_FMA4,
|
||||
X86_FEAT_XOP,
|
||||
X86_FEAT_FMA,
|
||||
X86_FEAT_AVX512F,
|
||||
X86_FEAT_BMI,
|
||||
X86_FEAT_BMI2,
|
||||
X86_FEAT_AES,
|
||||
X86_FEAT_PCLMUL,
|
||||
X86_FEAT_AVX512VL,
|
||||
X86_FEAT_AVX512BW,
|
||||
X86_FEAT_AVX512DQ,
|
||||
X86_FEAT_AVX512CD,
|
||||
X86_FEAT_AVX512ER,
|
||||
X86_FEAT_AVX512PF,
|
||||
X86_FEAT_AVX512VBMI,
|
||||
X86_FEAT_AVX512IFMA,
|
||||
X86_FEAT_AVX5124VNNIW,
|
||||
X86_FEAT_AVX5124FMAPS,
|
||||
X86_FEAT_AVX512VPOPCNTDQ,
|
||||
X86_FEAT_AVX512VBMI2,
|
||||
X86_FEAT_GFNI,
|
||||
X86_FEAT_VPCLMULQDQ,
|
||||
X86_FEAT_AVX512VNNI,
|
||||
X86_FEAT_AVX512BITALG,
|
||||
X86_FEAT_AVX512BF16,
|
||||
X86_FEAT_AVX512VP2INTERSECT,
|
||||
X86_FEAT_ADX,
|
||||
X86_FEAT_AMX_BF16,
|
||||
X86_FEAT_AMX_INT8,
|
||||
X86_FEAT_AMX_TILE,
|
||||
X86_FEAT_CLDEMOTE,
|
||||
X86_FEAT_CLFLUSHOPT,
|
||||
X86_FEAT_CLWB,
|
||||
X86_FEAT_CLZERO,
|
||||
X86_FEAT_CMPXCHG16B,
|
||||
X86_FEAT_CMPXCHG8B,
|
||||
X86_FEAT_CRC32,
|
||||
X86_FEAT_ENQCMD,
|
||||
X86_FEAT_F16C,
|
||||
X86_FEAT_FSGSBASE,
|
||||
X86_FEAT_FXSR,
|
||||
X86_FEAT_INVPCID,
|
||||
X86_FEAT_KL,
|
||||
X86_FEAT_WIDEKL,
|
||||
X86_FEAT_LWP,
|
||||
X86_FEAT_LZCNT,
|
||||
X86_FEAT_MOVBE,
|
||||
X86_FEAT_MOVDIR64B,
|
||||
X86_FEAT_MOVDIRI,
|
||||
X86_FEAT_MWAITX,
|
||||
X86_FEAT_PCONFIG,
|
||||
X86_FEAT_PKU,
|
||||
X86_FEAT_PREFETCHI,
|
||||
X86_FEAT_PREFETCHWT1,
|
||||
X86_FEAT_PRFCHW,
|
||||
X86_FEAT_PTWRITE,
|
||||
X86_FEAT_RDPID,
|
||||
X86_FEAT_RDPRU,
|
||||
X86_FEAT_RDRND,
|
||||
X86_FEAT_RDSEED,
|
||||
X86_FEAT_RTM,
|
||||
X86_FEAT_SAHF,
|
||||
X86_FEAT_SERIALIZE,
|
||||
X86_FEAT_SGX,
|
||||
X86_FEAT_SHA,
|
||||
X86_FEAT_SHSTK,
|
||||
X86_FEAT_TBM,
|
||||
X86_FEAT_TSXLDTRK,
|
||||
X86_FEAT_UINTR,
|
||||
X86_FEAT_VAES,
|
||||
X86_FEAT_VZEROUPPER,
|
||||
X86_FEAT_WAITPKG,
|
||||
X86_FEAT_WBNOINVD,
|
||||
X86_FEAT_X87,
|
||||
X86_FEAT_XSAVE,
|
||||
X86_FEAT_XSAVEC,
|
||||
X86_FEAT_XSAVEOPT,
|
||||
X86_FEAT_XSAVES,
|
||||
X86_FEAT_HRESET,
|
||||
X86_FEAT_RAOINT,
|
||||
X86_FEAT_AVX512FP16,
|
||||
X86_FEAT_AMX_FP16,
|
||||
X86_FEAT_CMPCCXADD,
|
||||
X86_FEAT_AVXNECONVERT,
|
||||
X86_FEAT_AVXVNNI,
|
||||
X86_FEAT_AVXIFMA,
|
||||
X86_FEAT_AVXVNNIINT8,
|
||||
X86_FEATURE_LAST = X86_FEAT_AVXVNNIINT8,
|
||||
} X86Feature;
|
||||
|
||||
|
||||
|
||||
extern PlatformTarget platform_target;
|
||||
|
||||
@@ -57,8 +57,6 @@ typedef struct Task_
|
||||
void *arg;
|
||||
} Task;
|
||||
|
||||
typedef void *TaskQueueRef;
|
||||
|
||||
uint16_t *win_utf8to16(const char *name);
|
||||
char *win_utf16to8(const uint16_t *name);
|
||||
// Use as if it was mkdir(..., 0755) == 0
|
||||
@@ -98,8 +96,7 @@ char *calloc_string(size_t len);
|
||||
void free_arena(void);
|
||||
void print_arena_status(void);
|
||||
void run_arena_allocator_tests(void);
|
||||
TaskQueueRef taskqueue_create(int threads, Task **task_list);
|
||||
void taskqueue_wait_for_completion(TaskQueueRef queue);
|
||||
void taskqueue_run(int threads, Task **task_list);
|
||||
int cpus(void);
|
||||
const char *date_get(void);
|
||||
const char *time_get(void);
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
typedef struct TaskQueue_
|
||||
{
|
||||
pthread_t *threads;
|
||||
int thread_count;
|
||||
pthread_mutex_t lock;
|
||||
Task **queue;
|
||||
} TaskQueue;
|
||||
@@ -35,48 +33,80 @@ SHUTDOWN:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TaskQueueRef taskqueue_create(int threads, Task **task_list)
|
||||
void taskqueue_run(int threads, Task **task_list)
|
||||
{
|
||||
assert(threads > 0);
|
||||
TaskQueue *queue = CALLOCS(TaskQueue);
|
||||
queue->threads = MALLOC(sizeof(pthread_t) * (unsigned)threads);
|
||||
queue->thread_count = threads;
|
||||
queue->queue = task_list;
|
||||
if (pthread_mutex_init(&queue->lock, NULL)) error_exit("Failed to set up mutex");
|
||||
pthread_t *pthreads = malloc(sizeof(pthread_t) * (unsigned)threads);
|
||||
TaskQueue queue = { .queue = task_list };
|
||||
if (pthread_mutex_init(&queue.lock, NULL)) error_exit("Failed to set up mutex");
|
||||
for (int i = 0; i < threads; i++)
|
||||
{
|
||||
if (pthread_create(queue->threads + i, NULL, taskqueue_thread, queue)) error_exit("Fail to set up thread pool");
|
||||
if (pthread_create(&pthreads[i], NULL, taskqueue_thread, &queue)) error_exit("Fail to set up thread pool");
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
void taskqueue_wait_for_completion(TaskQueueRef queue_ref)
|
||||
{
|
||||
assert(queue_ref);
|
||||
TaskQueue *queue = queue_ref;
|
||||
for (int i = 0; i < queue->thread_count; i++)
|
||||
for (int i = 0; i < threads; i++)
|
||||
{
|
||||
if (pthread_join(queue->threads[i], NULL) != 0) error_exit("Failed to join thread.");
|
||||
if (pthread_join(pthreads[i], NULL) != 0) error_exit("Failed to join thread.");
|
||||
}
|
||||
pthread_mutex_destroy(&queue->lock);
|
||||
free(pthreads);
|
||||
pthread_mutex_destroy(&queue.lock);
|
||||
}
|
||||
|
||||
#elif PLATFORM_WINDOWS
|
||||
|
||||
#include <Windows.h>
|
||||
#include <process.h>
|
||||
|
||||
typedef struct TaskQueue_
|
||||
{
|
||||
CRITICAL_SECTION lock;
|
||||
Task **queue;
|
||||
} TaskQueue;
|
||||
|
||||
static DWORD WINAPI taskqueue_thread(LPVOID lpParam)
|
||||
{
|
||||
TaskQueue *task_queue = (TaskQueue *)lpParam;
|
||||
bool is_active = false;
|
||||
while (1)
|
||||
{
|
||||
EnterCriticalSection(&task_queue->lock);
|
||||
unsigned task_count = vec_size(task_queue->queue);
|
||||
if (!task_count) goto SHUTDOWN;
|
||||
Task *task = (Task*)task_queue->queue[task_count - 1];
|
||||
vec_pop(task_queue->queue);
|
||||
LeaveCriticalSection(&task_queue->lock);
|
||||
task->task(task->arg);
|
||||
}
|
||||
SHUTDOWN:
|
||||
LeaveCriticalSection(&task_queue->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void taskqueue_run(int threads, Task **task_list)
|
||||
{
|
||||
assert(threads > 0);
|
||||
HANDLE *handles = malloc(sizeof(HANDLE) * (unsigned)threads);
|
||||
TaskQueue queue = { .queue = task_list };
|
||||
InitializeCriticalSection(&queue.lock);
|
||||
for (int i = 0; i < threads; i++)
|
||||
{
|
||||
handles[i] = (HANDLE)_beginthreadex(NULL, 0, taskqueue_thread, &queue, 0, NULL);
|
||||
if (handles[i] == NULL) error_exit("Fail to set up thread pool");
|
||||
}
|
||||
WaitForMultipleObjects(threads, handles, TRUE, INFINITE);
|
||||
|
||||
for (int i = 0; i < threads; i++)
|
||||
{
|
||||
CloseHandle(handles[i]);
|
||||
}
|
||||
free((void*)handles);
|
||||
DeleteCriticalSection(&queue.lock);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void taskqueue_add(TaskQueueRef queue_ref, Task *task)
|
||||
void taskqueue_run(int threads, Task **task_list)
|
||||
{
|
||||
}
|
||||
|
||||
TaskQueueRef taskqueue_create(int threads, Task **tasks)
|
||||
{
|
||||
return tasks;
|
||||
}
|
||||
|
||||
void taskqueue_wait_for_completion(TaskQueueRef queue)
|
||||
{
|
||||
Task **tasks = queue;
|
||||
FOREACH_BEGIN(Task *task, tasks)
|
||||
FOREACH_BEGIN(Task *task, task_list)
|
||||
task->task(task->arg);
|
||||
FOREACH_END();
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.513"
|
||||
#define COMPILER_VERSION "0.4.522"
|
||||
@@ -1,7 +1,7 @@
|
||||
// #target: macos-aarch64
|
||||
module test;
|
||||
typedef Int8x16 = ichar[<16>];
|
||||
typedef Float32x3 = float[<3>];
|
||||
def Int8x16 = ichar[<16>];
|
||||
def Float32x3 = float[<3>];
|
||||
|
||||
struct HFAv3
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #target: macos-x64
|
||||
// #opt: --x86vec=avx512
|
||||
// #opt: --x86cpu=avx512
|
||||
module abi;
|
||||
|
||||
struct Half1 {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// #target: macos-x64
|
||||
// #opt: --x86vec=avx
|
||||
// #opt: --x86cpu=avx1
|
||||
module test;
|
||||
|
||||
typedef Mm256 = float[<8>];
|
||||
def Mm256 = float[<8>];
|
||||
struct St256 {
|
||||
Mm256 m;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ fn void f39() { f38(x38); f37(x37); }
|
||||
|
||||
// CHECK: declare void @func40(%struct.t128* byval(%struct.t128) align 16)
|
||||
|
||||
typedef Mm128 = float[<4>];
|
||||
def Mm128 = float[<4>];
|
||||
struct Two128 {
|
||||
Mm128 m;
|
||||
Mm128 n;
|
||||
@@ -44,7 +44,7 @@ fn void func43(Sa s) {
|
||||
}
|
||||
|
||||
|
||||
typedef Vec46 = float[<2>];
|
||||
def 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); }
|
||||
|
||||
@@ -69,7 +69,7 @@ fn void test54() {
|
||||
test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 0, 1.0 });
|
||||
}
|
||||
|
||||
typedef Mm512 = float[<16>];
|
||||
def Mm512 = float[<16>];
|
||||
struct St512 {
|
||||
Mm512 m;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// #target: macos-x64
|
||||
// #opt: --x86vec=avx512
|
||||
// #opt: --x86cpu=avx512
|
||||
module test;
|
||||
|
||||
typedef Mm256 = float[<8>];
|
||||
typedef Mm512 = float[<16>];
|
||||
def Mm256 = float[<8>];
|
||||
def Mm512 = float[<16>];
|
||||
struct St512 {
|
||||
Mm512 m;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// #target: macos-x64
|
||||
// #opt: --x86vec=sse
|
||||
// #opt: --x86cpu=sse4
|
||||
module test;
|
||||
|
||||
typedef Mm256 = float[<8>];
|
||||
def Mm256 = float[<8>];
|
||||
struct St256 {
|
||||
Mm256 m;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ fn void f39() { f38(x38); f37(x37); }
|
||||
|
||||
// CHECK: declare void @func40(%struct.t128* byval(%struct.t128) align 16)
|
||||
|
||||
typedef Mm128 = float[<4>];
|
||||
def Mm128 = float[<4>];
|
||||
struct Two128 {
|
||||
Mm128 m;
|
||||
Mm128 n;
|
||||
|
||||
@@ -86,7 +86,7 @@ fn V4f32wrapper f27(V4f32wrapper x) {
|
||||
// PR22563 - We should unwrap simple structs and arrays to pass
|
||||
// and return them in the appropriate vector registers if possible.
|
||||
|
||||
typedef V8f32 = float[<8>];
|
||||
def V8f32 = float[<8>];
|
||||
struct V8f32wrapper {
|
||||
V8f32 v;
|
||||
}
|
||||
@@ -133,15 +133,15 @@ fn float f31(F31foo x) {
|
||||
return x.c;
|
||||
}
|
||||
|
||||
typedef V1i64 = ulong[<1>];
|
||||
def V1i64 = ulong[<1>];
|
||||
|
||||
fn V1i64 f34(V1i64 arg) { return arg; }
|
||||
|
||||
|
||||
typedef V1i64_2 = uint[<2>];
|
||||
def V1i64_2 = uint[<2>];
|
||||
fn V1i64_2 f35(V1i64_2 arg) { return arg+arg; }
|
||||
|
||||
typedef V2i32 = float[<2>];
|
||||
def V2i32 = float[<2>];
|
||||
fn V2i32 f36(V2i32 arg) { return arg; }
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ struct Large {
|
||||
long a, b, c, d;
|
||||
}
|
||||
|
||||
typedef V32i8 = char[<32>];
|
||||
def 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) {
|
||||
|
||||
@@ -20,10 +20,10 @@ fn Foo getFoo(Foo f)
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
%.introspect = type { i8, i64, i64, i64, [0 x i64] }
|
||||
%.introspect = type { i8, ptr, i64, i64, i64, [0 x i64] }
|
||||
%Foo = type { i8, i8, i8 }
|
||||
|
||||
@"$ct.test.Foo" = linkonce constant %.introspect { i8 10, i64 3, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foo" = linkonce global %.introspect { i8 10, ptr null, i64 3, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @test.testing() #0 {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #target: linux-x64
|
||||
// #opt: --x86vec=avx512
|
||||
// #opt: --x86cpu=avx512
|
||||
module foo;
|
||||
|
||||
struct StringRef
|
||||
|
||||
@@ -15,7 +15,7 @@ Connection[3] link @private
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
@"$ct.test.Connection" = linkonce constant %.introspect { i8 10, i64 24, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Connection" = linkonce global %.introspect { i8 10, ptr null, i64 24, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8
|
||||
@.str = private unnamed_addr constant [6 x i8] c"link1\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [6 x i8] c"link2\00", align 1
|
||||
@.str.2 = private unnamed_addr constant [6 x i8] c"link3\00", align 1
|
||||
|
||||
7
test/test_suite/attributes/attr_not_imported.c3
Normal file
7
test/test_suite/attributes/attr_not_imported.c3
Normal file
@@ -0,0 +1,7 @@
|
||||
module abc;
|
||||
|
||||
def @Foo = { @inline };
|
||||
|
||||
module bar;
|
||||
|
||||
fn void test() abc::@Foo {} // #error: Did you mean the attribute
|
||||
@@ -1,7 +1,7 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
const int FOO @private = 4;
|
||||
define @Align(x) = { @align(x * FOO) };
|
||||
def @Align(x) = { @align(x * FOO) };
|
||||
|
||||
module test2;
|
||||
import test;
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
module test;
|
||||
|
||||
define @Foo = { @noreturn @weak };
|
||||
def @Foo = { @noreturn @weak };
|
||||
|
||||
define @Align(y) = { @align(y) };
|
||||
define @Align16(x) @private = { @Align(8 * x) @align(1024) };
|
||||
define @Test = { @noinline };
|
||||
define @TestZero = { };
|
||||
def @Align(y) = { @align(y) };
|
||||
def @Align16(x) @private = { @Align(8 * x) @align(1024) };
|
||||
def @Test = { @noinline };
|
||||
def @TestZero = { };
|
||||
struct Foo
|
||||
{
|
||||
int z;
|
||||
@@ -32,7 +32,7 @@ fn void main() @TestZero
|
||||
/* #expect: test.ll
|
||||
|
||||
%Foo = type { i32, [1020 x i8], i32, [1020 x i8] }
|
||||
@"$ct.test.Foo" = linkonce constant %.introspect { i8 10, i64 2048, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foo" = linkonce global %.introspect { i8 10, ptr null, i64 2048, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@test.f = local_unnamed_addr global %Foo zeroinitializer, align 1024
|
||||
|
||||
define weak void @test.testme2() #0 {
|
||||
|
||||
@@ -5,8 +5,8 @@ bitstruct Test : int
|
||||
float a : 1..3; // #error: 'float' is not supported in a bitstruct, only enums, integer and boolean values may be used.
|
||||
}
|
||||
|
||||
typedef Baz = distinct float;
|
||||
typedef Foo = distinct bool;
|
||||
def Baz = distinct float;
|
||||
def Foo = distinct bool;
|
||||
enum Boo
|
||||
{
|
||||
BAR
|
||||
|
||||
@@ -22,8 +22,8 @@ fn void test1()
|
||||
$endswitch
|
||||
}
|
||||
|
||||
typedef Foo = int;
|
||||
typedef Bar = double;
|
||||
def Foo = int;
|
||||
def Bar = double;
|
||||
fn void test2()
|
||||
{
|
||||
$switch (int.typeid)
|
||||
|
||||
@@ -24,26 +24,27 @@ fn void main()
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
%.introspect = type { i8, i64, i64, i64, [0 x i64] }
|
||||
|
||||
%.introspect = type { i8, ptr, i64, i64, i64, [0 x i64] }
|
||||
%Foo = type { i32, i32 }
|
||||
%"int[]" = type { ptr, i64 }
|
||||
%any = type { ptr, i64 }
|
||||
|
||||
@"$ct.test.Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foo" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@.str = private unnamed_addr constant [9 x i8] c"%s %s %s\00", align 1
|
||||
@"$ct.int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.a2$int" = linkonce constant %.introspect { i8 15, i64 8, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$int" = linkonce constant %.introspect { i8 16, i64 16, i64 ptrtoint (ptr @"$ct.int" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.v2$int" = linkonce constant %.introspect { i8 17, i64 8, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.int" = linkonce global %.introspect { i8 2, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.a2$int" = linkonce global %.introspect { i8 15, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$int" = linkonce global %.introspect { i8 16, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.int" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.v2$int" = linkonce global %.introspect { i8 17, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@.__const = private unnamed_addr constant [1 x %Foo] [%Foo { i32 1, i32 2 }], align 4
|
||||
@.__const.1 = private unnamed_addr constant %Foo { i32 1, i32 2 }, align 4
|
||||
@.__const.2 = private unnamed_addr constant [1 x [2 x i32]] [[2 x i32] [i32 1, i32 2]], align 4
|
||||
@.__const.3 = private unnamed_addr constant [1 x [2 x double]] [[2 x double] [double 1.000000e+00, double 2.000000e+00]], align 16
|
||||
@.str.4 = private unnamed_addr constant [15 x i8] c"%s %s {%s, %s}\00", align 1
|
||||
@"$ct.a1$a2$int" = linkonce constant %.introspect { i8 15, i64 8, i64 ptrtoint (ptr @"$ct.a2$int" to i64), i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.double" = linkonce constant %.introspect { i8 4, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.a2$double" = linkonce constant %.introspect { i8 15, i64 16, i64 ptrtoint (ptr @"$ct.double" to i64), i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.a1$a2$double" = linkonce constant %.introspect { i8 15, i64 16, i64 ptrtoint (ptr @"$ct.a2$double" to i64), i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.a1$a2$int" = linkonce global %.introspect { i8 15, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.a2$int" to i64), i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.double" = linkonce global %.introspect { i8 4, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.a2$double" = linkonce global %.introspect { i8 15, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.double" to i64), i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.a1$a2$double" = linkonce global %.introspect { i8 15, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.a2$double" to i64), i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @test.test(i64 %0, ptr %1, i64 %2, double %3) #0 {
|
||||
|
||||
@@ -22,7 +22,7 @@ fn void main()
|
||||
|
||||
/* #expect: qnametest.ll
|
||||
|
||||
@"$ct.qnametest.Blob" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.qnametest.Blob" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@qnametest.x = local_unnamed_addr global i32 0, align 4
|
||||
@.str = private unnamed_addr constant [12 x i8] c"printf: %s\0A\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [7 x i8] c"printf\00", align 1
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
module foo;
|
||||
|
||||
// define <name> = <name>
|
||||
// def <name> = <name>
|
||||
def standard_foo = __stdin;
|
||||
def someFunctionIntBool = someFunction<int, bool>;
|
||||
def FooInt = Foo<int>;
|
||||
def A_CONST_INT = A_CONST<int>;
|
||||
|
||||
def standard_foo<int> = ofke; // #error: Expected '='
|
||||
def fn foo = fef; // #error: A variable, constant or attribute name was expected here.
|
||||
def fn foo = fef; // #error: A type, variable, constant or attribute name was expected here
|
||||
def feokfe = fn void(int); // #error: Expected a function or variable name here
|
||||
def AOFKE = ofek; // #error: Expected a constant name here
|
||||
def okfoe = OFKEOK; // #error: Expected a function or variable name here
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
typedef int = int; // #error: 'int' is the name of a built-in type and can't be used as an alias.
|
||||
def int = int; // #error: 'int' is a reserved keyword, try another name
|
||||
def main = foo; // #error: 'main' is reserved and cannot be used as an alias.
|
||||
|
||||
typedef hello = int; // #error: uppercase letter
|
||||
typedef hello = Foo; // #error: uppercase letter
|
||||
def hello = int; // #error: uppercase letter
|
||||
def hello = Foo; // #error: uppercase letter
|
||||
|
||||
typedef HELLO = int; // #error: uppercase letter
|
||||
typedef HELLO = Foo; // #error: uppercase letter
|
||||
def HELLO = int; // #error: uppercase letter
|
||||
def HELLO = Foo; // #error: uppercase letter
|
||||
@@ -1,3 +1,3 @@
|
||||
typedef Abc = int[*]; // #error: Inferred array types can only
|
||||
typedef Bcd = anyfault; // #error: 'anyfault' may not be aliased.
|
||||
typedef Efd = any; // #error: 'any' may not be aliased.
|
||||
def Abc = int[*]; // #error: Inferred array types can only
|
||||
def Bcd = anyfault; // #error: 'anyfault' may not be aliased.
|
||||
def Efd = any; // #error: 'any' may not be aliased.
|
||||
|
||||
@@ -3,8 +3,8 @@ fault Error
|
||||
ABC
|
||||
}
|
||||
|
||||
typedef Foo1 = distinct Error; // #error: You cannot create a distinct type
|
||||
def Foo1 = distinct Error; // #error: You cannot create a distinct type
|
||||
|
||||
typedef Foo3 = distinct void; // #error: create a distinct type from 'void'
|
||||
def Foo3 = distinct void; // #error: create a distinct type from 'void'
|
||||
|
||||
typedef Foo4 = distinct typeid; // #error: create a distinct type from 'typeid'
|
||||
def Foo4 = distinct typeid; // #error: create a distinct type from 'typeid'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
typedef Foo = distinct double[];
|
||||
def Foo = distinct double[];
|
||||
|
||||
fn void main()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ struct Struct
|
||||
double y;
|
||||
}
|
||||
|
||||
typedef Foo = distinct Struct;
|
||||
def Foo = distinct Struct;
|
||||
|
||||
struct Struct2
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module test;
|
||||
|
||||
typedef Foo = distinct int;
|
||||
def Foo = distinct int;
|
||||
|
||||
struct Struct
|
||||
{
|
||||
@@ -8,8 +8,8 @@ struct Struct
|
||||
int y;
|
||||
}
|
||||
|
||||
typedef Struct2 = distinct Struct;
|
||||
typedef StructArr = distinct Struct2[3];
|
||||
def Struct2 = distinct Struct;
|
||||
def StructArr = distinct Struct2[3];
|
||||
|
||||
fn void test(int x)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ union Union
|
||||
double y;
|
||||
}
|
||||
|
||||
typedef Foo = distinct Union;
|
||||
def Foo = distinct Union;
|
||||
|
||||
union Union2
|
||||
{
|
||||
@@ -19,9 +19,9 @@ union Union2
|
||||
}
|
||||
Foo f = { .x = 1 };
|
||||
|
||||
typedef Union3 = distinct Union2;
|
||||
def Union3 = distinct Union2;
|
||||
|
||||
typedef UnionArr = distinct Union3[3];
|
||||
def UnionArr = distinct Union3[3];
|
||||
|
||||
fn void test(int x)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module test;
|
||||
|
||||
typedef Int2 = distinct int;
|
||||
def Int2 = distinct int;
|
||||
|
||||
fn void test()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module test;
|
||||
|
||||
typedef Foo = distinct int;
|
||||
def Foo = distinct int;
|
||||
|
||||
fn int test1()
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ struct Struct
|
||||
double y;
|
||||
}
|
||||
|
||||
typedef Foo = distinct Struct;
|
||||
def Foo = distinct Struct;
|
||||
|
||||
struct Struct2
|
||||
{
|
||||
|
||||
@@ -18,8 +18,8 @@ fn void main()
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
@"$ct.uint" = linkonce constant %.introspect { i8 3, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foo" = linkonce constant { i8, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"$ct.uint" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 1 }, %"char[]" { ptr @.enum.1, i64 1 }] }, align 8
|
||||
@"$ct.uint" = linkonce global %.introspect { i8 3, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foo" = linkonce global { i8, ptr, i64, i64, i64, [2 x %"char[]"] } { i8 8, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.uint" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 1 }, %"char[]" { ptr @.enum.1, i64 1 }] }, 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
|
||||
|
||||
@@ -24,11 +24,11 @@ enum Foo : int(String val)
|
||||
|
||||
/* #expect: abc.ll
|
||||
|
||||
@"$ct.abc.Abc" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.abc.Abc" = linkonce global %.introspect { i8 10, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
@.enum.0 = internal constant [4 x i8] c"ABC\00", align 1
|
||||
@.enum.1 = internal constant [4 x i8] c"DEF\00", align 1
|
||||
@"$ct.int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.abc.Foo" = linkonce constant { i8, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 3 }, %"char[]" { ptr @.enum.1, i64 3 }] }, align 8
|
||||
@"$ct.int" = linkonce global %.introspect { i8 2, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.abc.Foo" = linkonce global { i8, ptr, i64, i64, i64, [2 x %"char[]"] } { i8 8, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 3 }, %"char[]" { ptr @.enum.1, i64 3 }] }, align 8
|
||||
@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [6 x i8] c"world\00", align 1
|
||||
@"abc.Foo$val" = linkonce constant [2 x %"char[]"] [%"char[]" { ptr @.str, i64 5 }, %"char[]" { ptr @.str.1, i64 5 }], align 8
|
||||
@@ -37,18 +37,19 @@ enum Foo : int(String val)
|
||||
|
||||
// #expect: test.ll
|
||||
|
||||
@"$ct.abc.Abc" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.abc.Abc" = linkonce global %.introspect { i8 10, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
@abc.dabc = external global i32, align 4
|
||||
@.enum.0 = internal constant [4 x i8] c"ABC\00", align 1
|
||||
@.enum.1 = internal constant [4 x i8] c"DEF\00", align 1
|
||||
@"$ct.int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.abc.Foo" = linkonce constant { i8, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 3 }, %"char[]" { ptr @.enum.1, i64 3 }] }, align 8
|
||||
@"$ct.int" = linkonce global %.introspect { i8 2, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.abc.Foo" = linkonce global { i8, ptr, i64, i64, i64, [2 x %"char[]"] } { i8 8, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 3 }, %"char[]" { ptr @.enum.1, i64 3 }] }, align 8
|
||||
@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [6 x i8] c"world\00", align 1
|
||||
@"abc.Foo$val" = linkonce constant [2 x %"char[]"] [%"char[]" { ptr @.str, i64 5 }, %"char[]" { ptr @.str.1, i64 5 }], align 8
|
||||
@.str.2 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
|
||||
@"$ct.char" = linkonce constant %.introspect { i8 3, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$char" = linkonce constant %.introspect { i8 16, i64 16, i64 ptrtoint (ptr @"$ct.char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.char" = linkonce global %.introspect { i8 3, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$char" = linkonce global %.introspect { i8 16, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
|
||||
|
||||
define void @test.main(ptr %0, i64 %1) #0 {
|
||||
entry:
|
||||
|
||||
@@ -22,18 +22,18 @@ fn void main()
|
||||
@.fault = internal constant [4 x i8] c"BAR\00", align 1
|
||||
@"foo.Foo$BAZ" = linkonce constant %.fault { i64 ptrtoint (ptr @"$ct.foo.Foo" to i64), %"char[]" { ptr @.fault.1, i64 3 }, i64 2 }, align 8
|
||||
@.fault.1 = internal constant [4 x i8] c"BAZ\00", align 1
|
||||
@"$ct.foo.Foo" = linkonce constant %.introspect { i8 9, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.foo.Foo" = linkonce global %.introspect { i8 9, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@.str = private unnamed_addr constant [4 x i8] c"BAR\00", align 1
|
||||
@.str.2 = private unnamed_addr constant [4 x i8] c"BAZ\00", align 1
|
||||
@.str.3 = private unnamed_addr constant [14 x i8] c"Foo.names: %s\00", align 1
|
||||
@"$ct.char" = linkonce constant %.introspect { i8 3, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$char" = linkonce constant %.introspect { i8 16, i64 16, i64 ptrtoint (ptr @"$ct.char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.String" = linkonce constant %.introspect { i8 18, i64 16, i64 ptrtoint (ptr @"$ct.sa$char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$String" = linkonce constant %.introspect { i8 16, i64 16, i64 ptrtoint (ptr @"$ct.String" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.char" = linkonce global %.introspect { i8 3, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$char" = linkonce global %.introspect { i8 16, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.String" = linkonce global %.introspect { i8 18, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.sa$char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$String" = linkonce global %.introspect { i8 16, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.String" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@.str.4 = private unnamed_addr constant [15 x i8] c"Foo.values: %s\00", align 1
|
||||
@"$ct.a2$foo.Foo" = linkonce constant %.introspect { i8 15, i64 16, i64 ptrtoint (ptr @"$ct.foo.Foo" to i64), i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.a2$foo.Foo" = linkonce global %.introspect { i8 15, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.foo.Foo" to i64), i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@.str.5 = private unnamed_addr constant [17 x i8] c"Foo.elements: %s\00", align 1
|
||||
@"$ct.long" = linkonce constant %.introspect { i8 2, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.long" = linkonce global %.introspect { i8 2, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
|
||||
entry:
|
||||
%x = alloca %"char[][]", align 8
|
||||
|
||||
@@ -27,9 +27,10 @@ fn void main()
|
||||
|
||||
%Foo = type { i32, i32 }
|
||||
|
||||
@"$ct.test.Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foo" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"test.MyErr$FOO" = linkonce constant %.fault { i64 ptrtoint (ptr @"$ct.test.MyErr" to i64), %"char[]" { ptr @.fault, i64 3 }, i64 1 }, align 8
|
||||
@"$ct.test.MyErr" = linkonce constant %.introspect { i8 9, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
@.fault = internal constant [4 x i8] c"FOO\00", align 1
|
||||
@"$ct.test.MyErr" = linkonce global %.introspect { i8 9, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, 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
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ fn void test6()
|
||||
int[]* e = &arr[1..2]; // #error: To take the address of a temporary value, use '&&' instead of '&'
|
||||
}
|
||||
|
||||
typedef Baz = Foo;
|
||||
typedef Bar = distinct int;
|
||||
def Baz = Foo;
|
||||
def Bar = distinct int;
|
||||
fault Err { FOO }
|
||||
union Un { int x; }
|
||||
enum MyEnum { BAR }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
typedef Number = int;
|
||||
def Number = int;
|
||||
|
||||
fn void test1()
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ enum Foo
|
||||
{
|
||||
ABC
|
||||
}
|
||||
typedef Abc = distinct int;
|
||||
def Abc = distinct int;
|
||||
fn void main()
|
||||
{
|
||||
Abc d = Foo.ABC; // #error: Implicitly casting
|
||||
|
||||
@@ -13,7 +13,7 @@ enum EnumB : char
|
||||
C, D
|
||||
}
|
||||
|
||||
typedef Func = fn void(Enum);
|
||||
def Func = fn void(Enum);
|
||||
|
||||
fn void test1(Enum e)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// #target: macos-x64
|
||||
module cast_expr;
|
||||
|
||||
fn int main(int argc, char** argv)
|
||||
|
||||
@@ -8,9 +8,9 @@ enum Enum : uptr
|
||||
A, B
|
||||
}
|
||||
|
||||
typedef Func = fn void(int);
|
||||
typedef FuncOther = fn bool(char*);
|
||||
typedef FuncSame = fn void(int);
|
||||
def Func = fn void(int);
|
||||
def FuncOther = fn bool(char*);
|
||||
def FuncSame = fn void(int);
|
||||
|
||||
|
||||
fn void test1(Func arg)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
typedef Number = int;
|
||||
def Number = int;
|
||||
|
||||
fn void test1()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
typedef Number8 = char;
|
||||
typedef Number32 = int;
|
||||
typedef DNumber32 = distinct int;
|
||||
def Number8 = char;
|
||||
def Number32 = int;
|
||||
def DNumber32 = distinct int;
|
||||
fn void test1()
|
||||
{
|
||||
int a = (ichar)(10);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
typedef Foo = distinct double;
|
||||
typedef Bar = distinct void*;
|
||||
def Foo = distinct double;
|
||||
def Bar = distinct void*;
|
||||
fn int main()
|
||||
{
|
||||
float f = 1;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module test;
|
||||
|
||||
typedef Foo = distinct int;
|
||||
def Foo = distinct int;
|
||||
|
||||
fn void test1()
|
||||
{
|
||||
|
||||
@@ -42,10 +42,10 @@ fn void testSimple()
|
||||
%.anon = type { i32, i32 }
|
||||
%.anon.0 = type { double }
|
||||
|
||||
@"$ct.pointer_access.c" = linkonce constant %.introspect { i8 10, i64 40, i64 0, i64 5, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.pointer_access.$anon" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.pointer_access.$anon.4" = linkonce constant %.introspect { i8 11, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.pointer_access.ExtraSimple" = linkonce constant %.introspect { i8 10, i64 72, i64 0, i64 6, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.pointer_access.c" = linkonce global %.introspect { i8 10, ptr null, i64 40, i64 0, i64 5, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.pointer_access.$anon" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.pointer_access.$anon.4" = linkonce global %.introspect { i8 11, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.pointer_access.ExtraSimple" = linkonce global %.introspect { i8 10, ptr null, i64 72, i64 0, i64 6, [0 x i64] zeroinitializer }, 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 {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
typedef Callback = fn int(char c);
|
||||
def Callback = fn int(char c);
|
||||
struct Person { int i; }
|
||||
struct Company { int j; }
|
||||
enum Status : int
|
||||
|
||||
@@ -32,14 +32,14 @@ fn void main()
|
||||
/* #expect: test.ll
|
||||
|
||||
@.str = private unnamed_addr constant [3 x i8] c"%d\00", align 1
|
||||
@"$ct.int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.int" = linkonce global %.introspect { i8 2, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@.str.1 = private unnamed_addr constant [3 x i8] c"%d\00", align 1
|
||||
@.str.2 = private unnamed_addr constant [3 x i8] c"%d\00", align 1
|
||||
@.str.3 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
|
||||
@.str.4 = private unnamed_addr constant [13 x i8] c"fn int(int)*\00", align 1
|
||||
@"$ct.char" = linkonce constant %.introspect { i8 3, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$char" = linkonce constant %.introspect { i8 16, i64 16, i64 ptrtoint (ptr @"$ct.char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.String" = linkonce constant %.introspect { i8 18, i64 16, i64 ptrtoint (ptr @"$ct.sa$char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.char" = linkonce global %.introspect { i8 3, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.sa$char" = linkonce global %.introspect { i8 16, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.String" = linkonce global %.introspect { i8 18, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.sa$char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@.str.5 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
|
||||
@.str.6 = private unnamed_addr constant [13 x i8] c"fn int(int)*\00", align 1
|
||||
@.str.7 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
|
||||
@@ -48,8 +48,9 @@ fn void main()
|
||||
@.str.10 = private unnamed_addr constant [7 x i8] c"test2*\00", align 1
|
||||
@.str.11 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
|
||||
@.str.12 = private unnamed_addr constant [14 x i8] c"fn int!(int)*\00", align 1
|
||||
@"$ct.fn$int$int$" = linkonce constant %.introspect { i8 13, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.p$fn$int$int$" = linkonce constant %.introspect { i8 19, i64 8, i64 ptrtoint (ptr @"$ct.fn$int$int$" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.fn$int$int$" = linkonce global %.introspect { i8 13, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.p$fn$int$int$" = linkonce global %.introspect { i8 19, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.fn$int$int$" to i64), i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
|
||||
|
||||
define void @test.main() #0 {
|
||||
entry:
|
||||
|
||||
@@ -65,8 +65,8 @@ fn int Foo2.mutate(Foo2 *foo)
|
||||
return ++foo.x;
|
||||
}
|
||||
|
||||
define oopsInt = test2::argh<int>;
|
||||
define oopsDouble = test2::argh<int>;
|
||||
def oopsInt = test2::argh<int>;
|
||||
def oopsDouble = test2::argh<int>;
|
||||
typedef Argh = fn int(double, Bobo);
|
||||
typedef Argh2 = fn int(double, Bobo);
|
||||
|
||||
@@ -95,12 +95,12 @@ struct Foo
|
||||
int b;
|
||||
}
|
||||
|
||||
define getValueInt = test2::getValue<int>;
|
||||
define getValueDouble = test2::getValue<double>;
|
||||
def getValueInt = test2::getValue<int>;
|
||||
def getValueDouble = test2::getValue<double>;
|
||||
typedef IntBlob = test2::Blob<int>;
|
||||
typedef DoubleBlob = Blob<double>;
|
||||
define getMultInt = test2::getMult<int>;
|
||||
define getMultDouble = test2::getMult<double>;
|
||||
def getMultInt = test2::getMult<int>;
|
||||
def getMultDouble = test2::getMult<double>;
|
||||
|
||||
typedef IntArray = List<int>;
|
||||
typedef IntList = LinkedList<int>;
|
||||
@@ -173,7 +173,7 @@ module hello_world;
|
||||
import foo;
|
||||
|
||||
extern fn int printf(char *, ...);
|
||||
define doubleMult = foo::check<double>;
|
||||
def doubleMult = foo::check<double>;
|
||||
|
||||
fn void hello()
|
||||
{
|
||||
@@ -219,8 +219,8 @@ macro Hello wut()
|
||||
}
|
||||
|
||||
typedef Bye = Hello;
|
||||
define wat = wut;
|
||||
define byebye = hello;
|
||||
def wat = wut;
|
||||
def byebye = hello;
|
||||
|
||||
fn int hello()
|
||||
{
|
||||
@@ -243,13 +243,13 @@ fn Type getValue(Blob blob)
|
||||
%List = type { i64, i64, ptr, ptr }
|
||||
%Foo = type { i32, i32 }
|
||||
|
||||
@"$ct.test.Bobo" = linkonce constant %.introspect { i8 10, i64 20, i64 0, i64 6, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Blob" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foor" = linkonce constant %.introspect { i8 11, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foo2" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Bobo" = linkonce global %.introspect { i8 10, ptr null, i64 20, i64 0, i64 6, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Blob" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foor" = linkonce global %.introspect { i8 11, ptr null, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.Foo2" = linkonce global %.introspect { i8 10, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8
|
||||
|
||||
@"$ct.int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.MyEnum" = linkonce constant { i8, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 4 }, %"char[]" { ptr @.enum.1, i64 5 }, %"char[]" { ptr @.enum.2, i64 3 }] }, align 8
|
||||
@"$ct.int" = linkonce global %.introspect { i8 2, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.test.MyEnum" = linkonce global { i8, ptr, i64, i64, i64, [3 x %"char[]"] } { i8 8, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 4 }, %"char[]" { ptr @.enum.1, i64 5 }, %"char[]" { ptr @.enum.2, i64 3 }] }, align 8
|
||||
@"test_static$x" = internal unnamed_addr global i32 1, align 4
|
||||
|
||||
define void @test.Foo2.printme(ptr %0) #0 {
|
||||
|
||||
@@ -67,8 +67,8 @@ fn int Foo2.mutate(Foo2 *foo)
|
||||
|
||||
|
||||
|
||||
define oopsInt = test2::argh<int>;
|
||||
define oopsDouble = test2::argh<int>;
|
||||
def oopsInt = test2::argh<int>;
|
||||
def oopsDouble = test2::argh<int>;
|
||||
typedef Argh = fn int(double, Bobo);
|
||||
typedef Argh2 = fn int(double, Bobo);
|
||||
|
||||
@@ -97,12 +97,12 @@ struct Foo
|
||||
int b;
|
||||
}
|
||||
|
||||
define getValueInt = test2::getValue<int>;
|
||||
define getValueDouble = test2::getValue<double>;
|
||||
def getValueInt = test2::getValue<int>;
|
||||
def getValueDouble = test2::getValue<double>;
|
||||
typedef IntBlob = test2::Blob<int>;
|
||||
typedef DoubleBlob = Blob<double>;
|
||||
define getMultInt = test2::getMult<int>;
|
||||
define getMultDouble = test2::getMult<double>;
|
||||
def getMultInt = test2::getMult<int>;
|
||||
def getMultDouble = test2::getMult<double>;
|
||||
|
||||
typedef IntArray = List<int>;
|
||||
typedef IntList = LinkedList<int>;
|
||||
@@ -175,7 +175,7 @@ module hello_world;
|
||||
import foo;
|
||||
|
||||
extern fn int printf(char *, ...);
|
||||
define doubleMult = foo::check<double>;
|
||||
def doubleMult = foo::check<double>;
|
||||
|
||||
fn void hello()
|
||||
{
|
||||
@@ -221,8 +221,8 @@ macro Hello wut()
|
||||
}
|
||||
|
||||
typedef Bye = Hello;
|
||||
define wat = wut;
|
||||
define byebye = hello;
|
||||
def wat = wut;
|
||||
def byebye = hello;
|
||||
|
||||
fn int hello()
|
||||
{
|
||||
@@ -259,13 +259,13 @@ $"$ct.int" = comdat any
|
||||
|
||||
$"$ct.test.MyEnum" = comdat any
|
||||
|
||||
@"$ct.test.Bobo" = linkonce constant %.introspect { i8 10, i64 20, i64 0, i64 6, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.Blob" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.Foor" = linkonce constant %.introspect { i8 11, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.Foo2" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.MyEnum" = linkonce constant { i8, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 4 }, %"char[]" { ptr @.enum.1, i64 5 }, %"char[]" { ptr @.enum.2, i64 3 }] }, comdat, align 8
|
||||
@"$ct.test.Bobo" = linkonce global %.introspect { i8 10, ptr null, i64 20, i64 0, i64 6, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.Blob" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.Foor" = linkonce global %.introspect { i8 11, ptr null, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.Foo2" = linkonce global %.introspect { i8 10, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.Foo" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.int" = linkonce global %.introspect { i8 2, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, comdat, align 8
|
||||
@"$ct.test.MyEnum" = linkonce global { i8, ptr, i64, i64, i64, [3 x %"char[]"] } { i8 8, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 4 }, %"char[]" { ptr @.enum.1, i64 5 }, %"char[]" { ptr @.enum.2, i64 3 }] }, 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import std::io;
|
||||
typedef Tester = fn int(int x, int y, int z);
|
||||
def Tester = fn int(int x, int y, int z);
|
||||
|
||||
fn int test1(
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 20
|
||||
|
||||
@@ -22,7 +22,8 @@ fn int main()
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
@"$ct.int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
|
||||
@"$ct.int" = linkonce global %.introspect { i8 2, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8
|
||||
|
||||
define void @test.retest(ptr %0, i64 %1) #0 {
|
||||
entry:
|
||||
|
||||
@@ -9,4 +9,4 @@ fn void abc()
|
||||
module tester;
|
||||
import foo;
|
||||
|
||||
define abc_my = foo::abc<int>;
|
||||
def abc_my = foo::abc<int>;
|
||||
@@ -2,7 +2,7 @@
|
||||
module test;
|
||||
import bar;
|
||||
|
||||
typedef BazTest = Baz<Test>;
|
||||
def BazTest = Baz<Test>;
|
||||
|
||||
struct Test // #error: Recursive definition of 'Test'
|
||||
{
|
||||
|
||||
@@ -13,8 +13,8 @@ fn Type addMult(Type x, Type a, Type b)
|
||||
module test;
|
||||
import gen;
|
||||
|
||||
define intMult = gen::mult<int>;
|
||||
define doubleAddMult = gen::addMult<double>;
|
||||
def intMult = gen::mult<int>;
|
||||
def doubleAddMult = gen::addMult<double>;
|
||||
|
||||
fn int getIt(int i)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ fn Type x(Type t)
|
||||
|
||||
module test;
|
||||
import hello;
|
||||
define xint = hello::x<int, -123>;
|
||||
def xint = hello::x<int, -123>;
|
||||
|
||||
import std::io;
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ fn int test()
|
||||
%"int[]" = type { ptr, i64 }
|
||||
%"Bar[]" = type { ptr, i64 }
|
||||
|
||||
@"$ct.general_tests.Baz" = linkonce constant %.introspect { i8 11, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.general_tests.Bar" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.general_tests.Baz" = linkonce global %.introspect { i8 11, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.general_tests.Bar" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, 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
|
||||
|
||||
@@ -35,8 +35,8 @@ fn int main()
|
||||
%Bar = type { i32, i32 }
|
||||
%"Bar[]" = type { ptr, i64 }
|
||||
|
||||
@"$ct.statics.Baz" = linkonce constant %.introspect { i8 11, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.statics.Bar" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.statics.Baz" = linkonce global %.introspect { i8 11, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.statics.Bar" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@.taddr = private global [1 x %Bar] [%Bar { i32 1, i32 2 }], align 8
|
||||
@"test$c" = internal unnamed_addr global %"Bar[]" { ptr @.taddr, i64 1 }, align 8
|
||||
@.str = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
|
||||
|
||||
@@ -52,8 +52,8 @@ fn int main()
|
||||
%File = type { ptr }
|
||||
%Baz = type { double }
|
||||
|
||||
@"$ct.subarrays.Baz" = linkonce constant %.introspect { i8 11, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.subarrays.Bar" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.subarrays.Baz" = linkonce global %.introspect { i8 11, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.subarrays.Bar" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, 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[]" { ptr @.taddr, i64 2 }, align 8
|
||||
@.taddr.3 = private global [2 x i32] [i32 1, i32 2], align 4
|
||||
@@ -68,6 +68,7 @@ fn int main()
|
||||
@.__const = private unnamed_addr constant { i32, [4 x i8] } { i32 1, [4 x i8] undef }, align 8
|
||||
@.str.9 = private unnamed_addr constant [3 x i8] c"Ok\00", align 1
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
%w = alloca %Bar, align 4
|
||||
|
||||
@@ -79,7 +79,7 @@ fn void main()
|
||||
|
||||
%Foo = type { i16, i8, i8, i16, i16 }
|
||||
|
||||
@"$ct.userland_bitcast.Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 5, [0 x i64] zeroinitializer }, align 8
|
||||
@"$ct.userland_bitcast.Foo" = linkonce global %.introspect { i8 10, ptr null, i64 8, i64 0, i64 5, [0 x i64] zeroinitializer }, 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
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ struct An3
|
||||
An2 y;
|
||||
}
|
||||
|
||||
typedef AnCall = fn void();
|
||||
def AnCall = fn void();
|
||||
|
||||
struct An2
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
typedef NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data);
|
||||
def NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data);
|
||||
fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) @private {}
|
||||
|
||||
struct TreeNode { int abc; NodeNotifyHandler notifyHandler; }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user