Make JetStream 2
[WebKit-https.git] / PerformanceTests / JetStream2 / ARES-6 / Air / arg.js
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25 "use strict";
26
27 class Arg {
28     constructor()
29     {
30         this._kind = Arg.Invalid;
31     }
32     
33     static isAnyUse(role)
34     {
35         switch (role) {
36         case Arg.Use:
37         case Arg.ColdUse:
38         case Arg.UseDef:
39         case Arg.UseZDef:
40         case Arg.LateUse:
41         case Arg.LateColdUse:
42         case Arg.Scratch:
43             return true;
44         case Arg.Def:
45         case Arg.ZDef:
46         case Arg.UseAddr:
47         case Arg.EarlyDef:
48             return false;
49         default:
50             throw new Error("Bad role");
51         }
52     }
53     
54     static isColdUse(role)
55     {
56         switch (role) {
57         case Arg.ColdUse:
58         case Arg.LateColdUse:
59             return true;
60         case Arg.Use:
61         case Arg.UseDef:
62         case Arg.UseZDef:
63         case Arg.LateUse:
64         case Arg.Def:
65         case Arg.ZDef:
66         case Arg.UseAddr:
67         case Arg.Scratch:
68         case Arg.EarlyDef:
69             return false;
70         default:
71             throw new Error("Bad role");
72         }
73     }
74     
75     static isWarmUse(role)
76     {
77         return Arg.isAnyUse(role) && !Arg.isColdUse(role);
78     }
79     
80     static cooled(role)
81     {
82         switch (role) {
83         case Arg.ColdUse:
84         case Arg.LateColdUse:
85         case Arg.UseDef:
86         case Arg.UseZDef:
87         case Arg.Def:
88         case Arg.ZDef:
89         case Arg.UseAddr:
90         case Arg.Scratch:
91         case Arg.EarlyDef:
92             return role;
93         case Arg.Use:
94             return Arg.ColdUse;
95         case Arg.LateUse:
96             return Arg.LateColdUse;
97         default:
98             throw new Error("Bad role");
99         }
100     }
101
102     static isEarlyUse(role)
103     {
104         switch (role) {
105         case Arg.Use:
106         case Arg.ColdUse:
107         case Arg.UseDef:
108         case Arg.UseZDef:
109             return true;
110         case Arg.Def:
111         case Arg.ZDef:
112         case Arg.UseAddr:
113         case Arg.LateUse:
114         case Arg.LateColdUse:
115         case Arg.Scratch:
116         case Arg.EarlyDef:
117             return false;
118         default:
119             throw new Error("Bad role");
120         }
121     }
122     
123     static isLateUse(role)
124     {
125         switch (role) {
126         case Arg.LateUse:
127         case Arg.LateColdUse:
128         case Arg.Scratch:
129             return true;
130         case Arg.ColdUse:
131         case Arg.Use:
132         case Arg.UseDef:
133         case Arg.UseZDef:
134         case Arg.Def:
135         case Arg.ZDef:
136         case Arg.UseAddr:
137         case Arg.EarlyDef:
138             return false;
139         default:
140             throw new Error("Bad role");
141         }
142     }
143     
144     static isAnyDef(role)
145     {
146         switch (role) {
147         case Arg.Use:
148         case Arg.ColdUse:
149         case Arg.UseAddr:
150         case Arg.LateUse:
151         case Arg.LateColdUse:
152             return false;
153         case Arg.Def:
154         case Arg.UseDef:
155         case Arg.ZDef:
156         case Arg.UseZDef:
157         case Arg.EarlyDef:
158         case Arg.Scratch:
159             return true;
160         default:
161             throw new Error("Bad role");
162         }
163     }
164     
165     static isEarlyDef(role)
166     {
167         switch (role) {
168         case Arg.Use:
169         case Arg.ColdUse:
170         case Arg.UseAddr:
171         case Arg.LateUse:
172         case Arg.Def:
173         case Arg.UseDef:
174         case Arg.ZDef:
175         case Arg.UseZDef:
176         case Arg.LateColdUse:
177             return false;
178         case Arg.EarlyDef:
179         case Arg.Scratch:
180             return true;
181         default:
182             throw new Error("Bad role");
183         }
184     }
185     
186     static isLateDef(role)
187     {
188         switch (role) {
189         case Arg.Use:
190         case Arg.ColdUse:
191         case Arg.UseAddr:
192         case Arg.LateUse:
193         case Arg.EarlyDef:
194         case Arg.Scratch:
195         case Arg.LateColdUse:
196             return false;
197         case Arg.Def:
198         case Arg.UseDef:
199         case Arg.ZDef:
200         case Arg.UseZDef:
201             return true;
202         default:
203             throw new Error("Bad role");
204         }
205     }
206     
207     static isZDef(role)
208     {
209         switch (role) {
210         case Arg.Use:
211         case Arg.ColdUse:
212         case Arg.UseAddr:
213         case Arg.LateUse:
214         case Arg.Def:
215         case Arg.UseDef:
216         case Arg.EarlyDef:
217         case Arg.Scratch:
218         case Arg.LateColdUse:
219             return false;
220         case Arg.ZDef:
221         case Arg.UseZDef:
222             return true;
223         default:
224             throw new Error("Bad role");
225         }
226     }
227     
228     static typeForB3Type(type)
229     {
230         switch (type) {
231         case Int32:
232         case Int64:
233             return GP;
234         case Float:
235         case Double:
236             return FP;
237         default:
238             throw new Error("Bad B3 type");
239         }
240     }
241     
242     static widthForB3Type(type)
243     {
244         switch (type) {
245         case Int32:
246         case Float:
247             return 32;
248         case Int64:
249         case Double:
250             return 64;
251         default:
252             throw new Error("Bad B3 type");
253         }
254     }
255     
256     static conservativeWidth(type)
257     {
258         return type == GP ? Ptr : 64;
259     }
260     
261     static minimumWidth(type)
262     {
263         return type == GP ? 8 : 32;
264     }
265     
266     static bytes(width)
267     {
268         return width / 8;
269     }
270     
271     static widthForBytes(bytes)
272     {
273         switch (bytes) {
274         case 0:
275         case 1:
276             return 8;
277         case 2:
278             return 16;
279         case 3:
280         case 4:
281             return 32;
282         default:
283             if (bytes > 8)
284                 throw new Error("Bad number of bytes");
285             return 64;
286         }
287     }
288     
289     static createTmp(tmp)
290     {
291         let result = new Arg();
292         result._kind = Arg.Tmp;
293         result._tmp = tmp;
294         return result;
295     }
296     
297     static fromReg(reg)
298     {
299         return Arg.createTmp(reg);
300     }
301     
302     static createImm(value)
303     {
304         let result = new Arg();
305         result._kind = Arg.Imm;
306         result._value = value;
307         return result;
308     }
309     
310     static createBigImm(lowValue, highValue = 0)
311     {
312         let result = new Arg();
313         result._kind = Arg.BigImm;
314         result._lowValue = lowValue;
315         result._highValue = highValue;
316         return result;
317     }
318     
319     static createBitImm(value)
320     {
321         let result = new Arg();
322         result._kind = Arg.BitImm;
323         result._value = value;
324         return result;
325     }
326     
327     static createBitImm64(lowValue, highValue = 0)
328     {
329         let result = new Arg();
330         result._kind = Arg.BitImm64;
331         result._lowValue = lowValue;
332         result._highValue = highValue;
333         return result;
334     }
335     
336     static createAddr(base, offset = 0)
337     {
338         let result = new Arg();
339         result._kind = Arg.Addr;
340         result._base = base;
341         result._offset = offset;
342         return result;
343     }
344     
345     static createStack(slot, offset = 0)
346     {
347         let result = new Arg();
348         result._kind = Arg.Stack;
349         result._slot = slot;
350         result._offset = offset;
351         return result;
352     }
353     
354     static createCallArg(offset)
355     {
356         let result = new Arg();
357         result._kind = Arg.CallArg;
358         result._offset = offset;
359         return result;
360     }
361     
362     static createStackAddr(offsetFromFP, frameSize, width)
363     {
364         let result = Arg.createAddr(Reg.callFrameRegister, offsetFromFP);
365         if (!result.isValidForm(width))
366             result = Arg.createAddr(Reg.stackPointerRegister, offsetFromFP + frameSize);
367         return result;
368     }
369     
370     static isValidScale(scale, width)
371     {
372         switch (scale) {
373         case 1:
374         case 2:
375         case 4:
376         case 8:
377             return true;
378         default:
379             return false;
380         }
381     }
382     
383     static logScale(scale)
384     {
385         switch (scale) {
386         case 1:
387             return 0;
388         case 2:
389             return 1;
390         case 4:
391             return 2;
392         case 8:
393             return 3;
394         default:
395             throw new Error("Bad scale");
396         }
397     }
398     
399     static createIndex(base, index, scale = 1, offset = 0)
400     {
401         let result = new Arg();
402         result._kind = Arg.Index;
403         result._base = base;
404         result._index = index;
405         result._scale = scale;
406         result._offset = offset;
407         return result;
408     }
409     
410     static createRelCond(condition)
411     {
412         let result = new Arg();
413         result._kind = Arg.RelCond;
414         result._condition = condition;
415         return result;
416     }
417     
418     static createResCond(condition)
419     {
420         let result = new Arg();
421         result._kind = Arg.ResCond;
422         result._condition = condition;
423         return result;
424     }
425     
426     static createDoubleCond(condition)
427     {
428         let result = new Arg();
429         result._kind = Arg.DoubleCond;
430         result._condition = condition;
431         return result;
432     }
433     
434     static createWidth(width)
435     {
436         let result = new Arg();
437         result._kind = Arg.Width;
438         result._width = width;
439         return result;
440     }
441     
442     static createSpecial()
443     {
444         let result = new Arg();
445         result._kind = Arg.Special;
446         return result;
447     }
448     
449     get kind() { return this._kind; }
450     get isTmp() { return this._kind == Arg.Tmp; }
451     get isImm() { return this._kind == Arg.Imm; }
452     get isBigImm() { return this._kind == Arg.BigImm; }
453     get isBitImm() { return this._kind == Arg.BitImm; }
454     get isBitImm64() { return this._kind == Arg.BitImm64; }
455     get isSomeImm()
456     {
457         switch (this._kind) {
458         case Arg.Imm:
459         case Arg.BitImm:
460             return true;
461         default:
462             return false;
463         }
464     }
465     get isSomeBigImm()
466     {
467         switch (this._kind) {
468         case Arg.BigImm:
469         case Arg.BitImm64:
470             return true;
471         default:
472             return false;
473         }
474     }
475     get isAddr() { return this._kind == Arg.Addr; }
476     get isStack() { return this._kind == Arg.Stack; }
477     get isCallArg() { return this._kind == Arg.CallArg; }
478     get isIndex() { return this._kind == Arg.Index; }
479     get isMemory()
480     {
481         switch (this._kind) {
482         case Arg.Addr:
483         case Arg.Stack:
484         case Arg.CallArg:
485         case Arg.Index:
486             return true;
487         default:
488             return false;
489         }
490     }
491     get isStackMemory()
492     {
493         switch (this._kind) {
494         case Arg.Addr:
495             return this._base == Reg.callFrameRegister
496                 || this._base == Reg.stackPointerRegister;
497         case Arg.Stack:
498         case Arg.CallArg:
499             return true;
500         default:
501             return false;
502         }
503     }
504     get isRelCond() { return this._kind == Arg.RelCond; }
505     get isResCond() { return this._kind == Arg.ResCond; }
506     get isDoubleCond() { return this._kind == Arg.DoubleCond; }
507     get isCondition()
508     {
509         switch (this._kind) {
510         case Arg.RelCond:
511         case Arg.ResCond:
512         case Arg.DoubleCond:
513             return true;
514         default:
515             return false;
516         }
517     }
518     get isWidth() { return this._kind == Arg.Width; }
519     get isSpecial() { return this._kind == Arg.Special; }
520     get isAlive() { return this.isTmp || this.isStack; }
521     
522     get tmp()
523     {
524         if (this._kind != Arg.Tmp)
525             throw new Error("Called .tmp for non-tmp");
526         return this._tmp;
527     }
528     
529     get value()
530     {
531         if (!this.isSomeImm)
532             throw new Error("Called .value for non-imm");
533         return this._value;
534     }
535     
536     get lowValue()
537     {
538         if (!this.isSomeBigImm)
539             throw new Error("Called .lowValue for non-big-imm");
540         return this._lowValue;
541     }
542     
543     get highValue()
544     {
545         if (!this.isSomeBigImm)
546             throw new Error("Called .highValue for non-big-imm");
547         return this._highValue;
548     }
549     
550     get base()
551     {
552         switch (this._kind) {
553         case Arg.Addr:
554         case Arg.Index:
555             return this._base;
556         default:
557             throw new Error("Called .base for non-address");
558         }
559     }
560     
561     get hasOffset() { return this.isMemory; }
562     
563     get offset()
564     {
565         switch (this._kind) {
566         case Arg.Addr:
567         case Arg.Index:
568         case Arg.Stack:
569         case Arg.CallArg:
570             return this._offset;
571         default:
572             throw new Error("Called .offset for non-address");
573         }
574     }
575     
576     get stackSlot()
577     {
578         if (this._kind != Arg.Stack)
579             throw new Error("Called .stackSlot for non-address");
580         return this._slot;
581     }
582     
583     get index()
584     {
585         if (this._kind != Arg.Index)
586             throw new Error("Called .index for non-Index");
587         return this._index;
588     }
589     
590     get scale()
591     {
592         if (this._kind != Arg.Index)
593             throw new Error("Called .scale for non-Index");
594         return this._scale;
595     }
596     
597     get logScale()
598     {
599         return Arg.logScale(this.scale);
600     }
601     
602     get width()
603     {
604         if (this._kind != Arg.Width)
605             throw new Error("Called .width for non-Width");
606         return this._width;
607     }
608     
609     get isGPTmp() { return this.isTmp && this.tmp.isGP; }
610     get isFPTmp() { return this.isTmp && this.tmp.isFP; }
611     
612     get isGP()
613     {
614         switch (this._kind) {
615         case Arg.Imm:
616         case Arg.BigImm:
617         case Arg.BitImm:
618         case Arg.BitImm64:
619         case Arg.Addr:
620         case Arg.Index:
621         case Arg.Stack:
622         case Arg.CallArg:
623         case Arg.RelCond:
624         case Arg.ResCond:
625         case Arg.DoubleCond:
626         case Arg.Width:
627         case Arg.Special:
628             return true;
629         case Arg.Tmp:
630             return this.isGPTmp;
631         case Arg.Invalid:
632             return false;
633         default:
634             throw new Error("Bad kind");
635         }
636     }
637     
638     get isFP()
639     {
640         switch (this._kind) {
641         case Arg.Imm:
642         case Arg.BitImm:
643         case Arg.BitImm64:
644         case Arg.RelCond:
645         case Arg.ResCond:
646         case Arg.DoubleCond:
647         case Arg.Width:
648         case Arg.Special:
649         case Arg.Invalid:
650             return false;
651         case Arg.Addr:
652         case Arg.Index:
653         case Arg.Stack:
654         case Arg.CallArg:
655         case Arg.BigImm:
656             return true;
657         case Arg.Tmp:
658             return this.isFPTmp;
659         default:
660             throw new Error("Bad kind");
661         }
662     }
663     
664     get hasType()
665     {
666         switch (this._kind) {
667         case Arg.Imm:
668         case Arg.BitImm:
669         case Arg.BitImm64:
670         case Arg.Tmp:
671             return true;
672         default:
673             return false;
674         }
675     }
676     
677     get type()
678     {
679         return this.isGP ? GP : FP;
680     }
681     
682     isType(type)
683     {
684         switch (type) {
685         case Arg.GP:
686             return this.isGP;
687         case Arg.FP:
688             return this.isFP;
689         default:
690             throw new Error("Bad type");
691         }
692     }
693     
694     isCompatibleType(other)
695     {
696         if (this.hasType)
697             return other.isType(this.type);
698         if (other.hasType)
699             return this.isType(other.type);
700         return true;
701     }
702     
703     get isGPR() { return this.isTmp && this.tmp.isGPR; }
704     get gpr() { return this.tmp.gpr; }
705     get isFPR() { return this.isTmp && this.tmp.isFPR; }
706     get fpr() { return this.tmp.fpr; }
707     get isReg() { return this.isTmp && this.tmp.isReg; }
708     get reg() { return this.tmp.reg; }
709     
710     static isValidImmForm(value)
711     {
712         return isRepresentableAsInt32(value);
713     }
714     static isValidBitImmForm(value)
715     {
716         return isRepresentableAsInt32(value);
717     }
718     static isValidBitImm64Form(value)
719     {
720         return isRepresentableAsInt32(value);
721     }
722     
723     static isValidAddrForm(offset, width)
724     {
725         return true;
726     }
727     
728     static isValidIndexForm(scale, offset, width)
729     {
730         if (!isValidScale(scale, width))
731             return false;
732         return true;
733     }
734     
735     isValidForm(width)
736     {
737         switch (this._kind) {
738         case Arg.Invalid:
739             return false;
740         case Arg.Tmp:
741             return true;
742         case Arg.Imm:
743             return Arg.isValidImmForm(this.value);
744         case Arg.BigImm:
745             return true;
746         case Arg.BitImm:
747             return Arg.isValidBitImmForm(this.value);
748         case Arg.BitImm64:
749             return Arg.isValidBitImm64Form(this.value);
750         case Arg.Addr:
751         case Arg.Stack:
752         case Arg.CallArg:
753             return Arg.isValidAddrForm(this.offset, width);
754         case Arg.Index:
755             return Arg.isValidIndexForm(this.scale, this.offset, width);
756         case Arg.RelCond:
757         case Arg.ResCond:
758         case Arg.DoubleCond:
759         case Arg.Width:
760         case Arg.Special:
761             return true;
762         default:
763             throw new Error("Bad kind");
764         }
765     }
766     
767     forEachTmpFast(func)
768     {
769         switch (this._kind) {
770         case Arg.Tmp: {
771             let replacement;
772             if (replacement = func(this._tmp))
773                 return Arg.createTmp(replacement);
774             break;
775         }
776         case Arg.Addr: {
777             let replacement;
778             if (replacement = func(this._base))
779                 return Arg.createAddr(replacement, this._offset);
780             break;
781         }
782         case Arg.Index: {
783             let baseReplacement = func(this._base);
784             let indexReplacement = func(this._index);
785             if (baseReplacement || indexReplacement) {
786                 return Arg.createIndex(
787                     baseReplacement ? baseReplacement : this._base,
788                     indexReplacement ? indexReplacement : this._index,
789                     this._scale, this._offset);
790             }
791             break;
792         }
793         default:
794             break;
795         }
796     }
797     
798     usesTmp(expectedTmp)
799     {
800         let usesTmp = false;
801         forEachTmpFast(tmp => {
802             usesTmp |= tmp == expectedTmp;
803         });
804         return usesTmp;
805     }
806     
807     forEachTmp(role, type, width, func)
808     {
809         switch (this._kind) {
810         case Arg.Tmp: {
811             let replacement;
812             if (replacement = func(this._tmp, role, type, width))
813                 return Arg.createTmp(replacement);
814             break;
815         }
816         case Arg.Addr: {
817             let replacement;
818             if (replacement = func(this._base, Arg.Use, GP, role == Arg.UseAddr ? width : Ptr))
819                 return Arg.createAddr(replacement, this._offset);
820             break;
821         }
822         case Arg.Index: {
823             let baseReplacement = func(this._base, Arg.Use, GP, role == Arg.UseAddr ? width : Ptr);
824             let indexReplacement = func(this._index, Arg.Use, GP, role == Arg.UseAddr ? width : Ptr);
825             if (baseReplacement || indexReplacement) {
826                 return Arg.createIndex(
827                     baseReplacement ? baseReplacement : this._base,
828                     indexReplacement ? indexReplacement : this._index,
829                     this._scale, this._offset);
830             }
831             break;
832         }
833         default:
834             break;
835         }
836     }
837     
838     is(thing) { return !!thing.extract(this); }
839     as(thing) { return thing.extract(this); }
840     
841     // This lets you say things like:
842     // arg.forEach(Tmp | Reg | Arg | StackSlot, ...)
843     //
844     // It's used for abstract liveness analysis.
845     forEachFast(thing, func)
846     {
847         return thing.forEachFast(this, func);
848     }
849     forEach(thing, role, type, width, func)
850     {
851         return thing.forEach(this, role, type, width, func);
852     }
853     
854     static extract(arg) { return arg; }
855     static forEachFast(arg, func) { return func(arg); }
856     static forEach(arg, role, type, width, func) { return func(arg, role, type, width); }
857
858     get condition()
859     {
860         switch (this._kind) {
861         case Arg.RelCond:
862         case Arg.ResCond:
863         case Arg.DoubleCond:
864             return this._condition;
865         default:
866             throw new Error("Called .condition for non-condition");
867         }
868     }
869     
870     get isInvertible()
871     {
872         switch (this._kind) {
873         case Arg.RelCond:
874         case Arg.DoubleCold:
875             return true;
876         case Arg.ResCond:
877             switch (this._condition) {
878             case Zero:
879             case NonZero:
880             case Signed:
881             case PositiveOrZero:
882                 return true;
883             default:
884                 return false;
885             }
886         default:
887             return false;
888         }
889     }
890     
891     static kindCode(kind)
892     {
893         switch (kind) {
894         case Arg.Invalid:
895             return 0;
896         case Arg.Tmp:
897             return 1;
898         case Arg.Imm:
899             return 2;
900         case Arg.BigImm:
901             return 3;
902         case Arg.BitImm:
903             return 4;
904         case Arg.BitImm64:
905             return 5;
906         case Arg.Addr:
907             return 6;
908         case Arg.Stack:
909             return 7;
910         case Arg.CallArg:
911             return 8;
912         case Arg.Index:
913             return 9;
914         case Arg.RelCond:
915             return 10;
916         case Arg.ResCond:
917             return 11;
918         case Arg.DoubleCond:
919             return 12;
920         case Arg.Special:
921             return 13;
922         case Arg.WidthArg:
923             return 14;
924         default:
925             throw new Error("Bad kind");
926         }
927     }
928     
929     hash()
930     {
931         let result = Arg.kindCode(this._kind);
932         
933         switch (this._kind) {
934         case Arg.Invalid:
935         case Arg.Special:
936             break;
937         case Arg.Tmp:
938             result += this._tmp.hash();
939             result |= 0;
940             break;
941         case Arg.Imm:
942         case Arg.BitImm:
943             result += this._value;
944             result |= 0;
945             break;
946         case Arg.BigImm:
947         case Arg.BitImm64:
948             result += this._lowValue;
949             result |= 0;
950             result += this._highValue;
951             result |= 0;
952             break;
953         case Arg.CallArg:
954             result += this._offset;
955             result |= 0;
956             break;
957         case Arg.RelCond:
958             result += relCondCode(this._condition);
959             result |= 0;
960             break;
961         case Arg.ResCond:
962             result += resCondCode(this._condition);
963             result |= 0;
964             break;
965         case Arg.DoubleCond:
966             result += doubleCondCode(this._condition);
967             result |= 0;
968             break;
969         case Arg.WidthArg:
970             result += this._width;
971             result |= 0;
972             break;
973         case Arg.Addr:
974             result += this._offset;
975             result |= 0;
976             result += this._base.hash();
977             result |= 0;
978             break;
979         case Arg.Index:
980             result += this._offset;
981             result |= 0;
982             result += this._scale;
983             result |= 0;
984             result += this._base.hash();
985             result |= 0;
986             result += this._index.hash();
987             result |= 0;
988             break;
989         case Arg.Stack:
990             result += this._offset;
991             result |= 0;
992             result += this.stackSlot.index;
993             result |= 0;
994             break;
995         }
996         
997         return result >>> 0;
998     }
999     
1000     toString()
1001     {
1002         switch (this._kind) {
1003         case Arg.Invalid:
1004             return "<invalid>";
1005         case Arg.Tmp:
1006             return this._tmp.toString();
1007         case Arg.Imm:
1008             return "$" + this._value;
1009         case Arg.BigImm:
1010         case Arg.BitImm64:
1011             return "$0x" + this._highValue.toString(16) + ":" + this._lowValue.toString(16);
1012         case Arg.Addr:
1013             return "" + (this._offset ? this._offset : "") + "(" + this._base + ")";
1014         case Arg.Index:
1015             return "" + (this._offset ? this._offset : "") + "(" + this._base +
1016                 "," + this._index + (this._scale == 1 ? "" : "," + this._scale) + ")";
1017         case Arg.Stack:
1018             return "" + (this._offset ? this._offset : "") + "(" + this._slot + ")";
1019         case Arg.CallArg:
1020             return "" + (this._offset ? this._offset : "") + "(callArg)";
1021         case Arg.RelCond:
1022         case Arg.ResCond:
1023         case Arg.DoubleCond:
1024             return symbolName(this._condition);
1025         case Arg.Special:
1026             return "special";
1027         case Arg.Width:
1028             return "" + this._value;
1029         default:
1030             throw new Error("Bad kind");
1031         }
1032     }
1033 }
1034
1035 // Arg kinds
1036 Arg.Invalid = Symbol("Invalid");
1037 Arg.Tmp = Symbol("Tmp");
1038 Arg.Imm = Symbol("Imm");
1039 Arg.BigImm = Symbol("BigImm");
1040 Arg.BitImm = Symbol("BitImm");
1041 Arg.BitImm64 = Symbol("BitImm64");
1042 Arg.Addr = Symbol("Addr");
1043 Arg.Stack = Symbol("Stack");
1044 Arg.CallArg = Symbol("CallArg");
1045 Arg.Index = Symbol("Index");
1046 Arg.RelCond = Symbol("RelCond");
1047 Arg.ResCond = Symbol("ResCond");
1048 Arg.DoubleCond = Symbol("DoubleCond");
1049 Arg.Special = Symbol("Special");
1050 Arg.Width = Symbol("Width");
1051
1052 // Arg roles
1053 Arg.Use = Symbol("Use");
1054 Arg.ColdUse = Symbol("ColdUse");
1055 Arg.LateUse = Symbol("LateUse");
1056 Arg.LateColdUse = Symbol("LateColdUse");
1057 Arg.Def = Symbol("Def");
1058 Arg.ZDef = Symbol("ZDef");
1059 Arg.UseDef = Symbol("UseDef");
1060 Arg.UseZDef = Symbol("UseZDef");
1061 Arg.EarlyDef = Symbol("EarlyDef");
1062 Arg.Scratch = Symbol("Scratch");
1063 Arg.UseAddr = Symbol("UseAddr");
1064