@@ -4103,6 +4103,16 @@ class JSCodeGen()(using genCtx: Context) {
41034103 js.UnaryOp (js.UnaryOp .UnwrapFromThrowable ,
41044104 js.UnaryOp (js.UnaryOp .CheckNotNull , genArgs1))
41054105
4106+ case LINKTIME_IF =>
4107+ // LinkingInfo.linkTimeIf(cond, thenp, elsep)
4108+ val cond = genLinkTimeExpr(args(0 ))
4109+ val thenp = genExpr(args(1 ))
4110+ val elsep = genExpr(args(2 ))
4111+ val tpe =
4112+ if (isStat) jstpe.VoidType
4113+ else toIRType(tree.tpe)
4114+ js.LinkTimeIf (cond, thenp, elsep)(tpe)
4115+
41064116 case UNION_FROM | UNION_FROM_TYPE_CONSTRUCTOR =>
41074117 /* js.|.from and js.|.fromTypeConstructor
41084118 * We should not have to deal with those. They have a perfectly valid
@@ -4128,6 +4138,91 @@ class JSCodeGen()(using genCtx: Context) {
41284138 }
41294139 }
41304140
4141+ private def genLinkTimeExpr (tree : Tree ): js.Tree = {
4142+ import dotty .tools .backend .ScalaPrimitivesOps .*
4143+
4144+ import primitives .*
4145+
4146+ implicit val pos = tree.span
4147+
4148+ def invalid (): js.Tree = {
4149+ report.error(
4150+ " Illegal expression in the condition of a linkTimeIf. " +
4151+ " Valid expressions are: boolean and int primitives; " +
4152+ " references to link-time properties; " +
4153+ " primitive operations on booleans; " +
4154+ " and comparisons on ints." ,
4155+ tree.sourcePos)
4156+ js.BooleanLiteral (false )
4157+ }
4158+
4159+ tree match {
4160+ case Literal (c) =>
4161+ import Constants .*
4162+ c.tag match {
4163+ case BooleanTag => js.BooleanLiteral (c.booleanValue)
4164+ case IntTag => js.IntLiteral (c.intValue)
4165+ case _ => invalid()
4166+ }
4167+
4168+ case Apply (fun, args) =>
4169+ fun.symbol.getAnnotation(jsdefn.LinkTimePropertyAnnot ) match {
4170+ case Some (annotation) =>
4171+ val propName = annotation.argumentConstantString(0 ).get
4172+ js.LinkTimeProperty (propName)(toIRType(tree.tpe))
4173+
4174+ case None if isPrimitive(fun.symbol) =>
4175+ val code = getPrimitive(fun.symbol)
4176+ val receiver = (fun : @ unchecked) match {
4177+ case fun : Select => fun.qualifier
4178+ case fun : Ident => desugarIdent(fun).get.qualifier
4179+ }
4180+
4181+ def genLhs : js.Tree = genLinkTimeExpr(receiver)
4182+ def genRhs : js.Tree = genLinkTimeExpr(args.head)
4183+
4184+ def unaryOp (op : js.UnaryOp .Code ): js.Tree =
4185+ js.UnaryOp (op, genLhs)
4186+ def binaryOp (op : js.BinaryOp .Code ): js.Tree =
4187+ js.BinaryOp (op, genLhs, genRhs)
4188+
4189+ toIRType(receiver.tpe) match {
4190+ case jstpe.BooleanType =>
4191+ (code : @ switch) match {
4192+ case ZNOT => unaryOp(js.UnaryOp .Boolean_! )
4193+ case EQ => binaryOp(js.BinaryOp .Boolean_== )
4194+ case NE | XOR => binaryOp(js.BinaryOp .Boolean_!= )
4195+ case OR => binaryOp(js.BinaryOp .Boolean_| )
4196+ case AND => binaryOp(js.BinaryOp .Boolean_& )
4197+ case ZOR => js.LinkTimeIf (genLhs, js.BooleanLiteral (true ), genRhs)(jstpe.BooleanType )
4198+ case ZAND => js.LinkTimeIf (genLhs, genRhs, js.BooleanLiteral (false ))(jstpe.BooleanType )
4199+ case _ => invalid()
4200+ }
4201+
4202+ case jstpe.IntType =>
4203+ (code : @ switch) match {
4204+ case EQ => binaryOp(js.BinaryOp .Int_== )
4205+ case NE => binaryOp(js.BinaryOp .Int_!= )
4206+ case LT => binaryOp(js.BinaryOp .Int_< )
4207+ case LE => binaryOp(js.BinaryOp .Int_<= )
4208+ case GT => binaryOp(js.BinaryOp .Int_> )
4209+ case GE => binaryOp(js.BinaryOp .Int_>= )
4210+ case _ => invalid()
4211+ }
4212+
4213+ case _ =>
4214+ invalid()
4215+ }
4216+
4217+ case None => // if !isPrimitive
4218+ invalid()
4219+ }
4220+
4221+ case _ =>
4222+ invalid()
4223+ }
4224+ }
4225+
41314226 /** Gen the SJSIR for a reflective call.
41324227 *
41334228 * Reflective calls are calls to a structural type field or method that
0 commit comments