Convert arithmetic operations to intrinsics (#2464)
Convert arithmetic operations from C++ functions to intrinsics
This commit is contained in:
+1
-1
@@ -14,7 +14,7 @@ internal fun CommonBackendContext.reportCompilationError(message: String, irFile
|
||||
throw KonanCompilationException()
|
||||
}
|
||||
|
||||
internal fun CommonBackendContext.reportCompilationError(message: String) {
|
||||
internal fun CommonBackendContext.reportCompilationError(message: String): Nothing {
|
||||
report(null, null, message, true)
|
||||
throw KonanCompilationException()
|
||||
}
|
||||
|
||||
+4
-2
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.binaryTypeIsReference
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.ConstructorDescriptor
|
||||
@@ -17,7 +16,6 @@ import org.jetbrains.kotlin.backend.konan.isInlined
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
|
||||
/**
|
||||
@@ -81,6 +79,10 @@ internal fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction {
|
||||
internal val FunctionDescriptor.isIntrinsic: Boolean
|
||||
get() = this.descriptor.isIntrinsic
|
||||
|
||||
// TODO: Merge with `isIntrinsic`
|
||||
internal val FunctionDescriptor.isTypedIntrinsic: Boolean
|
||||
get() = this.descriptor.isTypedIntrinsic
|
||||
|
||||
internal val DeclarationDescriptor.isFrozen: Boolean
|
||||
get() = this.descriptor.isFrozen
|
||||
|
||||
|
||||
+7
-1
@@ -239,6 +239,7 @@ fun CallableMemberDescriptor.findSourceFile(): SourceFile {
|
||||
}
|
||||
}
|
||||
|
||||
internal val TypedIntrinsic = FqName("kotlin.native.internal.TypedIntrinsic")
|
||||
private val intrinsicAnnotation = FqName("kotlin.native.internal.Intrinsic")
|
||||
private val symbolNameAnnotation = FqName("kotlin.native.SymbolName")
|
||||
private val objCMethodAnnotation = FqName("kotlinx.cinterop.ObjCMethod")
|
||||
@@ -253,6 +254,9 @@ internal val DeclarationDescriptor.isFrozen: Boolean
|
||||
internal val FunctionDescriptor.isIntrinsic: Boolean
|
||||
get() = this.annotations.hasAnnotation(intrinsicAnnotation)
|
||||
|
||||
internal val FunctionDescriptor.isTypedIntrinsic: Boolean
|
||||
get() = this.annotations.hasAnnotation(TypedIntrinsic)
|
||||
|
||||
// TODO: coalesce all our annotation value getters into fewer functions.
|
||||
fun getAnnotationValue(annotation: AnnotationDescriptor): String? {
|
||||
return annotation.allValueArguments.values.ifNotEmpty {
|
||||
@@ -269,5 +273,7 @@ fun CallableMemberDescriptor.externalSymbolOrThrow(): String? {
|
||||
|
||||
if (this.annotations.hasAnnotation(objCMethodAnnotation)) return null
|
||||
|
||||
throw Error("external function ${this} must have @SymbolName, @Intrinsic or @ObjCMethod annotation")
|
||||
if (this.annotations.hasAnnotation(TypedIntrinsic)) return null
|
||||
|
||||
throw Error("external function ${this} must have @TypedIntrinsic, @SymbolName, @Intrinsic or @ObjCMethod annotation")
|
||||
}
|
||||
|
||||
+3
@@ -260,6 +260,9 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
||||
|
||||
override val areEqual get() = error("Must not be used")
|
||||
|
||||
val throwArithmeticException = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("ThrowArithmeticException").single())
|
||||
|
||||
override val ThrowNullPointerException = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("ThrowNullPointerException").single())
|
||||
|
||||
|
||||
+10
@@ -481,6 +481,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
fun icmpLt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLT, arg0, arg1, name)!!
|
||||
fun icmpLe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLE, arg0, arg1, name)!!
|
||||
fun icmpNe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntNE, arg0, arg1, name)!!
|
||||
fun icmpULt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntULT, arg0, arg1, name)!!
|
||||
fun icmpUGt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntUGT, arg0, arg1, name)!!
|
||||
|
||||
/* floating-point comparisons */
|
||||
@@ -490,6 +491,15 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
fun fcmpLt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOLT, arg0, arg1, name)!!
|
||||
fun fcmpLe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOLE, arg0, arg1, name)!!
|
||||
|
||||
fun sub(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildSub(builder, arg0, arg1, name)!!
|
||||
fun add(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildAdd(builder, arg0, arg1, name)!!
|
||||
|
||||
fun fsub(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFSub(builder, arg0, arg1, name)!!
|
||||
fun fadd(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFAdd(builder, arg0, arg1, name)!!
|
||||
|
||||
fun select(ifValue: LLVMValueRef, thenValue: LLVMValueRef, elseValue: LLVMValueRef, name: String = ""): LLVMValueRef =
|
||||
LLVMBuildSelect(builder, ifValue, thenValue, elseValue, name)!!
|
||||
|
||||
fun bitcast(type: LLVMTypeRef?, value: LLVMValueRef, name: String = "") = LLVMBuildBitCast(builder, value, type, name)!!
|
||||
|
||||
fun intToPtr(value: LLVMValueRef?, DestTy: LLVMTypeRef, Name: String = "") = LLVMBuildIntToPtr(builder, value, DestTy, Name)!!
|
||||
|
||||
+300
@@ -0,0 +1,300 @@
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.TypedIntrinsic
|
||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
private enum class IntrinsicType {
|
||||
PLUS,
|
||||
MINUS,
|
||||
TIMES,
|
||||
SIGNED_DIV,
|
||||
SIGNED_REM,
|
||||
UNSIGNED_DIV,
|
||||
UNSIGNED_REM,
|
||||
INC,
|
||||
DEC,
|
||||
UNARY_PLUS,
|
||||
UNARY_MINUS,
|
||||
SHL,
|
||||
SHR,
|
||||
USHR,
|
||||
AND,
|
||||
OR,
|
||||
XOR,
|
||||
INV,
|
||||
SIGN_EXTEND,
|
||||
ZERO_EXTEND,
|
||||
INT_TRUNCATE,
|
||||
FLOAT_TRUNCATE,
|
||||
FLOAT_EXTEND,
|
||||
SIGNED_TO_FLOAT,
|
||||
UNSIGNED_TO_FLOAT,
|
||||
FLOAT_TO_SIGNED,
|
||||
SIGNED_COMPARE_TO,
|
||||
UNSIGNED_COMPARE_TO,
|
||||
NOT,
|
||||
TO_BITS,
|
||||
FROM_BITS
|
||||
}
|
||||
|
||||
internal class IntrinsicGenerator(val codegen: CodeGenerator) {
|
||||
|
||||
private val context = codegen.context
|
||||
|
||||
private val IrCall.llvmReturnType: LLVMTypeRef
|
||||
get() = LLVMGetReturnType(codegen.getLlvmFunctionType(symbol.owner))!!
|
||||
|
||||
private fun getIntrinsicType(callSite: IrCall): IntrinsicType {
|
||||
val function = callSite.symbol.owner
|
||||
val annotation = function.descriptor.annotations.findAnnotation(TypedIntrinsic)!!
|
||||
val value = annotation.allValueArguments[Name.identifier("kind")]!!.value as String
|
||||
return IntrinsicType.valueOf(value)
|
||||
}
|
||||
|
||||
fun evaluateCall(callSite: IrCall, args: List<LLVMValueRef>, generationContext: FunctionGenerationContext, exceptionHandler: ExceptionHandler): LLVMValueRef =
|
||||
generationContext.evaluateCall(callSite, args, exceptionHandler)
|
||||
|
||||
// Assuming that we checked for `TypedIntrinsic` annotation presence.
|
||||
private fun FunctionGenerationContext.evaluateCall(callSite: IrCall, args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||
val result = when (getIntrinsicType(callSite)) {
|
||||
IntrinsicType.PLUS -> emitPlus(args)
|
||||
IntrinsicType.MINUS -> emitMinus(args)
|
||||
IntrinsicType.TIMES -> emitTimes(args)
|
||||
IntrinsicType.SIGNED_DIV -> emitSignedDiv(args, exceptionHandler)
|
||||
IntrinsicType.SIGNED_REM -> emitSignedRem(args, exceptionHandler)
|
||||
IntrinsicType.UNSIGNED_DIV -> emitUnsignedDiv(args, exceptionHandler)
|
||||
IntrinsicType.UNSIGNED_REM -> emitUnsignedRem(args, exceptionHandler)
|
||||
IntrinsicType.INC -> emitInc(args)
|
||||
IntrinsicType.DEC -> emitDec(args)
|
||||
IntrinsicType.UNARY_PLUS -> emitUnaryPlus(args)
|
||||
IntrinsicType.UNARY_MINUS -> emitUnaryMinus(args)
|
||||
IntrinsicType.SHL -> emitShl(args)
|
||||
IntrinsicType.SHR -> emitShr(args)
|
||||
IntrinsicType.USHR -> emitUshr(args)
|
||||
IntrinsicType.AND -> emitAnd(args)
|
||||
IntrinsicType.OR -> emitOr(args)
|
||||
IntrinsicType.XOR -> emitXor(args)
|
||||
IntrinsicType.INV -> emitInv(args)
|
||||
IntrinsicType.SIGNED_COMPARE_TO -> emitSignedCompareTo(args)
|
||||
IntrinsicType.UNSIGNED_COMPARE_TO -> emitUnsignedCompareTo(args)
|
||||
IntrinsicType.NOT -> emitNot(args)
|
||||
IntrinsicType.FROM_BITS -> emitReinterpret(callSite, args)
|
||||
IntrinsicType.TO_BITS -> emitReinterpret(callSite, args)
|
||||
IntrinsicType.SIGN_EXTEND -> emitSignExtend(callSite, args)
|
||||
IntrinsicType.ZERO_EXTEND -> emitZeroExtend(callSite, args)
|
||||
IntrinsicType.INT_TRUNCATE -> emitIntTruncate(callSite, args)
|
||||
IntrinsicType.SIGNED_TO_FLOAT -> emitSignedToFloat(callSite, args)
|
||||
IntrinsicType.UNSIGNED_TO_FLOAT -> emitUnsignedToFloat(callSite, args)
|
||||
IntrinsicType.FLOAT_TO_SIGNED -> emitFloatToSigned(callSite, args)
|
||||
IntrinsicType.FLOAT_EXTEND -> emitFloatExtend(callSite, args)
|
||||
IntrinsicType.FLOAT_TRUNCATE -> emitFloatTruncate(callSite, args)
|
||||
}
|
||||
assert(result.type == callSite.llvmReturnType) {
|
||||
"Substitution of ${callSite.symbol.owner.functionName} has wrong result type"
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitReinterpret(callSite: IrCall, args: List<LLVMValueRef>) =
|
||||
bitcast(callSite.llvmReturnType, args[0])
|
||||
|
||||
private fun FunctionGenerationContext.emitNot(args: List<LLVMValueRef>) =
|
||||
not(args[0])
|
||||
|
||||
private fun FunctionGenerationContext.emitPlus(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
return if (first.type.isFloatingPoint()) {
|
||||
fadd(first, second)
|
||||
} else {
|
||||
add(first, second)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitSignExtend(callSite: IrCall, args: List<LLVMValueRef>) =
|
||||
sext(args[0], callSite.llvmReturnType)
|
||||
|
||||
private fun FunctionGenerationContext.emitZeroExtend(callSite: IrCall, args: List<LLVMValueRef>) =
|
||||
zext(args[0], callSite.llvmReturnType)
|
||||
|
||||
private fun FunctionGenerationContext.emitIntTruncate(callSite: IrCall, args: List<LLVMValueRef>) =
|
||||
trunc(args[0], callSite.llvmReturnType)
|
||||
|
||||
private fun FunctionGenerationContext.emitSignedToFloat(callSite: IrCall, args: List<LLVMValueRef>) =
|
||||
LLVMBuildSIToFP(builder, args[0], callSite.llvmReturnType, "")!!
|
||||
|
||||
private fun FunctionGenerationContext.emitUnsignedToFloat(callSite: IrCall, args: List<LLVMValueRef>) =
|
||||
LLVMBuildUIToFP(builder, args[0], callSite.llvmReturnType, "")!!
|
||||
|
||||
private fun FunctionGenerationContext.emitFloatToSigned(callSite: IrCall, args: List<LLVMValueRef>) =
|
||||
LLVMBuildFPToSI(builder, args[0], callSite.llvmReturnType, "")!!
|
||||
|
||||
private fun FunctionGenerationContext.emitFloatExtend(callSite: IrCall, args: List<LLVMValueRef>) =
|
||||
LLVMBuildFPExt(builder, args[0], callSite.llvmReturnType, "")!!
|
||||
|
||||
private fun FunctionGenerationContext.emitFloatTruncate(callSite: IrCall, args: List<LLVMValueRef>) =
|
||||
LLVMBuildFPTrunc(builder, args[0], callSite.llvmReturnType, "")!!
|
||||
|
||||
private fun FunctionGenerationContext.emitShift(op: LLVMOpcode, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
val shift = if (first.type == int64Type) {
|
||||
val tmp = and(second, Int32(63).llvm)
|
||||
zext(tmp, int64Type)
|
||||
} else {
|
||||
and(second, Int32(31).llvm)
|
||||
}
|
||||
return LLVMBuildBinOp(builder, op, first, shift, "")!!
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitShl(args: List<LLVMValueRef>) =
|
||||
emitShift(LLVMOpcode.LLVMShl, args)
|
||||
|
||||
private fun FunctionGenerationContext.emitShr(args: List<LLVMValueRef>) =
|
||||
emitShift(LLVMOpcode.LLVMAShr, args)
|
||||
|
||||
private fun FunctionGenerationContext.emitUshr(args: List<LLVMValueRef>) =
|
||||
emitShift(LLVMOpcode.LLVMLShr, args)
|
||||
|
||||
private fun FunctionGenerationContext.emitAnd(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
return and(first, second)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitOr(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
return or(first, second)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitXor(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
return xor(first, second)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitInv(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val first = args[0]
|
||||
val mask = makeConstOfType(first.type, -1)
|
||||
return xor(first, mask)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitMinus(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
return if (first.type.isFloatingPoint()) {
|
||||
fsub(first, second)
|
||||
} else {
|
||||
sub(first, second)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitTimes(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
return if (first.type.isFloatingPoint()) {
|
||||
LLVMBuildFMul(builder, first, second, "")
|
||||
} else {
|
||||
LLVMBuildMul(builder, first, second, "")
|
||||
}!!
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitThrowIfZero(divider: LLVMValueRef, exceptionHandler: ExceptionHandler) {
|
||||
ifThen(icmpEq(divider, Zero(divider.type).llvm)) {
|
||||
val throwArithExc = codegen.llvmFunction(context.ir.symbols.throwArithmeticException.owner)
|
||||
call(throwArithExc, emptyList(), Lifetime.GLOBAL, exceptionHandler)
|
||||
unreachable()
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitSignedDiv(args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
if (!second.type.isFloatingPoint()) {
|
||||
emitThrowIfZero(second, exceptionHandler)
|
||||
}
|
||||
return if (first.type.isFloatingPoint()) {
|
||||
LLVMBuildFDiv(builder, first, second, "")
|
||||
} else {
|
||||
LLVMBuildSDiv(builder, first, second, "")
|
||||
}!!
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitSignedRem(args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
if (!second.type.isFloatingPoint()) {
|
||||
emitThrowIfZero(second, exceptionHandler)
|
||||
}
|
||||
return if (first.type.isFloatingPoint()) {
|
||||
LLVMBuildFRem(builder, first, second, "")
|
||||
} else {
|
||||
LLVMBuildSRem(builder, first, second, "")
|
||||
}!!
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitUnsignedDiv(args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
emitThrowIfZero(second, exceptionHandler)
|
||||
return LLVMBuildUDiv(builder, first, second, "")!!
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitUnsignedRem(args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
emitThrowIfZero(second, exceptionHandler)
|
||||
return LLVMBuildURem(builder, first, second, "")!!
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitInc(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val first = args[0]
|
||||
val const1 = makeConstOfType(first.type, 1)
|
||||
return if (first.type.isFloatingPoint()) {
|
||||
fadd(first, const1)
|
||||
} else {
|
||||
add(first, const1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitDec(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val first = args[0]
|
||||
val const1 = makeConstOfType(first.type, 1)
|
||||
return if (first.type.isFloatingPoint()) {
|
||||
fsub(first, const1)
|
||||
} else {
|
||||
sub(first, const1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitUnaryPlus(args: List<LLVMValueRef>) =
|
||||
args[0]
|
||||
|
||||
private fun FunctionGenerationContext.emitUnaryMinus(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val first = args[0]
|
||||
val destTy = first.type
|
||||
val const0 = makeConstOfType(destTy, 0)
|
||||
return if (destTy.isFloatingPoint()) {
|
||||
fsub(const0, first)
|
||||
} else {
|
||||
sub(const0, first)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitCompareTo(args: List<LLVMValueRef>, signed: Boolean): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
val equal = icmpEq(first, second)
|
||||
val less = if (signed) icmpLt(first, second) else icmpULt(first, second)
|
||||
val tmp = select(less, Int32(-1).llvm, Int32(1).llvm)
|
||||
return select(equal, Int32(0).llvm, tmp)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitSignedCompareTo(args: List<LLVMValueRef>) =
|
||||
emitCompareTo(args, signed = true)
|
||||
|
||||
private fun FunctionGenerationContext.emitUnsignedCompareTo(args: List<LLVMValueRef>) =
|
||||
emitCompareTo(args, signed = false)
|
||||
|
||||
private fun makeConstOfType(type: LLVMTypeRef, value: Int): LLVMValueRef = when (type) {
|
||||
int8Type -> Int8(value.toByte()).llvm
|
||||
int16Type -> Char16(value.toChar()).llvm
|
||||
int32Type -> Int32(value).llvm
|
||||
int64Type -> Int64(value.toLong()).llvm
|
||||
floatType -> Float32(value.toFloat()).llvm
|
||||
doubleType -> Float64(value.toDouble()).llvm
|
||||
else -> context.reportCompilationError("Unexpected primitive type: $type")
|
||||
}
|
||||
}
|
||||
+15
-21
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.hasBackingField
|
||||
|
||||
private val threadLocalAnnotationFqName = FqName("kotlin.native.ThreadLocal")
|
||||
private val sharedAnnotationFqName = FqName("kotlin.native.SharedImmutable")
|
||||
@@ -292,6 +291,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
val codegen = CodeGenerator(context)
|
||||
|
||||
val intrinsicGenerator = IntrinsicGenerator(codegen)
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
// TODO: consider eliminating mutable state
|
||||
@@ -720,6 +721,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
context.log{"visitFunction : ${ir2string(declaration)}"}
|
||||
|
||||
val body = declaration.body
|
||||
|
||||
if (declaration.descriptor.modality == Modality.ABSTRACT) return
|
||||
@@ -1846,12 +1848,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val args = evaluateExplicitArgs(value)
|
||||
|
||||
updateBuilderDebugLocation(value)
|
||||
when {
|
||||
value is IrDelegatingConstructorCall ->
|
||||
return delegatingConstructorCall(value.symbol.owner, args)
|
||||
|
||||
else ->
|
||||
return evaluateFunctionCall(value as IrCall, args, resultLifetime(value))
|
||||
return when (value) {
|
||||
is IrDelegatingConstructorCall -> delegatingConstructorCall(value.symbol.owner, args)
|
||||
else -> evaluateFunctionCall(value as IrCall, args, resultLifetime(value))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2092,23 +2091,17 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateFunctionCall(callee: IrCall, args: List<LLVMValueRef>,
|
||||
resultLifetime: Lifetime): LLVMValueRef {
|
||||
val descriptor = callee.symbol.owner
|
||||
val function = callee.symbol.owner
|
||||
|
||||
val argsWithContinuationIfNeeded = if (descriptor.isSuspend)
|
||||
val argsWithContinuationIfNeeded = if (function.isSuspend)
|
||||
args + getContinuation()
|
||||
else args
|
||||
if (descriptor.isIntrinsic) {
|
||||
return evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded)
|
||||
}
|
||||
|
||||
when {
|
||||
descriptor.origin == IrDeclarationOrigin.IR_BUILTINS_STUB ->
|
||||
return evaluateOperatorCall(callee, argsWithContinuationIfNeeded)
|
||||
|
||||
descriptor is ConstructorDescriptor -> return evaluateConstructorCall(callee, argsWithContinuationIfNeeded)
|
||||
|
||||
else -> return evaluateSimpleFunctionCall(
|
||||
descriptor, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner)
|
||||
return when {
|
||||
function.isTypedIntrinsic -> intrinsicGenerator.evaluateCall(callee, args, functionGenerationContext, currentCodeContext.exceptionHandler)
|
||||
function.isIntrinsic -> evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded)
|
||||
function.origin == IrDeclarationOrigin.IR_BUILTINS_STUB -> evaluateOperatorCall(callee, argsWithContinuationIfNeeded)
|
||||
function is ConstructorDescriptor -> evaluateConstructorCall(callee, argsWithContinuationIfNeeded)
|
||||
else -> evaluateSimpleFunctionCall(function, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2207,6 +2200,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
// TODO: Move to [IntrinsicsGenerator]
|
||||
private fun evaluateIntrinsicCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val descriptor = callee.descriptor.original
|
||||
val function = callee.symbol.owner
|
||||
|
||||
+1
-1
@@ -398,7 +398,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
}
|
||||
|
||||
val llvmFunction = if (descriptor.isExternal) {
|
||||
if (descriptor.isIntrinsic || descriptor.isObjCBridgeBased()) {
|
||||
if (descriptor.isTypedIntrinsic || descriptor.isIntrinsic || descriptor.isObjCBridgeBased()) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -91,6 +91,14 @@ internal class Int64(val value: Long) : ConstValue {
|
||||
override val llvm = LLVMConstInt(LLVMInt64Type(), value, 1)!!
|
||||
}
|
||||
|
||||
internal class Float32(val value: Float) : ConstValue {
|
||||
override val llvm = LLVMConstReal(LLVMFloatType(), value.toDouble())!!
|
||||
}
|
||||
|
||||
internal class Float64(val value: Double) : ConstValue {
|
||||
override val llvm = LLVMConstReal(LLVMDoubleType(), value)!!
|
||||
}
|
||||
|
||||
internal class Zero(val type: LLVMTypeRef) : ConstValue {
|
||||
override val llvm = LLVMConstNull(type)!!
|
||||
}
|
||||
@@ -113,6 +121,8 @@ internal val int16Type = LLVMInt16Type()!!
|
||||
internal val int32Type = LLVMInt32Type()!!
|
||||
internal val int64Type = LLVMInt64Type()!!
|
||||
internal val int8TypePtr = pointerType(int8Type)
|
||||
internal val floatType = LLVMFloatType()!!
|
||||
internal val doubleType = LLVMDoubleType()!!
|
||||
|
||||
internal val voidType = LLVMVoidType()!!
|
||||
|
||||
|
||||
@@ -1048,6 +1048,19 @@ task initializers_correctOrder2(type: RunKonanTest) {
|
||||
source = "codegen/initializers/correctOrder2.kt"
|
||||
}
|
||||
|
||||
task arithmetic_basic(type: RunKonanTest) {
|
||||
source = "codegen/arithmetic/basic.kt"
|
||||
}
|
||||
|
||||
task arithmetic_division(type: RunKonanTest) {
|
||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||
source = "codegen/arithmetic/division.kt"
|
||||
}
|
||||
|
||||
task arithmetic_github1856(type: RunKonanTest) {
|
||||
source = "codegen/arithmetic/github1856.kt"
|
||||
}
|
||||
|
||||
task bridges_test0(type: RunKonanTest) {
|
||||
goldValue = "42\n42\n"
|
||||
source = "codegen/bridges/test0.kt"
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package codegen.arithmetic.basic
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
// Check that compiler doesn't optimize it to `true`
|
||||
fun selfCmp1(x: Int) = x + 1 > x
|
||||
|
||||
fun selfCmp2(x: Int) = x - 1 < x
|
||||
|
||||
@Test
|
||||
fun selfComparison() {
|
||||
assertFalse(selfCmp1(Int.MAX_VALUE))
|
||||
assertFalse(selfCmp2(Int.MIN_VALUE))
|
||||
}
|
||||
|
||||
private fun charCornersMinus(): Int {
|
||||
val a: Char = 0xFFFF.toChar()
|
||||
val b: Char = 0.toChar()
|
||||
return a - b
|
||||
}
|
||||
|
||||
private fun charCornersComparison(): Boolean {
|
||||
val a = 0xFFFF.toChar()
|
||||
val b = 0.toChar()
|
||||
return a < b
|
||||
}
|
||||
|
||||
@Test
|
||||
fun charCornerCases() {
|
||||
assertEquals(65535, charCornersMinus())
|
||||
assertFalse(charCornersComparison())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shifts() {
|
||||
assertEquals(-2147483648, 1 shl -1)
|
||||
assertEquals(0, 1 shr -1)
|
||||
assertEquals(1, 1 shl 32)
|
||||
assertEquals(1073741823, -1 ushr 2)
|
||||
assertEquals(-1, -1 shr 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
@kotlin.ExperimentalUnsignedTypes
|
||||
fun uintTests() {
|
||||
assertEquals(UInt.MAX_VALUE, UInt.MIN_VALUE - 1u)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun charConversions() {
|
||||
assertEquals(97.0, 'a'.toDouble())
|
||||
assertEquals(-1, Char.MAX_VALUE.toShort())
|
||||
assertEquals(32768, Short.MIN_VALUE.toChar().toInt())
|
||||
assertEquals(-1, Char.MAX_VALUE.toByte())
|
||||
assertEquals(65408, Byte.MIN_VALUE.toChar().toInt())
|
||||
assertEquals(0, Float.MIN_VALUE.toChar().toInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleBasic() {
|
||||
assertEquals(1, 0f.compareTo(-0f))
|
||||
assertEquals(1, 0.0.compareTo(-0.0))
|
||||
|
||||
assertEquals(1.0, Double.fromBits(1.0.toBits()))
|
||||
assertEquals(1.0f, Float.fromBits(1.0f.toBits()))
|
||||
|
||||
assertEquals(Double.NaN, Double.fromBits((0 / 0.0).toBits()))
|
||||
assertEquals(Float.NaN, Float.fromBits((0 / 0f).toBits()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun integralToFloat() {
|
||||
assertEquals(9.223372E18f, Long.MAX_VALUE.toFloat())
|
||||
assertEquals(-9.223372E18f, Long.MIN_VALUE.toFloat())
|
||||
|
||||
assertEquals(-2.147483648E9, Int.MIN_VALUE.toDouble())
|
||||
assertEquals(2.147483647E9, Int.MAX_VALUE.toDouble())
|
||||
|
||||
assertEquals(2147483647, Double.MAX_VALUE.toInt())
|
||||
assertEquals(0, Float.MIN_VALUE.toLong())
|
||||
|
||||
assertEquals(9223372036854775807, Float.MAX_VALUE.toLong())
|
||||
assertEquals(0, Double.MIN_VALUE.toInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun compareIntToFloat() {
|
||||
assertEquals(1, 0.compareTo(-0.0f))
|
||||
assertEquals(0, 0.compareTo(+0.0f))
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package codegen.arithmetic.division
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
@Test
|
||||
fun divisionByZero() {
|
||||
assertFailsWith(ArithmeticException::class, { 5 / 0 })
|
||||
assertFailsWith(ArithmeticException::class, { 5 % 0 })
|
||||
assertEquals(1, 5 / try { 0 / 0; 1 } catch (e: ArithmeticException) { 5 })
|
||||
assertEquals(Double.NaN, 0.0 / 0.0)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package codegen.arithmetic.github1856
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
object RGBA {
|
||||
fun packFast(r: Int, g: Int, b: Int, a: Int) = (r shl 0) or (g shl 8) or (b shl 16) or (a shl 24)
|
||||
|
||||
fun getFastR(v: Int): Int = (v ushr 0) and 0xFF
|
||||
fun getFastG(v: Int): Int = (v ushr 8) and 0xFF
|
||||
fun getFastB(v: Int): Int = (v ushr 16) and 0xFF
|
||||
fun getFastA(v: Int): Int = (v ushr 24) and 0xFF
|
||||
|
||||
fun premultiplyFastInt(v: Int): Int {
|
||||
val A = getFastA(v) + 1
|
||||
val RB = (((v and 0x00FF00FF) * A) ushr 8) and 0x00FF00FF
|
||||
val G = (((v and 0x0000FF00) * A) ushr 8) and 0x0000FF00
|
||||
return (v and 0x00FFFFFF.inv()) or RB or G
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun main() {
|
||||
val source = listOf(0xFFFFFFFF.toInt(), 0xFFFFFF77.toInt(), 0x777777FF.toInt(), 0x77777777.toInt())
|
||||
val expect = listOf(-1, -137, 2000107383, 2000107319)
|
||||
assertEquals(expect, source.map { RGBA.premultiplyFastInt(it) })
|
||||
}
|
||||
@@ -19,431 +19,52 @@
|
||||
|
||||
#include "DoubleConversions.h"
|
||||
#include "Natives.h"
|
||||
#include "Exceptions.h"
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename R, typename Ta, typename Tb> R div(Ta a, Tb b) {
|
||||
if (__builtin_expect(b == 0, false)) {
|
||||
ThrowArithmeticException();
|
||||
}
|
||||
return a / b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
//--- Boolean -----------------------------------------------------------------//
|
||||
|
||||
ALWAYS_INLINE KBoolean Kotlin_Boolean_not (KBoolean a ) { return !a; }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Boolean_and_Boolean (KBoolean a, KBoolean b) { return a && b; }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Boolean_or_Boolean (KBoolean a, KBoolean b) { return a || b; }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Boolean_xor_Boolean (KBoolean a, KBoolean b) { return a != b; }
|
||||
KInt Kotlin_Boolean_compareTo_Boolean(KBoolean a, KBoolean b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
|
||||
//--- Char --------------------------------------------------------------------//
|
||||
|
||||
KInt Kotlin_Char_compareTo_Char (KChar a, KChar b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
ALWAYS_INLINE KChar Kotlin_Char_plus_Int (KChar a, KInt b) { return a + b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Char_minus_Char (KChar a, KChar b) { return a - b; }
|
||||
ALWAYS_INLINE KChar Kotlin_Char_minus_Int (KChar a, KInt b) { return a - b; }
|
||||
ALWAYS_INLINE KChar Kotlin_Char_inc (KChar a ) { return a + 1; }
|
||||
ALWAYS_INLINE KChar Kotlin_Char_dec (KChar a ) { return a - 1; }
|
||||
|
||||
ALWAYS_INLINE KByte Kotlin_Char_toByte (KChar a ) { return a; }
|
||||
ALWAYS_INLINE KChar Kotlin_Char_toChar (KChar a ) { return a; }
|
||||
ALWAYS_INLINE KShort Kotlin_Char_toShort (KChar a ) { return a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Char_toInt (KChar a ) { return a; }
|
||||
ALWAYS_INLINE KLong Kotlin_Char_toLong (KChar a ) { return a; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Char_toFloat (KChar a ) { return a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Char_toDouble (KChar a ) { return a; }
|
||||
|
||||
//--- Byte --------------------------------------------------------------------//
|
||||
|
||||
KInt Kotlin_Byte_compareTo_Byte (KByte a, KByte b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Byte_compareTo_Short (KByte a, KShort b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Byte_compareTo_Int (KByte a, KInt b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Byte_compareTo_Long (KByte a, KLong b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Byte_compareTo_Float (KByte a, KFloat b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Byte_compareTo_Double (KByte a, KDouble b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_plus_Byte (KByte a, KByte b) { return a + b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_plus_Short (KByte a, KShort b) { return a + b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_plus_Int (KByte a, KInt b) { return a + b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Byte_plus_Long (KByte a, KLong b) { return a + b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Byte_plus_Float (KByte a, KFloat b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Byte_plus_Double (KByte a, KDouble b) { return a + b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_minus_Byte (KByte a, KByte b) { return a - b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_minus_Short (KByte a, KShort b) { return a - b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_minus_Int (KByte a, KInt b) { return a - b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Byte_minus_Long (KByte a, KLong b) { return a - b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Byte_minus_Float (KByte a, KFloat b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Byte_minus_Double (KByte a, KDouble b) { return a - b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_div_Byte (KByte a, KByte b) { return div<KInt>(a, b); }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_div_Short (KByte a, KShort b) { return div<KInt>(a, b); }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_div_Int (KByte a, KInt b) { return div<KInt>(a, b); }
|
||||
ALWAYS_INLINE KLong Kotlin_Byte_div_Long (KByte a, KLong b) { return div<KLong>(a, b); }
|
||||
ALWAYS_INLINE KFloat Kotlin_Byte_div_Float (KByte a, KFloat b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Byte_div_Double (KByte a, KDouble b) { return a / b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_mod_Byte (KByte a, KByte b) { return a % b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_mod_Short (KByte a, KShort b) { return a % b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_mod_Int (KByte a, KInt b) { return a % b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Byte_mod_Long (KByte a, KLong b) { return a % b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Byte_mod_Float (KByte a, KFloat b) { return fmodf(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Byte_mod_Double (KByte a, KDouble b) { return fmod (a, b); }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_times_Byte (KByte a, KByte b) { return a * b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_times_Short (KByte a, KShort b) { return a * b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_times_Int (KByte a, KInt b) { return a * b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Byte_times_Long (KByte a, KLong b) { return a * b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Byte_times_Float (KByte a, KFloat b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Byte_times_Double (KByte a, KDouble b) { return a * b; }
|
||||
|
||||
ALWAYS_INLINE KByte Kotlin_Byte_inc (KByte a ) { return ++a; }
|
||||
ALWAYS_INLINE KByte Kotlin_Byte_dec (KByte a ) { return --a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_unaryPlus (KByte a ) { return +a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_unaryMinus (KByte a ) { return -a; }
|
||||
|
||||
ALWAYS_INLINE KByte Kotlin_Byte_toByte (KByte a ) { return a; }
|
||||
ALWAYS_INLINE KChar Kotlin_Byte_toChar (KByte a ) { return a; }
|
||||
ALWAYS_INLINE KShort Kotlin_Byte_toShort (KByte a ) { return a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Byte_toInt (KByte a ) { return a; }
|
||||
ALWAYS_INLINE KLong Kotlin_Byte_toLong (KByte a ) { return a; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Byte_toFloat (KByte a ) { return a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Byte_toDouble (KByte a ) { return a; }
|
||||
|
||||
//--- Short -------------------------------------------------------------------//
|
||||
|
||||
KInt Kotlin_Short_compareTo_Byte (KShort a, KByte b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Short_compareTo_Short (KShort a, KShort b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Short_compareTo_Int (KShort a, KInt b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Short_compareTo_Long (KShort a, KLong b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Short_compareTo_Float (KShort a, KFloat b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Short_compareTo_Double (KShort a, KDouble b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Short_plus_Byte (KShort a, KByte b) { return a + b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_plus_Short (KShort a, KShort b) { return a + b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_plus_Int (KShort a, KInt b) { return a + b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Short_plus_Long (KShort a, KLong b) { return a + b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Short_plus_Float (KShort a, KFloat b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Short_plus_Double (KShort a, KDouble b) { return a + b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Short_minus_Byte (KShort a, KByte b) { return a - b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_minus_Short (KShort a, KShort b) { return a - b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_minus_Int (KShort a, KInt b) { return a - b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Short_minus_Long (KShort a, KLong b) { return a - b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Short_minus_Float (KShort a, KFloat b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Short_minus_Double (KShort a, KDouble b) { return a - b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Short_div_Byte (KShort a, KByte b) { return div<KInt>(a, b); }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_div_Short (KShort a, KShort b) { return div<KInt>(a, b); }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_div_Int (KShort a, KInt b) { return div<KInt>(a, b); }
|
||||
ALWAYS_INLINE KLong Kotlin_Short_div_Long (KShort a, KLong b) { return div<KLong>(a, b); }
|
||||
ALWAYS_INLINE KFloat Kotlin_Short_div_Float (KShort a, KFloat b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Short_div_Double (KShort a, KDouble b) { return a / b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Short_mod_Byte (KShort a, KByte b) { return a % b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_mod_Short (KShort a, KShort b) { return a % b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_mod_Int (KShort a, KInt b) { return a % b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Short_mod_Long (KShort a, KLong b) { return a % b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Short_mod_Float (KShort a, KFloat b) { return fmodf(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Short_mod_Double (KShort a, KDouble b) { return fmod (a, b); }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Short_times_Byte (KShort a, KByte b) { return a * b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_times_Short (KShort a, KShort b) { return a * b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_times_Int (KShort a, KInt b) { return a * b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Short_times_Long (KShort a, KLong b) { return a * b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Short_times_Float (KShort a, KFloat b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Short_times_Double (KShort a, KDouble b) { return a * b; }
|
||||
|
||||
ALWAYS_INLINE KShort Kotlin_Short_inc (KShort a ) { return ++a; }
|
||||
ALWAYS_INLINE KShort Kotlin_Short_dec (KShort a ) { return --a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_unaryPlus (KShort a ) { return +a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_unaryMinus (KShort a ) { return -a; }
|
||||
|
||||
ALWAYS_INLINE KByte Kotlin_Short_toByte (KShort a ) { return a; }
|
||||
ALWAYS_INLINE KChar Kotlin_Short_toChar (KShort a ) { return a; }
|
||||
ALWAYS_INLINE KShort Kotlin_Short_toShort (KShort a ) { return a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Short_toInt (KShort a ) { return a; }
|
||||
ALWAYS_INLINE KLong Kotlin_Short_toLong (KShort a ) { return a; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Short_toFloat (KShort a ) { return a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Short_toDouble (KShort a ) { return a; }
|
||||
|
||||
//--- Int ---------------------------------------------------------------------//
|
||||
|
||||
KInt Kotlin_Int_compareTo_Byte (KInt a, KByte b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Int_compareTo_Short (KInt a, KShort b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Int_compareTo_Int (KInt a, KInt b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Int_compareTo_Long (KInt a, KLong b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Int_compareTo_Float (KInt a, KFloat b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Int_compareTo_Double (KInt a, KDouble b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Int_plus_Byte (KInt a, KByte b) { return a + b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_plus_Short (KInt a, KShort b) { return a + b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_plus_Int (KInt a, KInt b) { return a + b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Int_plus_Long (KInt a, KLong b) { return a + b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Int_plus_Float (KInt a, KFloat b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Int_plus_Double (KInt a, KDouble b) { return a + b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Int_minus_Byte (KInt a, KByte b) { return a - b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_minus_Short (KInt a, KShort b) { return a - b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_minus_Int (KInt a, KInt b) { return a - b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Int_minus_Long (KInt a, KLong b) { return a - b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Int_minus_Float (KInt a, KFloat b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Int_minus_Double (KInt a, KDouble b) { return a - b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Int_div_Byte (KInt a, KByte b) { return div<KInt>(a, b); }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_div_Short (KInt a, KShort b) { return div<KInt>(a, b); }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_div_Int (KInt a, KInt b) { return div<KInt>(a, b); }
|
||||
ALWAYS_INLINE KLong Kotlin_Int_div_Long (KInt a, KLong b) { return div<KLong>(a, b); }
|
||||
ALWAYS_INLINE KFloat Kotlin_Int_div_Float (KInt a, KFloat b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Int_div_Double (KInt a, KDouble b) { return a / b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Int_mod_Byte (KInt a, KByte b) { return a % b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_mod_Short (KInt a, KShort b) { return a % b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_mod_Int (KInt a, KInt b) { return a % b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Int_mod_Long (KInt a, KLong b) { return a % b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Int_mod_Float (KInt a, KFloat b) { return fmodf(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Int_mod_Double (KInt a, KDouble b) { return fmod (a, b); }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Int_times_Byte (KInt a, KByte b) { return a * b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_times_Short (KInt a, KShort b) { return a * b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_times_Int (KInt a, KInt b) { return a * b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Int_times_Long (KInt a, KLong b) { return a * b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Int_times_Float (KInt a, KFloat b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Int_times_Double (KInt a, KDouble b) { return a * b; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Int_inc (KInt a ) { return ++a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_dec (KInt a ) { return --a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_unaryPlus (KInt a ) { return +a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_unaryMinus (KInt a ) { return -a; }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Int_or_Int (KInt a, KInt b) { return a | b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_xor_Int (KInt a, KInt b) { return a ^ b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_and_Int (KInt a, KInt b) { return a & b; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_inv (KInt a ) { return ~a; }
|
||||
|
||||
// According to C++11 the result is undefined if the second operator is < 0 or >= <first operand bit length>.
|
||||
// We avoid it by using only the least significant bits
|
||||
ALWAYS_INLINE KInt Kotlin_Int_shl_Int (KInt a, KInt b) { return a << (b & 31); }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_shr_Int (KInt a, KInt b) { return a >> (b & 31); }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_ushr_Int (KInt a, KInt b) {
|
||||
return static_cast<uint32_t>(a) >> (b & 31);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE KByte Kotlin_Int_toByte (KInt a ) { return a; }
|
||||
ALWAYS_INLINE KChar Kotlin_Int_toChar (KInt a ) { return a; }
|
||||
ALWAYS_INLINE KShort Kotlin_Int_toShort (KInt a ) { return a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Int_toInt (KInt a ) { return a; }
|
||||
ALWAYS_INLINE KLong Kotlin_Int_toLong (KInt a ) { return a; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Int_toFloat (KInt a ) { return a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Int_toDouble (KInt a ) { return a; }
|
||||
|
||||
//--- Long --------------------------------------------------------------------//
|
||||
|
||||
KInt Kotlin_Long_compareTo_Byte (KLong a, KByte b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Long_compareTo_Short (KLong a, KShort b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Long_compareTo_Int (KLong a, KInt b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Long_compareTo_Long (KLong a, KLong b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Long_compareTo_Float (KLong a, KFloat b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
KInt Kotlin_Long_compareTo_Double (KLong a, KDouble b) { if (a == b) return 0; return (a < b) ? -1 : 1; }
|
||||
|
||||
ALWAYS_INLINE KLong Kotlin_Long_plus_Byte (KLong a, KByte b) { return a + b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_plus_Short (KLong a, KShort b) { return a + b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_plus_Int (KLong a, KInt b) { return a + b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_plus_Long (KLong a, KLong b) { return a + b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Long_plus_Float (KLong a, KFloat b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Long_plus_Double (KLong a, KDouble b) { return a + b; }
|
||||
|
||||
ALWAYS_INLINE KLong Kotlin_Long_minus_Byte (KLong a, KByte b) { return a - b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_minus_Short (KLong a, KShort b) { return a - b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_minus_Int (KLong a, KInt b) { return a - b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_minus_Long (KLong a, KLong b) { return a - b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Long_minus_Float (KLong a, KFloat b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Long_minus_Double (KLong a, KDouble b) { return a - b; }
|
||||
|
||||
ALWAYS_INLINE KLong Kotlin_Long_div_Byte (KLong a, KByte b) { return div<KLong>(a, b); }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_div_Short (KLong a, KShort b) { return div<KLong>(a, b); }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_div_Int (KLong a, KInt b) { return div<KLong>(a, b); }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_div_Long (KLong a, KLong b) { return div<KLong>(a, b); }
|
||||
ALWAYS_INLINE KFloat Kotlin_Long_div_Float (KLong a, KFloat b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Long_div_Double (KLong a, KDouble b) { return a / b; }
|
||||
|
||||
ALWAYS_INLINE KLong Kotlin_Long_mod_Byte (KLong a, KByte b) { return a % b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_mod_Short (KLong a, KShort b) { return a % b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_mod_Int (KLong a, KInt b) { return a % b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_mod_Long (KLong a, KLong b) { return a % b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Long_mod_Float (KLong a, KFloat b) { return fmodf(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Long_mod_Double (KLong a, KDouble b) { return fmod (a, b); }
|
||||
|
||||
ALWAYS_INLINE KLong Kotlin_Long_times_Byte (KLong a, KByte b) { return a * b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_times_Short (KLong a, KShort b) { return a * b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_times_Int (KLong a, KInt b) { return a * b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_times_Long (KLong a, KLong b) { return a * b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Long_times_Float (KLong a, KFloat b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Long_times_Double (KLong a, KDouble b) { return a * b; }
|
||||
|
||||
ALWAYS_INLINE KLong Kotlin_Long_inc (KLong a ) { return ++a; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_dec (KLong a ) { return --a; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_unaryPlus (KLong a ) { return +a; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_unaryMinus (KLong a ) { return -a; }
|
||||
|
||||
ALWAYS_INLINE KLong Kotlin_Long_xor_Long (KLong a, KLong b) { return a ^ b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_or_Long (KLong a, KLong b) { return a | b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_and_Long (KLong a, KLong b) { return a & b; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_inv (KLong a ) { return ~a; }
|
||||
|
||||
// According to C++11 the result is undefined if the second operator is < 0 or >= <first operand bit length>.
|
||||
// We avoid it by using only the least significant bits
|
||||
ALWAYS_INLINE KLong Kotlin_Long_shl_Int (KLong a, KInt b) { return a << (b & 63); }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_shr_Int (KLong a, KInt b) { return a >> (b & 63); }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_ushr_Int (KLong a, KInt b) {
|
||||
return static_cast<uint64_t>(a) >> (b & 63);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE KByte Kotlin_Long_toByte (KLong a ) { return a; }
|
||||
ALWAYS_INLINE KChar Kotlin_Long_toChar (KLong a ) { return a; }
|
||||
ALWAYS_INLINE KShort Kotlin_Long_toShort (KLong a ) { return a; }
|
||||
ALWAYS_INLINE KInt Kotlin_Long_toInt (KLong a ) { return a; }
|
||||
ALWAYS_INLINE KLong Kotlin_Long_toLong (KLong a ) { return a; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Long_toFloat (KLong a ) { return a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Long_toDouble (KLong a ) { return a; }
|
||||
|
||||
//--- Float -------------------------------------------------------------------//
|
||||
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_plus_Byte (KFloat a, KByte b) { return a + b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_plus_Short (KFloat a, KShort b) { return a + b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_plus_Int (KFloat a, KInt b) { return a + b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_plus_Long (KFloat a, KLong b) { return a + b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_plus_Float (KFloat a, KFloat b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Float_plus_Double (KFloat a, KDouble b) { return a + b; }
|
||||
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_minus_Byte (KFloat a, KByte b) { return a - b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_minus_Short (KFloat a, KShort b) { return a - b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_minus_Int (KFloat a, KInt b) { return a - b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_minus_Long (KFloat a, KLong b) { return a - b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_minus_Float (KFloat a, KFloat b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Float_minus_Double (KFloat a, KDouble b) { return a - b; }
|
||||
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_div_Byte (KFloat a, KByte b) { return a / b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_div_Short (KFloat a, KShort b) { return a / b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_div_Int (KFloat a, KInt b) { return a / b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_div_Long (KFloat a, KLong b) { return a / b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_div_Float (KFloat a, KFloat b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Float_div_Double (KFloat a, KDouble b) { return a / b; }
|
||||
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_mod_Byte (KFloat a, KByte b) { return fmodf(a, b); }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_mod_Short (KFloat a, KShort b) { return fmodf(a, b); }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_mod_Int (KFloat a, KInt b) { return fmodf(a, b); }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_mod_Long (KFloat a, KLong b) { return fmodf(a, b); }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_mod_Float (KFloat a, KFloat b) { return fmodf(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Float_mod_Double (KFloat a, KDouble b) { return fmod (a, b); }
|
||||
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_times_Byte (KFloat a, KByte b) { return a * b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_times_Short (KFloat a, KShort b) { return a * b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_times_Int (KFloat a, KInt b) { return a * b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_times_Long (KFloat a, KLong b) { return a * b; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_times_Float (KFloat a, KFloat b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Float_times_Double (KFloat a, KDouble b) { return a * b; }
|
||||
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_inc (KFloat a ) { return ++a; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_dec (KFloat a ) { return --a; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_unaryPlus (KFloat a ) { return +a; }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_unaryMinus (KFloat a ) { return -a; }
|
||||
|
||||
KInt Kotlin_Float_toInt (KFloat a ) {
|
||||
KInt Kotlin_Float_toInt(KFloat a) {
|
||||
if (isnan(a)) return 0;
|
||||
if (a >= (KFloat) INT32_MAX) return INT32_MAX;
|
||||
if (a <= (KFloat) INT32_MIN) return INT32_MIN;
|
||||
return a;
|
||||
}
|
||||
KLong Kotlin_Float_toLong (KFloat a ) {
|
||||
|
||||
KLong Kotlin_Float_toLong(KFloat a) {
|
||||
if (isnan(a)) return 0;
|
||||
if (a >= (KFloat) INT64_MAX) return INT64_MAX;
|
||||
if (a <= (KFloat) INT64_MIN) return INT64_MIN;
|
||||
return a;
|
||||
}
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_toFloat (KFloat a ) { return a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Float_toDouble (KFloat a ) { return a; }
|
||||
KByte Kotlin_Float_toByte (KFloat a ) { return (KByte) Kotlin_Float_toInt(a); }
|
||||
KShort Kotlin_Float_toShort (KFloat a ) { return (KShort) Kotlin_Float_toInt(a); }
|
||||
|
||||
ALWAYS_INLINE KInt Kotlin_Float_bits (KFloat a ) { return floatToBits(a); }
|
||||
ALWAYS_INLINE KFloat Kotlin_Float_fromBits (KInt a ) { return bitsToFloat(a); }
|
||||
KByte Kotlin_Float_toByte(KFloat a) { return (KByte) Kotlin_Float_toInt(a); }
|
||||
KShort Kotlin_Float_toShort(KFloat a) { return (KShort) Kotlin_Float_toInt(a); }
|
||||
|
||||
ALWAYS_INLINE KBoolean Kotlin_Float_isNaN (KFloat a) { return isnan(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Float_isInfinite (KFloat a) { return isinf(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Float_isFinite (KFloat a) { return isfinite(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Float_isNaN(KFloat a) { return isnan(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Float_isInfinite(KFloat a) { return isinf(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Float_isFinite(KFloat a) { return isfinite(a); }
|
||||
|
||||
//--- Double ------------------------------------------------------------------//
|
||||
//--- Double ------------------------------------------------------------------//
|
||||
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_plus_Byte (KDouble a, KByte b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_plus_Short (KDouble a, KShort b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_plus_Int (KDouble a, KInt b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_plus_Long (KDouble a, KLong b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_plus_Float (KDouble a, KFloat b) { return a + b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_plus_Double (KDouble a, KDouble b) { return a + b; }
|
||||
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_minus_Byte (KDouble a, KByte b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_minus_Short (KDouble a, KShort b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_minus_Int (KDouble a, KInt b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_minus_Long (KDouble a, KLong b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_minus_Float (KDouble a, KFloat b) { return a - b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_minus_Double (KDouble a, KDouble b) { return a - b; }
|
||||
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_div_Byte (KDouble a, KByte b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_div_Short (KDouble a, KShort b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_div_Int (KDouble a, KInt b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_div_Long (KDouble a, KLong b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_div_Float (KDouble a, KFloat b) { return a / b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_div_Double (KDouble a, KDouble b) { return a / b; }
|
||||
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_mod_Byte (KDouble a, KByte b) { return fmod(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_mod_Short (KDouble a, KShort b) { return fmod(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_mod_Int (KDouble a, KInt b) { return fmod(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_mod_Long (KDouble a, KLong b) { return fmod(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_mod_Float (KDouble a, KFloat b) { return fmod(a, b); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_mod_Double (KDouble a, KDouble b) { return fmod(a, b); }
|
||||
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_times_Byte (KDouble a, KByte b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_times_Short (KDouble a, KShort b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_times_Int (KDouble a, KInt b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_times_Long (KDouble a, KLong b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_times_Float (KDouble a, KFloat b) { return a * b; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_times_Double (KDouble a, KDouble b) { return a * b; }
|
||||
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_inc (KDouble a ) { return ++a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_dec (KDouble a ) { return --a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_unaryPlus (KDouble a ) { return +a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_unaryMinus (KDouble a ) { return -a; }
|
||||
|
||||
KInt Kotlin_Double_toInt (KDouble a ) {
|
||||
KInt Kotlin_Double_toInt(KDouble a) {
|
||||
if (isnan(a)) return 0;
|
||||
if (a >= (KDouble) INT32_MAX) return INT32_MAX;
|
||||
if (a <= (KDouble) INT32_MIN) return INT32_MIN;
|
||||
return a;
|
||||
}
|
||||
KLong Kotlin_Double_toLong (KDouble a ) {
|
||||
|
||||
KLong Kotlin_Double_toLong(KDouble a) {
|
||||
if (isnan(a)) return 0;
|
||||
if (a >= (KDouble) INT64_MAX) return INT64_MAX;
|
||||
if (a <= (KDouble) INT64_MIN) return INT64_MIN;
|
||||
return a;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE KFloat Kotlin_Double_toFloat (KDouble a ) { return a; }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_toDouble (KDouble a ) { return a; }
|
||||
|
||||
ALWAYS_INLINE KLong Kotlin_Double_bits (KDouble a ) { return doubleToBits(a); }
|
||||
ALWAYS_INLINE KDouble Kotlin_Double_fromBits (KLong a ) { return bitsToDouble(a); }
|
||||
|
||||
ALWAYS_INLINE KBoolean Kotlin_Double_isNaN (KDouble a) { return isnan(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Double_isInfinite (KDouble a) { return isinf(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Double_isFinite (KDouble a) { return isfinite(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Double_isNaN(KDouble a) { return isnan(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Double_isInfinite(KDouble a) { return isinf(a); }
|
||||
ALWAYS_INLINE KBoolean Kotlin_Double_isFinite(KDouble a) { return isfinite(a); }
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
package kotlin
|
||||
|
||||
import kotlin.native.internal.TypedIntrinsic
|
||||
import kotlin.native.internal.IntrinsicType
|
||||
|
||||
/**
|
||||
* Represents a value which is either `true` or `false`. On the JVM, non-nullable values of this type are
|
||||
* represented as values of the primitive type `boolean`.
|
||||
@@ -18,30 +21,30 @@ public class Boolean private constructor(
|
||||
/**
|
||||
* Returns the inverse of this boolean.
|
||||
*/
|
||||
@SymbolName("Kotlin_Boolean_not")
|
||||
@TypedIntrinsic(IntrinsicType.NOT)
|
||||
external public operator fun not(): Boolean
|
||||
|
||||
/**
|
||||
* Performs a logical `and` operation between this Boolean and the [other] one. Unlike the `&&` operator,
|
||||
* this function does not perform short-circuit evaluation. Both `this` and [other] will always be evaluated.
|
||||
*/
|
||||
@SymbolName("Kotlin_Boolean_and_Boolean")
|
||||
@TypedIntrinsic(IntrinsicType.AND)
|
||||
external public infix fun and(other: Boolean): Boolean
|
||||
|
||||
/**
|
||||
* Performs a logical `or` operation between this Boolean and the [other] one. Unlike the `||` operator,
|
||||
* this function does not perform short-circuit evaluation. Both `this` and [other] will always be evaluated.
|
||||
*/
|
||||
@SymbolName("Kotlin_Boolean_or_Boolean")
|
||||
@TypedIntrinsic(IntrinsicType.OR)
|
||||
external public infix fun or(other: Boolean): Boolean
|
||||
|
||||
/**
|
||||
* Performs a logical `xor` operation between this Boolean and the [other] one.
|
||||
*/
|
||||
@SymbolName("Kotlin_Boolean_xor_Boolean")
|
||||
@TypedIntrinsic(IntrinsicType.XOR)
|
||||
external public infix fun xor(other: Boolean): Boolean
|
||||
|
||||
@SymbolName("Kotlin_Boolean_compareTo_Boolean")
|
||||
@TypedIntrinsic(IntrinsicType.SIGNED_COMPARE_TO)
|
||||
external public override fun compareTo(other: Boolean): Int
|
||||
|
||||
public fun equals(other: Boolean): Boolean = kotlin.native.internal.areEqualByValue(this, other)
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
package kotlin
|
||||
|
||||
import kotlin.native.internal.TypedIntrinsic
|
||||
import kotlin.native.internal.IntrinsicType
|
||||
|
||||
/**
|
||||
* Represents a 16-bit Unicode character.
|
||||
*/
|
||||
@@ -16,25 +20,24 @@ public class Char private constructor(
|
||||
* Returns zero if this value is equal to the specified other value, a negative number if it's less than other,
|
||||
* or a positive number if it's greater than other.
|
||||
*/
|
||||
@SymbolName("Kotlin_Char_compareTo_Char")
|
||||
@TypedIntrinsic(IntrinsicType.UNSIGNED_COMPARE_TO)
|
||||
external public override fun compareTo(other: Char): Int
|
||||
|
||||
/** Adds the other Int value to this value resulting a Char. */
|
||||
@SymbolName("Kotlin_Char_plus_Int")
|
||||
external public operator fun plus(other: Int): Char
|
||||
|
||||
public inline operator fun plus(other: Int): Char =
|
||||
(this.toInt() + other).toChar()
|
||||
/** Subtracts the other Char value from this value resulting an Int. */
|
||||
@SymbolName("Kotlin_Char_minus_Char")
|
||||
external public operator fun minus(other: Char): Int
|
||||
public inline operator fun minus(other: Char): Int =
|
||||
this.toInt() - other.toInt()
|
||||
/** Subtracts the other Int value from this value resulting a Char. */
|
||||
@SymbolName("Kotlin_Char_minus_Int")
|
||||
external public operator fun minus(other: Int): Char
|
||||
public inline operator fun minus(other: Int): Char =
|
||||
(this.toInt() - other).toChar()
|
||||
|
||||
/** Increments this value. */
|
||||
@SymbolName("Kotlin_Char_inc")
|
||||
@TypedIntrinsic(IntrinsicType.INC)
|
||||
external public operator fun inc(): Char
|
||||
/** Decrements this value. */
|
||||
@SymbolName("Kotlin_Char_dec")
|
||||
@TypedIntrinsic(IntrinsicType.DEC)
|
||||
external public operator fun dec(): Char
|
||||
|
||||
/** Creates a range from this value to the specified [other] value. */
|
||||
@@ -43,25 +46,24 @@ public class Char private constructor(
|
||||
}
|
||||
|
||||
/** Returns the value of this character as a `Byte`. */
|
||||
@SymbolName("Kotlin_Char_toByte")
|
||||
@TypedIntrinsic(IntrinsicType.INT_TRUNCATE)
|
||||
external public fun toByte(): Byte
|
||||
/** Returns the value of this character as a `Char`. */
|
||||
@SymbolName("Kotlin_Char_toChar")
|
||||
external public fun toChar(): Char
|
||||
public inline fun toChar(): Char = this
|
||||
/** Returns the value of this character as a `Short`. */
|
||||
@SymbolName("Kotlin_Char_toShort")
|
||||
@TypedIntrinsic(IntrinsicType.ZERO_EXTEND)
|
||||
external public fun toShort(): Short
|
||||
/** Returns the value of this character as a `Int`. */
|
||||
@SymbolName("Kotlin_Char_toInt")
|
||||
@TypedIntrinsic(IntrinsicType.ZERO_EXTEND)
|
||||
external public fun toInt(): Int
|
||||
/** Returns the value of this character as a `Long`. */
|
||||
@SymbolName("Kotlin_Char_toLong")
|
||||
@TypedIntrinsic(IntrinsicType.ZERO_EXTEND)
|
||||
external public fun toLong(): Long
|
||||
/** Returns the value of this character as a `Float`. */
|
||||
@SymbolName("Kotlin_Char_toFloat")
|
||||
@TypedIntrinsic(IntrinsicType.UNSIGNED_TO_FLOAT)
|
||||
external public fun toFloat(): Float
|
||||
/** Returns the value of this character as a `Double`. */
|
||||
@SymbolName("Kotlin_Char_toDouble")
|
||||
@TypedIntrinsic(IntrinsicType.UNSIGNED_TO_FLOAT)
|
||||
external public fun toDouble(): Double
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
package kotlin
|
||||
|
||||
import kotlin.native.internal.TypedIntrinsic
|
||||
import kotlin.native.internal.IntrinsicType
|
||||
|
||||
/**
|
||||
* Returns `true` if the specified number is a
|
||||
* Not-a-Number (NaN) value, `false` otherwise.
|
||||
@@ -68,7 +71,7 @@ public actual inline fun Double.toRawBits(): Long = bits()
|
||||
public actual inline fun Double.Companion.fromBits(bits: Long): Double = kotlin.fromBits(bits)
|
||||
|
||||
@PublishedApi
|
||||
@SymbolName("Kotlin_Double_fromBits")
|
||||
@TypedIntrinsic(IntrinsicType.FROM_BITS)
|
||||
external internal fun fromBits(bits: Long): Double
|
||||
|
||||
/**
|
||||
@@ -96,5 +99,5 @@ public actual inline fun Float.toRawBits(): Int = bits()
|
||||
public actual inline fun Float.Companion.fromBits(bits: Int): Float = kotlin.fromBits(bits)
|
||||
|
||||
@PublishedApi
|
||||
@SymbolName("Kotlin_Float_fromBits")
|
||||
@TypedIntrinsic(IntrinsicType.FROM_BITS)
|
||||
external internal fun fromBits(bits: Int): Float
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -95,3 +95,8 @@ internal annotation class Escapes(val who: Int)
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
internal annotation class PointsTo(vararg val onWhom: Int)
|
||||
|
||||
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
internal annotation class TypedIntrinsic(val kind: String)
|
||||
@@ -0,0 +1,37 @@
|
||||
package kotlin.native.internal
|
||||
|
||||
class IntrinsicType {
|
||||
companion object {
|
||||
const val PLUS = "PLUS"
|
||||
const val MINUS = "MINUS"
|
||||
const val TIMES = "TIMES"
|
||||
const val SIGNED_DIV = "SIGNED_DIV"
|
||||
const val SIGNED_REM = "SIGNED_REM"
|
||||
const val UNSIGNED_DIV = "UNSIGNED_DIV"
|
||||
const val UNSIGNED_REM = "UNSIGNED_REM"
|
||||
const val INC = "INC"
|
||||
const val DEC = "DEC"
|
||||
const val UNARY_PLUS = "UNARY_PLUS"
|
||||
const val UNARY_MINUS = "UNARY_MINUS"
|
||||
const val SHL = "SHL"
|
||||
const val SHR = "SHR"
|
||||
const val USHR = "USHR"
|
||||
const val AND = "AND"
|
||||
const val OR = "OR"
|
||||
const val XOR = "XOR"
|
||||
const val INV = "INV"
|
||||
const val SIGN_EXTEND = "SIGN_EXTEND"
|
||||
const val ZERO_EXTEND = "ZERO_EXTEND"
|
||||
const val INT_TRUNCATE = "INT_TRUNCATE"
|
||||
const val FLOAT_TRUNCATE = "FLOAT_TRUNCATE"
|
||||
const val FLOAT_EXTEND = "FLOAT_EXTEND"
|
||||
const val SIGNED_TO_FLOAT = "SIGNED_TO_FLOAT"
|
||||
const val UNSIGNED_TO_FLOAT = "UNSIGNED_TO_FLOAT"
|
||||
const val FLOAT_TO_SIGNED = "FLOAT_TO_SIGNED"
|
||||
const val SIGNED_COMPARE_TO = "SIGNED_COMPARE_TO"
|
||||
const val UNSIGNED_COMPARE_TO = "UNSIGNED_COMPARE_TO"
|
||||
const val NOT = "NOT"
|
||||
const val TO_BITS = "TO_BITS"
|
||||
const val FROM_BITS = "FROM_BITS"
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,6 @@ fun ThrowInvalidReceiverTypeException(klass: KClass<*>): Nothing {
|
||||
throw RuntimeException("Unexpected receiver type: " + (klass.qualifiedName ?: "noname"))
|
||||
}
|
||||
|
||||
@ExportForCppRuntime
|
||||
internal fun ThrowArithmeticException() : Nothing {
|
||||
throw ArithmeticException()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user