2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[Unique]{The @Unique@ data type}
6 @Uniques@ are used to distinguish entities in the compiler (@Ids@,
7 @Classes@, etc.) from each other. Thus, @Uniques@ are the basic
8 comparison key in the compiler.
10 If there is any single operation that needs to be fast, it is @Unique@
11 comparison. Unsurprisingly, there is quite a bit of huff-and-puff
14 Some of the other hair in this code is to be able to use a
15 ``splittable @UniqueSupply@'' if requested/possible (not standard
19 #include "HsVersions.h"
21 --<mkdependHS:friends> UniqSupply
24 Unique, Uniquable(..),
25 u2i, -- hack: used in UniqFM
27 pprUnique, pprUnique10, showUnique,
29 mkUnique, -- Used in UniqSupply
30 mkUniqueGrimily, -- Used in UniqSupply only!
32 incrUnique, -- Used for renumbering
33 initTyVarUnique, mkTyVarUnique,
36 -- now all the built-in Uniques (and functions to make them)
37 -- [the Oh-So-Wonderful Haskell module system wins again...]
43 getBuiltinUniques, mkBuiltinUnique,
44 mkPseudoUnique1, mkPseudoUnique2, mkPseudoUnique3,
46 absentErrorIdKey, -- alphabetical...
58 byteArrayPrimTyConKey,
71 enumFromThenClassOpKey,
72 enumFromThenToClassOpKey,
87 foreignObjPrimTyConKey,
93 fromIntegerClassOpKey,
94 fromRationalClassOpKey,
103 integerMinusOneIdKey,
109 irrefutPatErrorIdKey,
121 mutableArrayPrimTyConKey,
122 mutableByteArrayPrimTyConKey,
124 noDefaultMethodErrorIdKey,
125 nonExhaustiveGuardsErrorIdKey,
126 nonExplicitMethodErrorIdKey,
148 return2GMPsDataConKey,
150 returnIntAndGMPDataConKey,
151 returnIntAndGMPTyConKey,
167 stablePtrPrimTyConKey,
169 stateAndAddrPrimDataConKey,
170 stateAndAddrPrimTyConKey,
171 stateAndArrayPrimDataConKey,
172 stateAndArrayPrimTyConKey,
173 stateAndByteArrayPrimDataConKey,
174 stateAndByteArrayPrimTyConKey,
175 stateAndCharPrimDataConKey,
176 stateAndCharPrimTyConKey,
177 stateAndDoublePrimDataConKey,
178 stateAndDoublePrimTyConKey,
179 stateAndFloatPrimDataConKey,
180 stateAndFloatPrimTyConKey,
181 stateAndForeignObjPrimDataConKey,
182 stateAndForeignObjPrimTyConKey,
183 stateAndIntPrimDataConKey,
184 stateAndIntPrimTyConKey,
185 stateAndMutableArrayPrimDataConKey,
186 stateAndMutableArrayPrimTyConKey,
187 stateAndMutableByteArrayPrimDataConKey,
188 stateAndMutableByteArrayPrimTyConKey,
189 stateAndPtrPrimDataConKey,
190 stateAndPtrPrimTyConKey,
191 stateAndStablePtrPrimDataConKey,
192 stateAndStablePtrPrimTyConKey,
193 stateAndSynchVarPrimDataConKey,
194 stateAndSynchVarPrimTyConKey,
195 stateAndWordPrimDataConKey,
196 stateAndWordPrimTyConKey,
202 synchVarPrimTyConKey,
208 unpackCStringAppendIdKey,
209 unpackCStringFoldrIdKey,
229 , mutableByteArrayTyConKey
233 #if __GLASGOW_HASKELL__ <= 201
238 import PrelBase ( Char(..), chr, ord )
248 %************************************************************************
250 \subsection[Unique-type]{@Unique@ type and operations}
252 %************************************************************************
254 The @Chars@ are ``tag letters'' that identify the @UniqueSupply@.
255 Fast comparison is everything on @Uniques@:
258 data Unique = MkUnique Int#
260 class Uniquable a where
261 uniqueOf :: a -> Unique
265 u2i :: Unique -> FAST_INT
269 Now come the functions which construct uniques from their pieces, and vice versa.
270 The stuff about unique *supplies* is handled further down this module.
273 mkUnique :: Char -> Int -> Unique -- Builds a unique from pieces
274 unpkUnique :: Unique -> (Char, Int) -- The reverse
276 mkUniqueGrimily :: Int# -> Unique -- A trap-door for UniqSupply
278 incrUnique :: Unique -> Unique
283 mkUniqueGrimily x = MkUnique x
285 incrUnique (MkUnique i) = MkUnique (i +# 1#)
287 -- pop the Char in the top 8 bits of the Unique(Supply)
289 -- No 64-bit bugs here, as long as we have at least 32 bits. --JSM
295 mkUnique (C# c) (I# i)
296 = MkUnique (w2i (((i2w (ord# c)) `shiftL#` (i2w_s 24#)) `or#` (i2w i)))
298 unpkUnique (MkUnique u)
300 tag = C# (chr# (w2i ((i2w u) `shiftr` (i2w_s 24#))))
301 i = I# (w2i ((i2w u) `and#` (i2w 16777215#){-``0x00ffffff''-}))
305 shiftr x y = shiftRA# x y
308 %************************************************************************
310 \subsection[Unique-instances]{Instance declarations for @Unique@}
312 %************************************************************************
314 And the whole point (besides uniqueness) is fast equality. We don't
315 use `deriving' because we want {\em precise} control of ordering
316 (equality on @Uniques@ is v common).
319 eqUnique (MkUnique u1) (MkUnique u2) = u1 ==# u2
320 ltUnique (MkUnique u1) (MkUnique u2) = u1 <# u2
321 leUnique (MkUnique u1) (MkUnique u2) = u1 <=# u2
323 cmpUnique (MkUnique u1) (MkUnique u2)
324 = if u1 ==# u2 then EQ_ else if u1 <# u2 then LT_ else GT_
326 instance Eq Unique where
327 a == b = eqUnique a b
328 a /= b = not (eqUnique a b)
330 instance Ord Unique where
332 a <= b = leUnique a b
333 a > b = not (leUnique a b)
334 a >= b = not (ltUnique a b)
335 _tagCmp a b = case cmpUnique a b of { LT_ -> _LT; EQ_ -> _EQ; GT__ -> _GT }
337 instance Ord3 Unique where
341 instance Uniquable Unique where
345 We do sometimes make strings with @Uniques@ in them:
347 pprUnique, pprUnique10 :: Unique -> Doc
350 = case unpkUnique uniq of
351 (tag, u) -> finish_ppr tag u (iToBase62 u)
353 pprUnique10 uniq -- in base-10, dudes
354 = case unpkUnique uniq of
355 (tag, u) -> finish_ppr tag u (int u)
357 finish_ppr 't' u pp_u | u < 26
358 = -- Special case to make v common tyvars, t1, t2, ...
359 -- come out as a, b, ... (shorter, easier to read)
360 char (chr (ord 'a' + u))
361 finish_ppr tag u pp_u = char tag <> pp_u
363 showUnique :: Unique -> String
364 showUnique uniq = show (pprUnique uniq)
366 instance Outputable Unique where
367 ppr sty u = pprUnique u
369 instance Text Unique where
370 showsPrec p uniq rest = showUnique uniq
373 %************************************************************************
375 \subsection[Utils-base62]{Base-62 numbers}
377 %************************************************************************
379 A character-stingy way to read/write numbers (notably Uniques).
380 The ``62-its'' are \tr{[0-9a-zA-Z]}. We don't handle negative Ints.
381 Code stolen from Lennart.
383 #if __GLASGOW_HASKELL__ == 201
384 # define BYTE_ARRAY GHCbase.ByteArray
385 # define RUN_ST GHCbase.runST
386 # define AND_THEN >>=
387 # define AND_THEN_ >>
388 # define RETURN return
389 #elif __GLASGOW_HASKELL__ >= 202
390 # define BYTE_ARRAY GlaExts.ByteArray
391 # define RUN_ST ST.runST
392 # define AND_THEN >>=
393 # define AND_THEN_ >>
394 # define RETURN return
396 # define BYTE_ARRAY _ByteArray
397 # define RUN_ST _runST
398 # define AND_THEN `thenStrictlyST`
399 # define AND_THEN_ `seqStrictlyST`
400 # define RETURN returnStrictlyST
403 iToBase62 :: Int -> Doc
408 bytes = case chars62 of { BYTE_ARRAY bounds_who_needs_'em bytes -> bytes }
411 case (indexCharArray# bytes n#) of { c ->
414 case (quotRem n 62) of { (q, I# r#) ->
415 case (indexCharArray# bytes r#) of { c ->
416 (<>) (iToBase62 q) (char (C# c)) }}
418 -- keep this at top level! (bug on 94/10/24 WDP)
419 chars62 :: BYTE_ARRAY Int
422 newCharArray (0, 61) AND_THEN \ ch_array ->
423 fill_in ch_array 0 62 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
425 unsafeFreezeByteArray ch_array
428 fill_in ch_array i lim str
432 = writeCharArray ch_array i (str !! i) AND_THEN_
433 fill_in ch_array (i+1) lim str
436 %************************************************************************
438 \subsection[Uniques-prelude]{@Uniques@ for wired-in Prelude things}
440 %************************************************************************
442 Allocation of unique supply characters:
443 v,t,u : for renumbering value-, type- and usage- vars.
444 other a-z: lower case chars for unique supplies (see Main.lhs)
446 C-E: pseudo uniques (used in native-code generator)
447 _: unifiable tyvars (above)
448 1-8: prelude things below
451 mkAlphaTyVarUnique i = mkUnique '1' i
453 mkPreludeClassUnique i = mkUnique '2' i
454 mkPreludeTyConUnique i = mkUnique '3' i
455 mkTupleTyConUnique a = mkUnique '4' a
457 mkPreludeDataConUnique i = mkUnique '5' i -- must be alphabetic
458 mkTupleDataConUnique a = mkUnique '6' a -- ditto (*may* be used in C labels)
460 mkPrimOpIdUnique op = mkUnique '7' op
461 mkPreludeMiscIdUnique i = mkUnique '8' i
463 -- The "tyvar uniques" print specially nicely: a, b, c, etc.
464 -- See pprUnique for details
466 initTyVarUnique :: Unique
467 initTyVarUnique = mkUnique 't' 0
469 mkTyVarUnique :: Int -> Unique
470 mkTyVarUnique n = mkUnique 't' n
472 initTidyUniques :: (Unique, Unique) -- Global and local
473 initTidyUniques = (mkUnique 'g' 0, mkUnique 'x' 0)
475 mkPseudoUnique1, mkPseudoUnique2, mkPseudoUnique3,
476 mkBuiltinUnique :: Int -> Unique
478 mkBuiltinUnique i = mkUnique 'B' i
479 mkPseudoUnique1 i = mkUnique 'C' i -- used for uniqueOf on Regs
480 mkPseudoUnique2 i = mkUnique 'D' i -- ditto
481 mkPseudoUnique3 i = mkUnique 'E' i -- ditto
483 getBuiltinUniques :: Int -> [Unique]
484 getBuiltinUniques n = map (mkUnique 'B') [1 .. n]
487 %************************************************************************
489 \subsubsection[Uniques-prelude-Classes]{@Uniques@ for wired-in @Classes@}
491 %************************************************************************
494 boundedClassKey = mkPreludeClassUnique 1
495 enumClassKey = mkPreludeClassUnique 2
496 eqClassKey = mkPreludeClassUnique 3
497 evalClassKey = mkPreludeClassUnique 4
498 floatingClassKey = mkPreludeClassUnique 5
499 fractionalClassKey = mkPreludeClassUnique 6
500 integralClassKey = mkPreludeClassUnique 7
501 monadClassKey = mkPreludeClassUnique 8
502 monadZeroClassKey = mkPreludeClassUnique 9
503 monadPlusClassKey = mkPreludeClassUnique 10
504 functorClassKey = mkPreludeClassUnique 11
505 numClassKey = mkPreludeClassUnique 12
506 ordClassKey = mkPreludeClassUnique 13
507 readClassKey = mkPreludeClassUnique 14
508 realClassKey = mkPreludeClassUnique 15
509 realFloatClassKey = mkPreludeClassUnique 16
510 realFracClassKey = mkPreludeClassUnique 17
511 showClassKey = mkPreludeClassUnique 18
513 cCallableClassKey = mkPreludeClassUnique 19
514 cReturnableClassKey = mkPreludeClassUnique 20
516 ixClassKey = mkPreludeClassUnique 21
517 allClassKey = mkPreludeClassUnique 22 -- Pseudo class used for universal quantification
520 %************************************************************************
522 \subsubsection[Uniques-prelude-TyCons]{@Uniques@ for wired-in @TyCons@}
524 %************************************************************************
527 addrPrimTyConKey = mkPreludeTyConUnique 1
528 addrTyConKey = mkPreludeTyConUnique 2
529 arrayPrimTyConKey = mkPreludeTyConUnique 3
530 boolTyConKey = mkPreludeTyConUnique 4
531 byteArrayPrimTyConKey = mkPreludeTyConUnique 5
532 charPrimTyConKey = mkPreludeTyConUnique 7
533 charTyConKey = mkPreludeTyConUnique 8
534 doublePrimTyConKey = mkPreludeTyConUnique 9
535 doubleTyConKey = mkPreludeTyConUnique 10
536 floatPrimTyConKey = mkPreludeTyConUnique 11
537 floatTyConKey = mkPreludeTyConUnique 12
538 funTyConKey = mkPreludeTyConUnique 13
539 intPrimTyConKey = mkPreludeTyConUnique 14
540 intTyConKey = mkPreludeTyConUnique 15
541 integerTyConKey = mkPreludeTyConUnique 16
542 liftTyConKey = mkPreludeTyConUnique 17
543 listTyConKey = mkPreludeTyConUnique 18
544 foreignObjPrimTyConKey = mkPreludeTyConUnique 19
545 foreignObjTyConKey = mkPreludeTyConUnique 20
546 mutableArrayPrimTyConKey = mkPreludeTyConUnique 21
547 mutableByteArrayPrimTyConKey = mkPreludeTyConUnique 22
548 orderingTyConKey = mkPreludeTyConUnique 23
549 synchVarPrimTyConKey = mkPreludeTyConUnique 24
550 ratioTyConKey = mkPreludeTyConUnique 25
551 rationalTyConKey = mkPreludeTyConUnique 26
552 realWorldTyConKey = mkPreludeTyConUnique 27
553 return2GMPsTyConKey = mkPreludeTyConUnique 28
554 returnIntAndGMPTyConKey = mkPreludeTyConUnique 29
555 stablePtrPrimTyConKey = mkPreludeTyConUnique 30
556 stablePtrTyConKey = mkPreludeTyConUnique 31
557 stateAndAddrPrimTyConKey = mkPreludeTyConUnique 32
558 stateAndArrayPrimTyConKey = mkPreludeTyConUnique 33
559 stateAndByteArrayPrimTyConKey = mkPreludeTyConUnique 34
560 stateAndCharPrimTyConKey = mkPreludeTyConUnique 35
561 stateAndDoublePrimTyConKey = mkPreludeTyConUnique 36
562 stateAndFloatPrimTyConKey = mkPreludeTyConUnique 37
563 stateAndIntPrimTyConKey = mkPreludeTyConUnique 38
564 stateAndForeignObjPrimTyConKey = mkPreludeTyConUnique 39
565 stateAndMutableArrayPrimTyConKey = mkPreludeTyConUnique 40
566 stateAndMutableByteArrayPrimTyConKey = mkPreludeTyConUnique 41
567 stateAndSynchVarPrimTyConKey = mkPreludeTyConUnique 42
568 stateAndPtrPrimTyConKey = mkPreludeTyConUnique 43
569 stateAndStablePtrPrimTyConKey = mkPreludeTyConUnique 44
570 stateAndWordPrimTyConKey = mkPreludeTyConUnique 45
571 statePrimTyConKey = mkPreludeTyConUnique 46
572 stateTyConKey = mkPreludeTyConUnique 47
573 mutableByteArrayTyConKey = mkPreludeTyConUnique 48
574 stTyConKey = mkPreludeTyConUnique 49
575 stRetTyConKey = mkPreludeTyConUnique 50
576 ioTyConKey = mkPreludeTyConUnique 51
577 ioResultTyConKey = mkPreludeTyConUnique 52
578 byteArrayTyConKey = mkPreludeTyConUnique 53
579 wordPrimTyConKey = mkPreludeTyConUnique 54
580 wordTyConKey = mkPreludeTyConUnique 55
581 voidTyConKey = mkPreludeTyConUnique 56
584 %************************************************************************
586 \subsubsection[Uniques-prelude-DataCons]{@Uniques@ for wired-in @DataCons@}
588 %************************************************************************
591 addrDataConKey = mkPreludeDataConUnique 1
592 buildDataConKey = mkPreludeDataConUnique 2
593 charDataConKey = mkPreludeDataConUnique 4
594 consDataConKey = mkPreludeDataConUnique 5
595 doubleDataConKey = mkPreludeDataConUnique 6
596 eqDataConKey = mkPreludeDataConUnique 7
597 falseDataConKey = mkPreludeDataConUnique 8
598 floatDataConKey = mkPreludeDataConUnique 9
599 gtDataConKey = mkPreludeDataConUnique 10
600 intDataConKey = mkPreludeDataConUnique 11
601 integerDataConKey = mkPreludeDataConUnique 12
602 liftDataConKey = mkPreludeDataConUnique 13
603 ltDataConKey = mkPreludeDataConUnique 14
604 foreignObjDataConKey = mkPreludeDataConUnique 15
605 nilDataConKey = mkPreludeDataConUnique 18
606 ratioDataConKey = mkPreludeDataConUnique 21
607 return2GMPsDataConKey = mkPreludeDataConUnique 22
608 returnIntAndGMPDataConKey = mkPreludeDataConUnique 23
609 stablePtrDataConKey = mkPreludeDataConUnique 24
610 stateAndAddrPrimDataConKey = mkPreludeDataConUnique 25
611 stateAndArrayPrimDataConKey = mkPreludeDataConUnique 26
612 stateAndByteArrayPrimDataConKey = mkPreludeDataConUnique 27
613 stateAndCharPrimDataConKey = mkPreludeDataConUnique 28
614 stateAndDoublePrimDataConKey = mkPreludeDataConUnique 29
615 stateAndFloatPrimDataConKey = mkPreludeDataConUnique 30
616 stateAndIntPrimDataConKey = mkPreludeDataConUnique 31
617 stateAndForeignObjPrimDataConKey = mkPreludeDataConUnique 32
618 stateAndMutableArrayPrimDataConKey = mkPreludeDataConUnique 33
619 stateAndMutableByteArrayPrimDataConKey = mkPreludeDataConUnique 34
620 stateAndSynchVarPrimDataConKey = mkPreludeDataConUnique 35
621 stateAndPtrPrimDataConKey = mkPreludeDataConUnique 36
622 stateAndStablePtrPrimDataConKey = mkPreludeDataConUnique 37
623 stateAndWordPrimDataConKey = mkPreludeDataConUnique 38
624 stateDataConKey = mkPreludeDataConUnique 39
625 trueDataConKey = mkPreludeDataConUnique 40
626 wordDataConKey = mkPreludeDataConUnique 41
627 stDataConKey = mkPreludeDataConUnique 42
628 stRetDataConKey = mkPreludeDataConUnique 43
629 ioDataConKey = mkPreludeDataConUnique 44
630 ioOkDataConKey = mkPreludeDataConUnique 45
631 ioFailDataConKey = mkPreludeDataConUnique 46
634 %************************************************************************
636 \subsubsection[Uniques-prelude-Ids]{@Uniques@ for wired-in @Ids@ (except @DataCons@)}
638 %************************************************************************
641 absentErrorIdKey = mkPreludeMiscIdUnique 1
642 andandIdKey = mkPreludeMiscIdUnique 2
643 appendIdKey = mkPreludeMiscIdUnique 3
644 augmentIdKey = mkPreludeMiscIdUnique 4
645 buildIdKey = mkPreludeMiscIdUnique 5
646 composeIdKey = mkPreludeMiscIdUnique 6
647 errorIdKey = mkPreludeMiscIdUnique 7
648 foldlIdKey = mkPreludeMiscIdUnique 8
649 foldrIdKey = mkPreludeMiscIdUnique 9
650 forkIdKey = mkPreludeMiscIdUnique 10
651 int2IntegerIdKey = mkPreludeMiscIdUnique 11
652 integerMinusOneIdKey = mkPreludeMiscIdUnique 12
653 integerPlusOneIdKey = mkPreludeMiscIdUnique 13
654 integerPlusTwoIdKey = mkPreludeMiscIdUnique 14
655 integerZeroIdKey = mkPreludeMiscIdUnique 15
656 irrefutPatErrorIdKey = mkPreludeMiscIdUnique 16
657 lexIdKey = mkPreludeMiscIdUnique 17
658 noDefaultMethodErrorIdKey = mkPreludeMiscIdUnique 20
659 nonExhaustiveGuardsErrorIdKey = mkPreludeMiscIdUnique 21
660 nonExplicitMethodErrorIdKey = mkPreludeMiscIdUnique 22
661 notIdKey = mkPreludeMiscIdUnique 23
662 packCStringIdKey = mkPreludeMiscIdUnique 24
663 parErrorIdKey = mkPreludeMiscIdUnique 25
664 parIdKey = mkPreludeMiscIdUnique 26
665 patErrorIdKey = mkPreludeMiscIdUnique 27
666 readParenIdKey = mkPreludeMiscIdUnique 28
667 realWorldPrimIdKey = mkPreludeMiscIdUnique 29
668 recConErrorIdKey = mkPreludeMiscIdUnique 30
669 recUpdErrorIdKey = mkPreludeMiscIdUnique 31
670 runSTIdKey = mkPreludeMiscIdUnique 32
671 seqIdKey = mkPreludeMiscIdUnique 33
672 showParenIdKey = mkPreludeMiscIdUnique 34
673 showSpaceIdKey = mkPreludeMiscIdUnique 35
674 showStringIdKey = mkPreludeMiscIdUnique 36
675 traceIdKey = mkPreludeMiscIdUnique 37
676 unpackCString2IdKey = mkPreludeMiscIdUnique 38
677 unpackCStringAppendIdKey = mkPreludeMiscIdUnique 39
678 unpackCStringFoldrIdKey = mkPreludeMiscIdUnique 40
679 unpackCStringIdKey = mkPreludeMiscIdUnique 41
680 voidIdKey = mkPreludeMiscIdUnique 42
681 ushowListIdKey = mkPreludeMiscIdUnique 43
682 ureadListIdKey = mkPreludeMiscIdUnique 44
684 copyableIdKey = mkPreludeMiscIdUnique 45
685 noFollowIdKey = mkPreludeMiscIdUnique 46
686 parAtAbsIdKey = mkPreludeMiscIdUnique 47
687 parAtForNowIdKey = mkPreludeMiscIdUnique 48
688 parAtIdKey = mkPreludeMiscIdUnique 49
689 parAtRelIdKey = mkPreludeMiscIdUnique 50
690 parGlobalIdKey = mkPreludeMiscIdUnique 51
691 parLocalIdKey = mkPreludeMiscIdUnique 52
694 Certain class operations from Prelude classes. They get
695 their own uniques so we can look them up easily when we want
696 to conjure them up during type checking.
698 fromIntClassOpKey = mkPreludeMiscIdUnique 53
699 fromIntegerClassOpKey = mkPreludeMiscIdUnique 54
700 minusClassOpKey = mkPreludeMiscIdUnique 55
701 fromRationalClassOpKey = mkPreludeMiscIdUnique 56
702 enumFromClassOpKey = mkPreludeMiscIdUnique 57
703 enumFromThenClassOpKey = mkPreludeMiscIdUnique 58
704 enumFromToClassOpKey = mkPreludeMiscIdUnique 59
705 enumFromThenToClassOpKey= mkPreludeMiscIdUnique 60
706 eqClassOpKey = mkPreludeMiscIdUnique 61
707 geClassOpKey = mkPreludeMiscIdUnique 62
708 zeroClassOpKey = mkPreludeMiscIdUnique 63
709 thenMClassOpKey = mkPreludeMiscIdUnique 64 -- (>>=)
710 unboundKey = mkPreludeMiscIdUnique 65 -- Just a place holder for unbound
711 -- variables produced by the renamer
712 fromEnumClassOpKey = mkPreludeMiscIdUnique 66
714 mainKey = mkPreludeMiscIdUnique 67
715 returnMClassOpKey = mkPreludeMiscIdUnique 68
716 otherwiseIdKey = mkPreludeMiscIdUnique 69
717 toEnumClassOpKey = mkPreludeMiscIdUnique 70