faslout.red 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. %
  2. % FASLOUT.RED - Top level of fasl file writer
  3. %
  4. % Author: Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 16 February 1982
  9. % Copyright (c) 1982 University of Utah
  10. %
  11. % <PSL.COMP>FASLOUT.RED.6, 16-Dec-82 12:49:59, Edit by KESSLER
  12. % Take out Semic!* as a fluid. Not used by anyone that I can see
  13. % and is already a global in RLISP.
  14. % <PSL.COMP>FASLOUT.RED.35, 10-Jun-82 10:41:18, Edit by GRISS
  15. % Made CompileUncompiledExpressions regular func
  16. % <PSL.COMP>FASLOUT.RED.12, 30-Apr-82 14:45:59, Edit by BENSON
  17. % Removed EVAL and IGNORE processing
  18. % <PSL.COMP>FASLOUT.RED.8, 29-Apr-82 06:23:18, Edit by GRISS
  19. % moved DEFINEROP call to RLISP-PARSER
  20. CompileTime <<
  21. flag('(CodeFileHeader CodeFileTrailer AllocateFaslSpaces),
  22. 'InternalFunction);
  23. load Fast!-Vector;
  24. >>;
  25. fluid '(!*WritingFaslFile
  26. !*Lower
  27. !*quiet_faslout
  28. DfPrint!*
  29. UncompiledExpressions!*
  30. ModuleName!*
  31. CodeOut!*
  32. InitOffset!*
  33. CurrentOffset!*
  34. FaslBlockEnd!*
  35. MaxFaslOffset!*
  36. BitTableOffset!*
  37. FaslFilenameFormat!*);
  38. FaslFilenameFormat!* := "%w.b";
  39. lisp procedure DfPrintFasl U; %. Called by TOP-loop, DFPRINT!*
  40. begin scalar Nam, Ty, Fn, !*WritingFaslFile;
  41. !*WritingFaslFile := T;
  42. if atom U then return NIL;
  43. Fn := car U;
  44. IF FN = 'PUTD THEN GOTO DB2;
  45. IF NOT (FN MEMQ '(DE DF DM DN)) THEN GOTO DB1;
  46. NAM:=CADR U;
  47. U:='LAMBDA . CDDR U;
  48. TY:=CDR ASSOC(FN, '((DE . EXPR)
  49. (DF . FEXPR)
  50. (DM . MACRO)
  51. (DN . NEXPR)));
  52. DB3: if Ty = 'MACRO then begin scalar !*Comp;
  53. PutD(Nam, Ty, U); % Macros get defined now
  54. end;
  55. if FlagP(Nam, 'Lose) then <<
  56. ErrorPrintF("*** %r has not been defined, because it is flagged LOSE",
  57. Nam);
  58. return NIL >>;
  59. IF FLAGP(TY,'COMPILE) THEN
  60. << PUT(NAM,'CFNTYPE,LIST TY);
  61. U := LIST('!*ENTRY,NAM,TY,LENGTH CADR U)
  62. . !&COMPROC(U, NAM);
  63. LAP U >>
  64. ELSE % should never happen
  65. SaveUncompiledExpression LIST('PUTD, MKQUOTE NAM,
  66. MKQUOTE TY,
  67. MKQUOTE U);
  68. if IGreaterP(Posn(), 0) then WriteChar char BLANK;
  69. Prin1 NAM;
  70. RETURN NIL;
  71. DB1: % Simple S-EXPRESSION, maybe EVAL it;
  72. IF NOT PAIRP U THEN RETURN NIL;
  73. if (Fn := get(car U, 'FaslPreEval)) then return Apply(Fn, list U)
  74. else if (Fn := GetD car U) and car Fn = 'MACRO then
  75. return DFPRINTFasl Apply(cdr Fn, list U);
  76. SaveUncompiledExpression U;
  77. RETURN NIL;
  78. DB2: NAM:=CADR U;
  79. TY:=CADDR U;
  80. FN:=CADDDR U;
  81. IF EQCAR(NAM,'QUOTE) THEN << NAM:=CADR NAM;
  82. IF EQCAR(TY,'QUOTE) THEN << TY:=CADR TY;
  83. IF PAIRP FN AND CAR FN MEMBER '(FUNCTION QUOTE) THEN << FN:=CADR FN;
  84. IF TY MEMQ '(EXPR FEXPR MACRO NEXPR) THEN
  85. << U:=FN; GOTO DB3 >> >> >> >>;
  86. GOTO DB1;
  87. END;
  88. FLAG ('(DEFLIST FLAG FLUID GLOBAL REMFLAG REMPROP UNFLUID),'EVAL);
  89. lisp procedure FaslPreEvalLoadTime U;
  90. DFPrintFasl cadr U; % remove LOADTIME
  91. put('LoadTime, 'FaslPreEval, 'FaslPreEvalLoadTime);
  92. put('BothTimes, 'FaslPreEval, 'FaslPreEvalLoadTime);
  93. put('StartupTime, 'FaslPreEval, 'FaslPreEvalLoadTime); % used in kernel
  94. % A few things to save space when loading
  95. put('Flag,
  96. 'FaslPreEval,
  97. function lambda U;
  98. if EqCar(second U, 'QUOTE) then
  99. DFPrintFasl('progn . for each X in second second U collect
  100. list('Flag1, MkQuote X, third U))
  101. else SaveUncompiledExpression U);
  102. put('fluid,
  103. 'FaslPreEval,
  104. function lambda U;
  105. if EqCar(second U, 'QUOTE) then
  106. DFPrintFasl('progn . for each X in second second U collect
  107. list('Fluid1, MkQuote X))
  108. else SaveUncompiledExpression U);
  109. put('global,
  110. 'FaslPreEval,
  111. function lambda U;
  112. if EqCar(second U, 'QUOTE) then
  113. DFPrintFasl('progn . for each X in second second U collect
  114. list('Global1, MkQuote X))
  115. else SaveUncompiledExpression U);
  116. put('DefList,
  117. 'FaslPreEval,
  118. function lambda U;
  119. if EqCar(second U, 'QUOTE) then
  120. DFPrintFasl('progn . for each X in second second U collect
  121. list('put, MkQuote first X,
  122. third U,
  123. MkQuote second X))
  124. else SaveUncompiledExpression U);
  125. put('ProgN,
  126. 'FaslPreEval,
  127. function lambda U;
  128. for each X in cdr U do
  129. DFPrintFasl X);
  130. put('LAP,
  131. 'FaslPreEval,
  132. function lambda U;
  133. if EqCar(cadr U, 'QUOTE) then Lap cadr cadr U
  134. else SaveUncompiledExpression U);
  135. UncompiledExpressions!* := NIL . NIL;
  136. lisp procedure SaveUncompiledExpression U;
  137. << if atom U then NIL
  138. else TConc(UncompiledExpressions!*, U);
  139. NIL >>;
  140. lisp procedure FaslOut FIL;
  141. << ModuleName!* := FIL;
  142. if not !*quiet_faslout then
  143. << if not FUnBoundP 'Begin1 then
  144. << Prin2T "FASLOUT: IN files; or type in expressions";
  145. Prin2T "When all done execute FASLEND;" >>
  146. else
  147. << Prin2T "FASLOUT: (DSKIN files) or type in expressions";
  148. Prin2T "When all done execute (FASLEND)" >> >>;
  149. CodeOut!* := BinaryOpenWrite BldMsg(FaslFilenameFormat!*, ModuleName!*);
  150. CodeFileHeader();
  151. DFPRINT!* := 'DFPRINTFasl;
  152. !*WritingFaslFile := T;
  153. !*DEFN := T >>;
  154. lisp procedure FaslEnd;
  155. if not !*WritingFaslFile then
  156. StdError "FASLEND not within FASLOUT"
  157. else
  158. << CompileUncompiledExpressions();
  159. UncompiledExpressions!* := NIL . NIL;
  160. CodeFileTrailer();
  161. BinaryClose CodeOut!*;
  162. DFPRINT!* := NIL;
  163. !*WritingFaslFile := NIL;
  164. !*DEFN := NIL >>;
  165. FLAG('(FaslEND), 'IGNORE);
  166. lisp procedure ComFile Filename;
  167. begin scalar !*Defn, !*WritingFaslFile, TestFile, FileBase, FileExt,
  168. I, N, DotFound, TestExts, !*quiet_faslout;
  169. if IDP Filename then
  170. (lambda (!*Lower); Filename := BldMsg("%w", Filename))(T);
  171. if not StringP Filename then return
  172. NonStringError(Filename, 'ComFile);
  173. N := ISizeS Filename;
  174. I := 0;
  175. while not DotFound and ILEQ(I, N) do
  176. << if IGetS(Filename, I) = char '!. then DotFound := T;
  177. I := IAdd1 I >>;
  178. if DotFound then
  179. << if not FileP Filename then return ContError(99, "Couldn't find file",
  180. ComFile Filename)
  181. else
  182. << FileBase := SubSeq(Filename, 0, I);
  183. FileExt := SubSeq(Filename, ISub1 I, IAdd1 N) >> >>
  184. else
  185. << TestExts := '(".build" ".sl" ".red");
  186. while not null TestExts
  187. and not FileP(TestFile := Concat(Filename, first TestExts)) do
  188. TestExts := rest TestExts;
  189. if null TestExts then return ContError(99,
  190. "Couldn't find file",
  191. ComFile Filename)
  192. else
  193. << FileExt := first TestExts;
  194. FileBase := Filename;
  195. Filename := TestFile >> >>;
  196. ErrorPrintF("*** Compiling %w", Filename);
  197. !*quiet_faslout := T;
  198. Faslout FileBase;
  199. if FileExt member '(".build" ".red") then
  200. EvIn list Filename
  201. else DskIn Filename;
  202. Faslend;
  203. return T;
  204. end;
  205. lisp procedure CompileUncompiledExpressions();
  206. << ErrorPrintF("*** Init code length is %w",
  207. length car UncompiledExpressions!*);
  208. DFPRINTFasl list('DE, '!*!*Fasl!*!*InitCode!*!*, '(),
  209. 'PROGN . car UncompiledExpressions!*) >>;
  210. lisp procedure CodeFileHeader();
  211. << BinaryWrite(CodeOut!*, const FASL_MAGIC_NUMBER);
  212. AllocateFaslSpaces() >>;
  213. fluid '(CodeBase!* BitTableBase!* OrderedIDList!* NextIDNumber!*);
  214. lisp procedure FindIDNumber U;
  215. begin scalar I;
  216. return if ILEQ(I := IDInf U, 128) then I
  217. else if (I := get(U, 'IDNumber)) then I
  218. else
  219. << put(U, 'IDNumber, I := NextIDNumber!*);
  220. OrderedIDList!* := TConc(OrderedIDList!*, U);
  221. NextIDNumber!* := IAdd1 NextIDNumber!*;
  222. I >>;
  223. end;
  224. lisp procedure CodeFileTrailer();
  225. begin scalar S;
  226. SystemFaslFixup();
  227. BinaryWrite(CodeOut!*, IDifference(ISub1 NextIDNumber!*, 2048));
  228. % Number of local IDs
  229. for each X in car OrderedIDList!* do
  230. << RemProp(X, 'IDNumber);
  231. X := StrInf ID2String X;
  232. S := StrLen X;
  233. BinaryWriteBlock(CodeOut!*, X, IAdd1 StrPack S) >>;
  234. BinaryWrite(CodeOut!*, % S is size in words
  235. S := IQuotient(IPlus2(CurrentOffset!*,
  236. ISub1 const AddressingUnitsPerItem),
  237. const AddressingUnitsPerItem));
  238. BinaryWrite(CodeOut!*, InitOffset!*);
  239. BinaryWriteBlock(CodeOut!*, CodeBase!*, S);
  240. BinaryWrite(CodeOut!*, S := IQuotient(IPlus2(BitTableOffset!*,
  241. ISub1 const BitTableEntriesPerWord),
  242. const BitTableEntriesPerWord));
  243. BinaryWriteBlock(CodeOut!*, BitTableBase!*, S);
  244. DelWArray(BitTableBase!*, FaslBlockEnd!*);
  245. end;
  246. lisp procedure UpdateBitTable(NumberOfEntries, FirstEntry);
  247. if !*WritingFaslFile then
  248. << PutBitTable(BitTableBase!*, BitTableOffset!*, FirstEntry);
  249. BitTableOffset!* := IAdd1 BitTableOffset!*;
  250. for I := 2 step 1 until NumberOfEntries do
  251. << PutBitTable(BitTableBase!*, BitTableOffset!*, 0);
  252. BitTableOffset!* := IAdd1 BitTableOffset!* >>;
  253. if IGreaterP(BitTableOffset!*, MaxFaslOffset!*) then
  254. FatalError "BPS exhausted during FaslOut; output file too large" >>;
  255. lisp procedure AllocateFaslSpaces();
  256. begin scalar B;
  257. B := GTWarray NIL; % how much is left?
  258. B := IDifference(B, IQuotient(B, 3));
  259. FaslBlockEnd!* := GTWArray 0; % pointer to top of space
  260. BitTableBase!* := GTWarray B; % take 2/3 of whatever's left
  261. CurrentOffset!* := 0;
  262. BitTableOffset!* := 0;
  263. CodeBase!*
  264. := Loc WGetV(BitTableBase!*, % split the space between
  265. IQuotient(B, % bit table and code
  266. IQuotient(const BitTableEntriesPerWord,
  267. const AddressingUnitsPerItem)));
  268. MaxFaslOffset!* := IDifference(FaslBlockEnd!*, CodeBase!*);
  269. OrderedIDList!* := NIL . NIL;
  270. NextIDNumber!* := 2048; % local IDs start at 2048
  271. end;
  272. END;