Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions src/device/exceptions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,33 +65,34 @@ end
return
end

macro gpu_throw(reason)
code = _reason_to_code(reason)
# throw a device-side exception of type `name`. only the type is reported: the exception
# info only has room for an error code, so `reason` is dropped.
macro gputhrow(name::String, reason::String)
code = _name_to_code(name)
quote
ei = kernel_state().exception_info
signal_exception!(ei, $code)
throw(nothing) # unreachable, but keeps Julia's type system happy
end
end

# Map reason strings to error codes at macro expansion time
function _reason_to_code(reason::String)
if startswith(reason, "BoundsError")
# Map exception type names to error codes at macro expansion time
function _name_to_code(name::String)
if name == "BoundsError"
ExceptionCode.BOUNDS_ERROR
elseif startswith(reason, "DomainError")
elseif name == "DomainError"
ExceptionCode.DOMAIN_ERROR
elseif startswith(reason, "OverflowError")
elseif name == "OverflowError"
ExceptionCode.OVERFLOW_ERROR
elseif startswith(reason, "InexactError")
elseif name == "InexactError"
ExceptionCode.INEXACT_ERROR
elseif startswith(reason, "ArgumentError")
elseif name == "ArgumentError"
ExceptionCode.ARGUMENT_ERROR
elseif startswith(reason, "DivideError")
elseif name == "DivideError"
ExceptionCode.DIVIDE_ERROR
elseif startswith(reason, "DimensionMismatch")
elseif name == "DimensionMismatch"
ExceptionCode.DIM_MISMATCH
else
ExceptionCode.UNKNOWN
end
end
_reason_to_code(reason) = ExceptionCode.UNKNOWN
38 changes: 17 additions & 21 deletions src/device/quirks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,48 @@

# math.jl
@device_override Base.Math.throw_complex_domainerror(f::Symbol, x) =
@gpu_throw "DomainError: This operation requires a complex input to return a complex result"
@device_override Base.Math.throw_exp_domainerror(f::Symbol, x) =
@gpu_throw "DomainError: Exponentiation yielding a complex result requires a complex argument"
@gputhrow "DomainError" "This operation requires a complex input to return a complex result"

# intfuncs.jl
@device_override Base.throw_domerr_powbysq(::Any, p) =
@gpu_throw "DomainError: Cannot raise an integer to a negative power"
@gputhrow "DomainError" "Cannot raise an integer to a negative power"
@device_override Base.throw_domerr_powbysq(::Integer, p) =
@gpu_throw "DomainError: Cannot raise an integer to a negative power"
@gputhrow "DomainError" "Cannot raise an integer to a negative power"
@device_override Base.throw_domerr_powbysq(::AbstractMatrix, p) =
@gpu_throw "DomainError: Cannot raise an integer to a negative power"
@gputhrow "DomainError" "Cannot raise an integer to a negative power"
@device_override Base.__throw_gcd_overflow(a, b) =
@gpu_throw "OverflowError: GCD overflow"
@gputhrow "OverflowError" "GCD overflow"

# checked.jl
@device_override Base.Checked.throw_overflowerr_binaryop(op, x, y) =
@gpu_throw "OverflowError: Binary operation overflowed"
@device_override Base.Checked.throw_overflowerr_negation(op, x, y) =
@gpu_throw "OverflowError: Negation overflowed"
@gputhrow "OverflowError" "Binary operation overflowed"
@device_override function Base.Checked.checked_abs(x::Base.Checked.SignedInt)
r = ifelse(x < 0, -x, x)
r < 0 && @gpu_throw "OverflowError: checked arithmetic: cannot compute |x|"
r < 0 && @gputhrow "OverflowError" "checked arithmetic: cannot compute |x|"
r
end

# boot.jl
@device_override Core.throw_inexacterror(f::Symbol, ::Type{T}, val) where {T} =
throw(nothing)
# @gpu_throw "InexactError: Inexact conversion"
# @gputhrow "InexactError" "Inexact conversion"
# FIXME: https://github.com/JuliaGPU/AMDGPU.jl/issues/808

# abstractarray.jl
@device_override Base.throw_boundserror(A, I) =
@gpu_throw "BoundsError: Out-of-bounds array access"
@gputhrow "BoundsError" "Out-of-bounds array access"

# trig.jl
@device_override Base.Math.sincos_domain_error(x) =
@gpu_throw "DomainError: sincos(x) is only defined for finite x"
@gputhrow "DomainError" "sincos(x) is only defined for finite x"

# Bodies copied from Base (`base/special/trig.jl`) with the inline `DomainError`
# throw replaced: boxing its untyped `val` field emits a device-side allocation.
# Provisional: JuliaLang/julia#62842 adds `Base.Math.sind_domain_error`, after
# which these collapse to two overrides, once the compat floor reaches 1.14.
@device_override function Base.Math.sind(x::Real)
if isinf(x)
@gpu_throw "DomainError: sind(x) is only defined for finite x"
@gputhrow "DomainError" "sind(x) is only defined for finite x"
elseif isnan(x)
return x
end
Expand Down Expand Up @@ -78,7 +74,7 @@ end

@device_override function Base.Math.cosd(x::Real)
if isinf(x)
@gpu_throw "DomainError: cosd(x) is only defined for finite x"
@gputhrow "DomainError" "cosd(x) is only defined for finite x"
elseif isnan(x)
return x
end
Expand Down Expand Up @@ -119,13 +115,13 @@ end
ref::R, step::S, len::Integer, offset::Integer=1,
) where {T,R,S,L}
if T <: Integer && !isinteger(ref + step)
@gpu_throw "ArgumentError: StepRangeLen{<:Integer} cannot have non-integer step"
@gputhrow "ArgumentError" "StepRangeLen{<:Integer} cannot have non-integer step"
end
len = convert(L, len)
len >= zero(len) || @gpu_throw "ArgumentError: StepRangeLen length cannot be negative"
len >= zero(len) || @gputhrow "ArgumentError" "StepRangeLen length cannot be negative"
offset = convert(L, offset)
L1 = oneunit(typeof(len))
L1 <= offset <= max(L1, len) || @gpu_throw "ArgumentError: StepRangeLen: offset must be in [1,...]"
L1 <= offset <= max(L1, len) || @gputhrow "ArgumentError" "StepRangeLen: offset must be in [1,...]"
$(Expr(:new, :(StepRangeLen{T,R,S,L}), :ref, :step, :len, :offset))
end
end
Expand All @@ -138,11 +134,11 @@ end
if i == j
@inbounds D.diag[i] = v
elseif !iszero(v)
@gpu_throw "ArgumentError: Cannot set off-diagonal entry to a nonzero value"
@gputhrow "ArgumentError" "Cannot set off-diagonal entry to a nonzero value"
end
return v
end

# TODO remove once we support strings/exceptions.
@device_override Base._throw_dmrs(n, str, dims) =
@gpu_throw "DimensionMismatch: Dimensions mismatch when reshaping. New dimensions must be consistent with array size"
@gputhrow "DimensionMismatch" "Dimensions mismatch when reshaping. New dimensions must be consistent with array size"
Loading