1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.incubator.code.internal;
 27 
 28 import jdk.incubator.code.Op;
 29 import jdk.incubator.code.dialect.core.FunctionType;
 30 import jdk.incubator.code.dialect.java.JavaOp;
 31 import jdk.incubator.code.dialect.java.MethodRef;
 32 
 33 import java.lang.invoke.MethodHandle;
 34 import java.lang.invoke.MethodHandles;
 35 import java.lang.invoke.MethodType;
 36 
 37 // @@@ there are more methods than we need for op evaluation
 38 // e.g. conversion from PT to boolean and from boolean to PT
 39 // these methods are used by interpreter
 40 public final class ArithmeticAndConvOpImpls {
 41     public static boolean eq(Object a, Object b) {
 42         return a == b;
 43     }
 44 
 45     public static boolean neq(Object a, Object b) {
 46         return a != b;
 47     }
 48 
 49 
 50     public static boolean not(boolean l) {
 51         return !l;
 52     }
 53 
 54     // int
 55 
 56     public static int neg(int l) {
 57         return -l;
 58     }
 59 
 60     public static int compl(int l) {
 61         return ~l;
 62     }
 63 
 64     public static int add(int l, int r) {
 65         return l + r;
 66     }
 67 
 68     public static int sub(int l, int r) {
 69         return l - r;
 70     }
 71 
 72     public static int mul(int l, int r) {
 73         return l * r;
 74     }
 75 
 76     public static int div(int l, int r) {
 77         return l / r;
 78     }
 79 
 80     public static int mod(int l, int r) {
 81         return l % r;
 82     }
 83 
 84     public static int or(int l, int r) {
 85         return l | r;
 86     }
 87 
 88     public static int and(int l, int r) {
 89         return l & r;
 90     }
 91 
 92     public static int xor(int l, int r) {
 93         return l ^ r;
 94     }
 95 
 96     public static int lshl(int l, int r) {
 97         return l << r;
 98     }
 99 
100     public static int ashr(int l, int r) {
101         return l >> r;
102     }
103 
104     public static int lshr(int l, int r) {
105         return l >>> r;
106     }
107 
108     public static int lshl(int l, long r) {
109         return l << r;
110     }
111 
112     public static int ashr(int l, long r) {
113         return l >> r;
114     }
115 
116     public static int lshr(int l, long r) {
117         return l >>> r;
118     }
119 
120     public static boolean eq(int l, int r) {
121         return l == r;
122     }
123 
124     public static boolean neq(int l, int r) {
125         return l != r;
126     }
127 
128     public static boolean gt(int l, int r) {
129         return l > r;
130     }
131 
132     public static boolean ge(int l, int r) {
133         return l >= r;
134     }
135 
136     public static boolean lt(int l, int r) {
137         return l < r;
138     }
139 
140     public static boolean le(int l, int r) {
141         return l <= r;
142     }
143 
144     // byte
145 
146     public static byte neg(byte l) {
147         return (byte) -l;
148     }
149 
150     public static byte compl(byte l) {
151         return (byte) ~l;
152     }
153 
154     public static byte add(byte l, byte r) {
155         return (byte) (l + r);
156     }
157 
158     public static byte sub(byte l, byte r) {
159         return (byte) (l - r);
160     }
161 
162     public static byte mul(byte l, byte r) {
163         return (byte) (l * r);
164     }
165 
166     public static byte div(byte l, byte r) {
167         return (byte) (l / r);
168     }
169 
170     public static byte mod(byte l, byte r) {
171         return (byte) (l % r);
172     }
173 
174     public static byte or(byte l, byte r) {
175         return (byte) (l | r);
176     }
177 
178     public static byte and(byte l, byte r) {
179         return (byte) (l & r);
180     }
181 
182     public static byte xor(byte l, byte r) {
183         return (byte) (l ^ r);
184     }
185 
186     public static byte ashr(byte l, long r) {
187         return (byte) (l >> r);
188     }
189 
190     public static byte lshr(byte l, long r) {
191         return (byte) (l >>> r);
192     }
193 
194     public static byte lshl(byte l, int r) {
195         return (byte) (l << r);
196     }
197 
198     public static byte ashr(byte l, int r) {
199         return (byte) (l >> r);
200     }
201 
202     public static byte lshr(byte l, int r) {
203         return (byte) (l >>> r);
204     }
205 
206     public static boolean eq(byte l, byte r) {
207         return l == r;
208     }
209 
210     public static boolean neq(byte l, byte r) {
211         return l != r;
212     }
213 
214     public static boolean gt(byte l, byte r) {
215         return l > r;
216     }
217 
218     public static boolean ge(byte l, byte r) {
219         return l >= r;
220     }
221 
222     public static boolean lt(byte l, byte r) {
223         return l < r;
224     }
225 
226     public static boolean le(byte l, byte r) {
227         return l <= r;
228     }
229 
230     // short
231 
232     public static short neg(short l) {
233         return (short) -l;
234     }
235 
236     public static short compl(short l) {
237         return (short) ~l;
238     }
239 
240     public static short add(short l, short r) {
241         return (short) (l + r);
242     }
243 
244     public static short sub(short l, short r) {
245         return (short) (l - r);
246     }
247 
248     public static short mul(short l, short r) {
249         return (short) (l * r);
250     }
251 
252     public static short div(short l, short r) {
253         return (short) (l / r);
254     }
255 
256     public static short mod(short l, short r) {
257         return (short) (l % r);
258     }
259 
260     public static short or(short l, short r) {
261         return (short) (l | r);
262     }
263 
264     public static short and(short l, short r) {
265         return (short) (l & r);
266     }
267 
268     public static short xor(short l, short r) {
269         return (short) (l ^ r);
270     }
271 
272     public static short ashr(short l, long r) {
273         return (short) (l >> r);
274     }
275 
276     public static short lshr(short l, long r) {
277         return (short) (l >>> r);
278     }
279 
280     public static short lshl(short l, int r) {
281         return (short) (l << r);
282     }
283 
284     public static short ashr(short l, int r) {
285         return (short) (l >> r);
286     }
287 
288     public static short lshr(short l, int r) {
289         return (short) (l >>> r);
290     }
291 
292     public static boolean eq(short l, short r) {
293         return l == r;
294     }
295 
296     public static boolean neq(short l, short r) {
297         return l != r;
298     }
299 
300     public static boolean gt(short l, short r) {
301         return l > r;
302     }
303 
304     public static boolean ge(short l, short r) {
305         return l >= r;
306     }
307 
308     public static boolean lt(short l, short r) {
309         return l < r;
310     }
311 
312     public static boolean le(short l, short r) {
313         return l <= r;
314     }
315 
316     // char
317 
318     public static char neg(char l) {
319         return (char) -l;
320     }
321 
322     public static char compl(char l) {
323         return (char) ~l;
324     }
325 
326     public static char add(char l, char r) {
327         return (char) (l + r);
328     }
329 
330     public static char sub(char l, char r) {
331         return (char) (l - r);
332     }
333 
334     public static char mul(char l, char r) {
335         return (char) (l * r);
336     }
337 
338     public static char div(char l, char r) {
339         return (char) (l / r);
340     }
341 
342     public static char mod(char l, char r) {
343         return (char) (l % r);
344     }
345 
346     public static char or(char l, char r) {
347         return (char) (l | r);
348     }
349 
350     public static char and(char l, char r) {
351         return (char) (l & r);
352     }
353 
354     public static char xor(char l, char r) {
355         return (char) (l ^ r);
356     }
357 
358     public static char ashr(char l, long r) {
359         return (char) (l >> r);
360     }
361 
362     public static char lshr(char l, long r) {
363         return (char) (l >>> r);
364     }
365 
366     public static char lshl(char l, int r) {
367         return (char) (l << r);
368     }
369 
370     public static char ashr(char l, int r) {
371         return (char) (l >> r);
372     }
373 
374     public static char lshr(char l, int r) {
375         return (char) (l >>> r);
376     }
377 
378     public static boolean eq(char l, char r) {
379         return l == r;
380     }
381 
382     public static boolean neq(char l, char r) {
383         return l != r;
384     }
385 
386     public static boolean gt(char l, char r) {
387         return l > r;
388     }
389 
390     public static boolean ge(char l, char r) {
391         return l >= r;
392     }
393 
394     public static boolean lt(char l, char r) {
395         return l < r;
396     }
397 
398     public static boolean le(char l, char r) {
399         return l <= r;
400     }
401     // long
402 
403     public static long neg(long l) {
404         return -l;
405     }
406 
407     public static long compl(long l) {
408         return ~l;
409     }
410 
411     public static long add(long l, long r) {
412         return l + r;
413     }
414 
415     public static long sub(long l, long r) {
416         return l - r;
417     }
418 
419     public static long mul(long l, long r) {
420         return l * r;
421     }
422 
423     public static long div(long l, long r) {
424         return l / r;
425     }
426 
427     public static long mod(long l, long r) {
428         return l % r;
429     }
430 
431     public static long or(long l, long r) {
432         return l | r;
433     }
434 
435     public static long and(long l, long r) {
436         return l & r;
437     }
438 
439     public static long xor(long l, long r) {
440         return l ^ r;
441     }
442 
443     public static long lshl(long l, long r) {
444         return l << r;
445     }
446 
447     public static long ashr(long l, long r) {
448         return l >> r;
449     }
450 
451     public static long lshr(long l, long r) {
452         return l >>> r;
453     }
454 
455     public static long lshl(long l, int r) {
456         return l << r;
457     }
458 
459     public static long ashr(long l, int r) {
460         return l >> r;
461     }
462 
463     public static long lshr(long l, int r) {
464         return l >>> r;
465     }
466 
467     public static boolean eq(long l, long r) {
468         return l == r;
469     }
470 
471     public static boolean neq(long l, long r) {
472         return l != r;
473     }
474 
475     public static boolean gt(long l, long r) {
476         return l > r;
477     }
478 
479     public static boolean ge(long l, long r) {
480         return l >= r;
481     }
482 
483     public static boolean lt(long l, long r) {
484         return l < r;
485     }
486 
487     public static boolean le(long l, long r) {
488         return l <= r;
489     }
490 
491 
492 
493     // float
494 
495     public static float neg(float l) {
496         return -l;
497     }
498 
499     public static float add(float l, float r) {
500         return l + r;
501     }
502 
503     public static float sub(float l, float r) {
504         return l - r;
505     }
506 
507     public static float mul(float l, float r) {
508         return l * r;
509     }
510 
511     public static float div(float l, float r) {
512         return l / r;
513     }
514 
515     public static float mod(float l, float r) {
516         return l % r;
517     }
518 
519     public static boolean eq(float l, float r) {
520         return l == r;
521     }
522 
523     public static boolean neq(float l, float r) {
524         return l != r;
525     }
526 
527     public static boolean gt(float l, float r) {
528         return l > r;
529     }
530 
531     public static boolean ge(float l, float r) {
532         return l >= r;
533     }
534 
535     public static boolean lt(float l, float r) {
536         return l < r;
537     }
538 
539     public static boolean le(float l, float r) {
540         return l <= r;
541     }
542 
543 
544 
545     // double
546 
547     public static double neg(double l) {
548         return -l;
549     }
550 
551     public static double add(double l, double r) {
552         return l + r;
553     }
554 
555     public static double sub(double l, double r) {
556         return l - r;
557     }
558 
559     public static double mul(double l, double r) {
560         return l * r;
561     }
562 
563     public static double div(double l, double r) {
564         return l / r;
565     }
566 
567     public static double mod(double l, double r) {
568         return l % r;
569     }
570 
571     public static boolean eq(double l, double r) {
572         return l == r;
573     }
574 
575     public static boolean neq(double l, double r) {
576         return l != r;
577     }
578 
579     public static boolean gt(double l, double r) {
580         return l > r;
581     }
582 
583     public static boolean ge(double l, double r) {
584         return l >= r;
585     }
586 
587     public static boolean lt(double l, double r) {
588         return l < r;
589     }
590 
591     public static boolean le(double l, double r) {
592         return l <= r;
593     }
594 
595 
596     // boolean
597 
598     public static boolean eq(boolean l, boolean r) {
599         return l == r;
600     }
601 
602     public static boolean neq(boolean l, boolean r) {
603         return l != r;
604     }
605 
606     public static boolean and(boolean l, boolean r) {
607         return l & r;
608     }
609 
610     public static boolean or(boolean l, boolean r) {
611         return l | r;
612     }
613 
614     public static boolean xor(boolean l, boolean r) {
615         return l ^ r;
616     }
617 
618 
619     // Primitive conversions
620 
621     // double conversion
622     public static double conv_double(double i) {
623         return i;
624     }
625     public static float conv_float(double i) {
626         return (float) i;
627     }
628     public static long conv_long(double i) {
629         return (long) i;
630     }
631     public static int conv_int(double i) {
632         return (int) i;
633     }
634     public static short conv_short(double i) {
635         return (short) i;
636     }
637     public static char conv_char(double i) {
638         return (char) i;
639     }
640     public static byte conv_byte(double i) {
641         return (byte) i;
642     }
643     public static boolean conv_boolean(double i) {
644         return ((int)i & 1) == 1;
645     }
646 
647     // float conversion
648     public static double conv_double(float i) {
649         return i;
650     }
651     public static float conv_float(float i) {
652         return i;
653     }
654     public static long conv_long(float i) {
655         return (long) i;
656     }
657     public static int conv_int(float i) {
658         return (int) i;
659     }
660     public static short conv_short(float i) {
661         return (short) i;
662     }
663     public static char conv_char(float i) {
664         return (char) i;
665     }
666     public static byte conv_byte(float i) {
667         return (byte) i;
668     }
669     public static boolean conv_boolean(float i) {
670         return ((int)i & 1) == 1;
671     }
672 
673     // long conversion
674     public static double conv_double(long i) {
675         return (double) i;
676     }
677     public static float conv_float(long i) {
678         return (float) i;
679     }
680     public static long conv_long(long i) {
681         return i;
682     }
683     public static int conv_int(long i) {
684         return (int) i;
685     }
686     public static short conv_short(long i) {
687         return (short) i;
688     }
689     public static char conv_char(long i) {
690         return (char) i;
691     }
692     public static byte conv_byte(long i) {
693         return (byte) i;
694     }
695     public static boolean conv_boolean(long i) {
696         return (i & 1) == 1;
697     }
698 
699     // int conversion
700     public static double conv_double(int i) {
701         return (double) i;
702     }
703     public static float conv_float(int i) {
704         return (float) i;
705     }
706     public static long conv_long(int i) {
707         return i;
708     }
709     public static int conv_int(int i) {
710         return i;
711     }
712     public static short conv_short(int i) {
713         return (short) i;
714     }
715     public static char conv_char(int i) {
716         return (char) i;
717     }
718     public static byte conv_byte(int i) {
719         return (byte) i;
720     }
721     public static boolean conv_boolean(int i) {
722         return (i & 1) == 1;
723     }
724 
725     // short conversion
726     public static double conv_double(short i) {
727         return i;
728     }
729     public static float conv_float(short i) {
730         return i;
731     }
732     public static long conv_long(short i) {
733         return i;
734     }
735     public static int conv_int(short i) {
736         return i;
737     }
738     public static short conv_short(short i) {
739         return i;
740     }
741     public static char conv_char(short i) {
742         return (char) i;
743     }
744     public static byte conv_byte(short i) {
745         return (byte) i;
746     }
747     public static boolean conv_boolean(short i) {
748         return (i & 1) == 1;
749     }
750 
751     // char conversion
752     public static double conv_double(char i) {
753         return i;
754     }
755     public static float conv_float(char i) {
756         return i;
757     }
758     public static long conv_long(char i) {
759         return i;
760     }
761     public static int conv_int(char i) {
762         return i;
763     }
764     public static short conv_short(char i) {
765         return (short) i;
766     }
767     public static char conv_char(char i) {
768         return i;
769     }
770     public static byte conv_byte(char i) {
771         return (byte) i;
772     }
773     public static boolean conv_boolean(char i) {
774         return (i & 1) == 1;
775     }
776 
777     // byte conversion
778     public static double conv_double(byte i) {
779         return i;
780     }
781     public static float conv_float(byte i) {
782         return i;
783     }
784     public static long conv_long(byte i) {
785         return i;
786     }
787     public static int conv_int(byte i) {
788         return i;
789     }
790     public static short conv_short(byte i) {
791         return i;
792     }
793     public static char conv_char(byte i) {
794         return (char) i;
795     }
796     public static byte conv_byte(byte i) {
797         return i;
798     }
799     public static boolean conv_boolean(byte i) {
800         return (i & 1) == 1;
801     }
802 
803     // boolean conversion
804     public static double conv_double(boolean i) {
805         return i ? 1d : 0d;
806     }
807     public static float conv_float(boolean i) {
808         return i ? 1f : 0f;
809     }
810     public static long conv_long(boolean i) {
811         return i ? 1l : 0l;
812     }
813     public static int conv_int(boolean i) {
814         return i ? 1 : 0;
815     }
816     public static short conv_short(boolean i) {
817         return i ? (short)1 : 0;
818     }
819     public static char conv_char(boolean i) {
820         return i ? (char)1 : 0;
821     }
822     public static byte conv_byte(boolean i) {
823         return i ? (byte)1 : 0;
824     }
825     public static boolean conv_boolean(boolean i) {
826         return i;
827     }
828 
829     // resolution
830     private static MethodType resolveToMethodType(FunctionType ft) {
831         try {
832             return MethodRef.toNominalDescriptor(ft).resolveConstantDesc(MethodHandles.publicLookup());
833         } catch (ReflectiveOperationException e) {
834             return null;
835         }
836     }
837 
838     private static MethodHandle opHandle(String methodName, FunctionType ft) {
839         MethodType mt = resolveToMethodType(ft);
840         if (mt == null) return null;
841         mt = mt.erase();
842         try {
843             return MethodHandles.lookup().findStatic(ArithmeticAndConvOpImpls.class, methodName, mt);
844         } catch (NoSuchMethodException e) {
845             return null;
846         } catch (IllegalAccessException e) {
847             throw new InternalError("Should not reach here");
848         }
849     }
850 
851     public static Object evaluate(Op op, Object... evaluatedOperands) throws NonConstantExpression {
852         String mn = op.externalizeOpName();
853         if (op instanceof JavaOp.ConvOp) {
854             mn = mn + "_" + op.resultType();
855         }
856         MethodHandle mh = opHandle(mn, op.opType());
857         if (mh == null) {
858             throw new NonConstantExpression();
859         }
860         try {
861             return mh.invokeWithArguments(evaluatedOperands);
862         } catch (Throwable e) {
863             throw new InternalError("Should not reach here", e);
864         }
865     }
866 
867     @SuppressWarnings("serial")
868     public static class NonConstantExpression extends Exception {
869         public NonConstantExpression() {}
870     }
871 }