///|
pub(all) enum FnAttr {
/// Describes behavior of an allocator function in terms of known properties.
AllocKind(Int)
/// The result of the function is guaranteed to point to a number of bytes that
/// we can determine if we know the value of the function's arguments.
AllocSize(Int)
/// inline=always.
AlwaysInline
/// Callee is recognized as a builtin, despite nobuiltin attribute on its
/// declaration.
Builtin
/// Marks function as being in a cold path.
Cold
/// Can only be moved to control-equivalent blocks.
/// NB: Could be IntersectCustom with "or" handling.
Convergent
/// Marks function as being in a hot path and frequently called.
Hot
/// Do not instrument function with sanitizers.
DisableSanitizerInstrumentation
/// Whether to keep return instructions, or replace with a jump to an external symbol.
FnRetThunkExtern
/// Function has a hybrid patchable thunk.
HybridPatchable
/// Source said inlining was desirable.
InlineHint
/// Build jump-instruction tables and replace refs.
JumpTable
/// Build jump-instruction tables and replace refs.
Memory(Int)
/// Function must be optimized for size first.
MinSize
/// Naked function.
Naked
/// Callee isn't recognized as a builtin.
NoBuiltin
/// Function cannot enter into caller's translation unit.
NoCallback
/// Function is not a source of divergence.
NoDivergenceSource
/// Call cannot be duplicated.
NoDuplicate
/// Function does not deallocate memory.
NoFree
/// Disable implicit floating point insts.
NoImplicitFloat
/// inline=never.
NoInline
/// Function is called early and/or often, so lazy binding isn't worthwhile.
NonLazyBind
/// Disable merging for specified functions or call sites.
NoMerge
/// The function does not recurse.
NoRecurse
/// Disable redzone.
NoRedZone
/// Mark the function as not returning.
NoReturn
/// Function does not synchronize.
NoSync
/// Disable Indirect Branch Tracking.
NoCfCheck
/// Function should not be instrumented.
NoProfile
/// This function should not be instrumented but it is ok to inline profiled functions into it.
SkipProfile
/// Function doesn't unwind stack.
NoUnwind
/// No SanitizeBounds instrumentation.
NoSanitizeBounds
/// No SanitizeCoverage instrumentation.
NoSanitizeCoverage
/// Null pointer in address space zero is valid.
NullPointerIsValid
/// Select optimizations that give decent debug info.
OptimizeForDebugging
/// Select optimizations for best fuzzing signal.
OptForFuzzing
/// opt_size.
OptimizeForSize
/// Function must not be optimized.
OptimizeNone
/// Similar to byval but without a copy.
Preallocated(&Type)
/// Function can return twice.
ReturnTwice
/// Safe Stack protection.
SafeStack
/// Shadow Call Stack protection.
ShadowCallStack
/// Alignment of stack for function (3 bits) stored as log2 of alignment with
/// +1 bias 0 means unaligned (different from alignstack=(1)).
StackAlignment(Int)
/// Function can be speculated.
Speculatable
/// Stack protection.
StackProtect
/// Stack protection required.
StackProtectReq
/// Strong Stack protection.
StackProtectStrong
/// Function was called in a scope requiring strict floating point semantics.
StrictFP
/// AddressSanitizer is on.
SanitizeAddress
/// ThreadSanitizer is on.
SanitizeThread
/// TypeSanitizer is on.
SanitizeType
/// MemorySanitizer is on.
SanitizeMemory
/// HWAddressSanitizer is on.
SanitizeHWAddress
/// MemTagSanitizer is on.
SanitizeMemTag
/// NumericalStabilitySanitizer is on.
SanitizeNumericalStability
/// RealtimeSanitizer is on.
SanitizeRealtime
/// RealtimeSanitizer should error if a real-time unsafe function is invoked
/// during a real-time sanitized function (see `sanitize_realtime`).
SanitizeRealtimeBlocking
/// Speculative Load Hardening is enabled.
///
/// Note that this uses the default compatibility (always compatible during
/// inlining) and a conservative merge strategy where inlining an attributed
/// body will add the attribute to the caller. This ensures that code carrying
/// this attribute will always be lowered with hardening enabled.
SpeculativeLoadHardening
/// Function must be in a unwind table.
UWTable(Int)
/// Minimum/Maximum vscale value for function.
VScaleRange(Int)
/// Function always comes back to callsite.
WillReturn
/// Function is required to make Forward Progress.
MustProgress
/// Function is a presplit coroutine.
PresplitCoroutine
/// The coroutine would only be destroyed when it is complete.
CoroDestroyOnlyWhenComplete
/// The coroutine call meets the elide requirement. Hint the optimization
/// pipeline to perform elide on the call or invoke instruction.
CoroElideSafe
DenormalFPMath
DenormalFPMathF32
} derive(Hash, Eq)
///|
///
/// TODO: Initializes is a ConstantRangeListAttr
/// TODO: Range is a ConstantRangeAttr
pub(all) enum ParamAttr {
/// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias.
/// 0 means unaligned (different from align(1)).
Alignment(Int)
/// Parameter of a function that tells us the alignment of an allocation, as in
/// aligned_alloc and aligned ::operator::new.
AllocAlign
/// Parameter is the pointer to be manipulated by the allocator function.
AllocatedPointer
/// Pass structure by value.
ByVal(&Type)
/// Mark in-memory ABI type.
ByRef(&Type)
/// Parameter or return value may not contain uninitialized or poison bits.
NoUndef
/// Pointer is known to be dereferenceable.
Dereferenceable(Int)
/// Pointer is either null or dereferenceable.
DereferenceableOrNull(Int)
/// Provide pointer element type to intrinsic.
ElementType(&Type)
/// Pass structure in an alloca.
InAlloca(&Type)
/// Pointer argument memory is initialized.
Initializes
/// Force argument to be passed in register.
InReg
/// Forbidden floating-point classes.
NoFPClass
/// Nested function static chain.
Nest
/// Considered to not alias after call.
NoAlias
/// Specify how the pointer may be captured.
Captures
/// No extension needed before/after call (high bits are undefined).
NoExt
/// Function does not deallocate memory.
NoFree
/// Argument is dead if the call unwinds.
DeadOnUnwind
/// Pointer is known to be not null.
NonNull
/// Similar to byval but without a copy.
Preallocated(&Type)
/// Parameter or return value is within the specified range.
Range
/// Function does not access memory.
ReadNone
/// Function only reads from memory.
ReadOnly
/// Return value is always equal to this argument.
Returned
/// Parameter is required to be a trivial constant.
ImmArg
/// Sign extended before/after call.
SExt
/// Alignment of stack for function (3 bits) stored as log2 of alignment with
/// +1 bias 0 means unaligned (different from alignstack=(1)).
StackAlignment(Int)
/// Hidden pointer to structure to return.
StructRet
/// Argument is swift error.
SwiftError
/// Argument is swift self/context.
SwiftSelf
/// Argument is swift async context.
SwiftAsync
/// Pointer argument is writable.
Writable
/// Function only writes to memory.
WriteOnly
/// Zero extended before/after call.
ZExt
} derive(Hash, Eq)
///|
pub(all) enum RetAttr {
/// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias.
/// 0 means unaligned (different from align(1)).
Alignment(Int)
/// Parameter or return value may not contain uninitialized or poison bits.
NoUndef
/// Pointer is known to be dereferenceable.
Dereferenceable(Int)
/// Pointer is either null or dereferenceable.
DereferenceableOrNull(Int)
/// Force argument to be passed in register.
InReg
/// Forbidden floating-point classes.
NoFPClass
/// Considered to not alias after call.
NoAlias
/// No extension needed before/after call (high bits are undefined).
NoExt
/// Pointer is known to be not null.
NonNull
/// Sign extended before/after call.
SExt
/// Alignment of stack for function (3 bits) stored as log2 of alignment with
/// +1 bias 0 means unaligned (different from alignstack=(1)).
StackAlignment(Int)
/// Zero extended before/after call.
ZExt
} derive(Hash, Eq)
///|
pub impl Show for FnAttr with output(self, logger) {
let str = match self {
AllocSize(a) => "allocsize(\{a})"
AlwaysInline => "alwaysinline"
Builtin => "builtin"
NoInline => "noinline"
AllocKind(i) => "allockind(\{i})"
Cold => "cold"
Convergent => "convergent"
Hot => "hot"
DisableSanitizerInstrumentation => "disable_sanitizer_instrumentation"
FnRetThunkExtern => "fn_ret_thunk_extern"
HybridPatchable => "hybrid_patchable"
InlineHint => "inlinehint"
JumpTable => "jumptable"
Memory(i) => "memory(\{i})"
MinSize => "minsize"
Naked => "naked"
NoBuiltin => "nobuiltin"
NoCallback => "nocallback"
NoDivergenceSource => "nodivergence_source"
NoDuplicate => "noduplicate"
NoFree => "nofree"
NoImplicitFloat => "noimplicitfloat"
NonLazyBind => "nonlazybind"
NoMerge => "nomerge"
NoRecurse => "norecurse"
NoRedZone => "noredzone"
NoReturn => "noreturn"
NoSync => "nosync"
NoCfCheck => "nocfcheck"
NoProfile => "noprofile"
SkipProfile => "skipprofile"
NoUnwind => "nounwind"
NoSanitizeBounds => "no_sanitize_bounds"
NoSanitizeCoverage => "no_sanitize_coverage"
NullPointerIsValid => "null_pointer_is_valid"
OptimizeForDebugging => "optimize_for_debugging"
OptForFuzzing => "opt_for_fuzzing"
OptimizeForSize => "optimize_for_size"
OptimizeNone => "optimize_none"
Preallocated(ty) => "preallocated(\{ty})"
ReturnTwice => "return_twice"
SafeStack => "safestack"
ShadowCallStack => "shadow_call_stack"
StackAlignment(i) => "stack_alignment(\{i})"
Speculatable => "speculatable"
StackProtect => "stackprotect"
StackProtectReq => "stackprotectreq"
StackProtectStrong => "stackprotectstrong"
StrictFP => "strictfp"
SanitizeAddress => "sanitize_address"
SanitizeThread => "sanitize_thread"
SanitizeType => "sanitize_type"
SanitizeMemory => "sanitize_memory"
SanitizeHWAddress => "sanitize_hwaddress"
SanitizeMemTag => "sanitize_memtag"
SanitizeNumericalStability => "sanitize_numerical_stability"
SanitizeRealtime => "sanitize_realtime"
SanitizeRealtimeBlocking => "sanitize_realtime_blocking"
SpeculativeLoadHardening => "speculative_load_hardening"
UWTable(i) => "uwtable(\{i})"
VScaleRange(i) => "vscale_range(\{i})"
WillReturn => "will_return"
MustProgress => "must_progress"
PresplitCoroutine => "presplit_coroutine"
CoroDestroyOnlyWhenComplete => "coro_destroy_only_when_complete"
CoroElideSafe => "coro_elide_safe"
DenormalFPMath => "denormal_fpmath"
DenormalFPMathF32 => "denormal_fpmath_f32"
}
logger.write_string(str)
}
///|
pub impl Show for ParamAttr with output(self, logger) {
let str = match self {
Alignment(a) => "align(\{a})"
AllocAlign => "allocalign"
ByVal(t) => "byval(\{t})"
ByRef(t) => "byref(\{t})"
NoAlias => "noalias"
NonNull => "nonnull"
AllocatedPointer => "allocated_pointer"
NoUndef => "noundef"
Dereferenceable(i) => "dereferenceable(\{i})"
DereferenceableOrNull(i) => "dereferenceable_or_null(\{i})"
ElementType(ty) => "element_type(\{ty})"
InAlloca(ty) => "inalloca(\{ty})"
Initializes => "initializes"
InReg => "inreg"
NoFPClass => "nofpclass"
Nest => "nest"
Captures => "captures"
NoExt => "noext"
NoFree => "nofree"
DeadOnUnwind => "dead_on_unwind"
Preallocated(ty) => "preallocated(\{ty})"
Range => "range"
ReadNone => "readnone"
ReadOnly => "readonly"
Returned => "returned"
ImmArg => "immarg"
SExt => "sext"
StackAlignment(i) => "stack_alignment(\{i})"
StructRet => "structret"
SwiftError => "swift_error"
SwiftSelf => "swift_self"
SwiftAsync => "swift_async"
Writable => "writable"
WriteOnly => "writeonly"
ZExt => "zext"
}
logger.write_string(str)
}
///|
pub impl Show for RetAttr with output(self, logger) {
let str = match self {
Alignment(a) => "align(\{a})"
NoUndef => "noundef"
Dereferenceable(i) => "dereferenceable(\{i})"
DereferenceableOrNull(i) => "dereferenceable_or_null(\{i})"
InReg => "inreg"
NoFPClass => "nofpclass"
NoAlias => "noalias"
NoExt => "noext"
NonNull => "nonnull"
SExt => "sext"
StackAlignment(i) => "stack_alignment(\{i})"
ZExt => "zext"
}
logger.write_string(str)
}
///|
struct AttributeSet {
fnAttrs : Set[FnAttr]
paramAttrs : Map[UInt, Set[ParamAttr]]
retAttrs : Set[RetAttr]
}
///|
fn AttributeSet::new() -> AttributeSet {
AttributeSet::{
fnAttrs: Set::new(),
paramAttrs: Map::new(),
retAttrs: Set::new(),
}
}