/
intrinsics.alu
183 lines (152 loc) · 6.06 KB
/
intrinsics.alu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//! Functions implemented directly in the compiler.
//!
//! Functions in this module are not intended for general use, and are usually called by
//! wrapper functions in the standard library (e.g. [mem::size_of] and [std::unreachable]).
//!
//! Intrinsic functions are not first-class citizens. You cannot take a reference to
//! one, or pass it as an argument to another function. The intrinsic call signature is not
//! strictly enforced (pass as many arguments as you want, they will be ignored, the intrinsic
//! may return a value of different type, etc.). Needless to say, intrinsics do not participate
//! in type inference.
/// Fail the compilation process with a human-readable message.
///
/// Use [std::compile_fail] instead.
extern "intrinsic" fn compile_fail(reason: &[u8]) -> !; // that's like a super !, since the code following it will not even be compiled, let alone executed
/// Emit a warning message during compilation.
extern "intrinsic" fn compile_warn(reason: &[u8]);
/// Emit a note during compilation.
extern "intrinsic" fn compile_note(reason: &[u8]);
/// Unreachable code
///
/// Use [std::unreachable] instead.
extern "intrinsic" fn unreachable() -> !;
/// Trigger a trap (e.g. through an invalid instruction).
extern "intrinsic" fn trap() -> !;
/// Size of type in bytes
///
/// Use [mem::size_of] instead.
extern "intrinsic" fn size_of<T>() -> usize;
/// Length of a fixed-size array
///
/// Use [std::builtins::array::len] instead.
extern "intrinsic" fn array_length_of<T: builtins::Array>() -> usize;
/// Unique type identifier
///
/// Use [std::typing::type_id] instead.
extern "intrinsic" fn type_id<T>() -> usize;
/// Name of a type
///
/// Use [std::typing::type_name] instead.
extern "intrinsic" fn type_name<T>() -> &[u8];
/// Minimum alignment of a type in bytes.
///
/// Use [mem::align_of] instead.
extern "intrinsic" fn align_of<T>() -> usize;
/// Generate a virtual method table for the given protocol and type.
///
/// Do not use directly, use coercion to `&dyn Protocol` instead. Meant to be called
/// from a static initializer.
extern "intrinsic" fn vtable<Proto, T>() -> [&fn(); 0];
/// Minimal support for unit testing in the compiler.
///
/// During AST construction, compiler will collect all the methods with `#[test]` attribute and
/// make them available via this intrinsic.
///
/// Do not use this directly. If implementing a custom test framework, use the
/// [runtime::internal::TEST_CASES] static instead to ensure that all test cases have been discovered.
extern "intrinsic" fn test_cases() -> &[TestCaseMeta];
/// Enum variants
///
/// Do not use directly, use [typing::enum_variants] instead. Meant to be called
/// from a static initializer (see [typing::internal::ENUM_VARIANTS]).
extern "intrinsic" fn enum_variants<T: builtins::Enum>() -> [(&[u8], T); 0];
/// Inline assembly
extern "intrinsic" fn asm(assembly: &[u8]);
/// Uninitialized value of type `T`
///
/// Use [mem::uninitialized] instead.
extern "intrinsic" fn uninitialized<T>() -> T;
/// Zero-initialized value of type `T`
///
/// Use [mem::zeroed] instead.
extern "intrinsic" fn zeroed<T>() -> T;
/// Appropriately aligned non-null pointer
///
/// Use [mem::dangling] instead.
extern "intrinsic" fn dangling<Ptr: builtins::Pointer>() -> Ptr;
/// Whether we are in constant evaluation context
///
/// Use [runtime::in_const_context] instead.
extern "intrinsic" fn in_const_context() -> bool;
/// Returns `true` if the expression is evaluable at compile-time.
///
/// Use [runtime::is_const_evaluable] instead.
extern "intrinsic" fn is_const_evaluable<T>(expr: T) -> bool;
/// Forces the argument to be evaluated at compile-time.
///
/// Use [runtime::const_eval] instead.
extern "intrinsic" fn const_eval<T>(expr: T) -> T;
/// Panics during constant evaluation (aborts compilation).
///
/// Invoking this during normal runtime is undefined behavior.
///
/// Use [panic] instead.
extern "intrinsic" fn const_panic(msg: &[u8]) -> !;
/// Writes a note during constant evaluation.
///
/// Invoking this during normal runtime is undefined behavior.
///
/// Use [println] instead.
extern "intrinsic" fn const_note(msg: &[u8]);
/// Writes a warning during constant evaluation.
///
/// Invoking this during normal runtime is undefined behavior.
///
/// Use [eprintln] instead.
extern "intrinsic" fn const_warning(msg: &[u8]);
/// Allocates memory during constant evaluation.
///
/// Use [mem::slice::alloc] in const context instead.
extern "intrinsic" fn const_alloc<T>(size: usize) -> &mut T;
/// Frees memory allocated during constant evaluation.
///
/// Use [mem::slice::free] in const context instead.
extern "intrinsic" fn const_free<T>(ptr: &mut T);
/// Transmute a value from one type to another.
///
/// Use [util::transmute] instead.
extern "intrinsic" fn transmute<T1, T2>(val: T1) -> T2;
/// Cast a pointer into a pointer-to-volatile.
///
/// Use [mem::read_volatile] and [mem::write_volatile] instead.
extern "intrinsic" fn volatile<Ptr: builtins::Pointer>(ptr: Ptr) -> Ptr;
/// Identity function.
///
/// Adds a tag to the IR subtree. This has no effect on the generated code, but is generally preserved
/// accross passes until codegen. Tags control certain aspects of const evaluation and compiler
/// diagnostics. They are not meant to be used by user code.
///
/// Tags are currently added when desugaring certain language constructs, such as `for` loops and `defer`
/// expressions.
///
/// The type, constness and value-kind of the tagged expression are preserved.
/// ```
/// let x = 0;
/// std::intrinsics::tag("foo", x) += 1; // this is valid
///
/// assert_eq!(x, 1);
/// ```
///
/// No user-facing equivalent.
extern "intrinsic" fn tag<T>(tag: &[u8], val: T) -> T;
#[cfg(boot)]
{
// These are only useful in alumina-boot, aluminac will use LLVM intrinsics that are
// explicitely defined.
/// Return the value of a C builtin constant
extern "intrinsic" fn codegen_const<T>(name: &[u8]) -> T;
/// Call a builtin C function
extern "intrinsic" fn codegen_func<T>(name: &[u8], ...) -> T;
/// Call a builtin C "type function" (e.g. sizeof)
extern "intrinsic" fn codegen_type_func<T, Ret>(name: &[u8]) -> T;
}