ccomp.red 115 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320
  1. % "ccomp.red" Copyright 1991-1996, Codemist Ltd
  2. %
  3. % Compiler that turns Lisp code into C in a way that fits in
  4. % with the conventions used with CSL/CCL
  5. %
  6. % A C Norman
  7. %
  8. symbolic;
  9. global '(!*fastvector !*unsafecar);
  10. flag('(fastvector unsafecar), 'switch);
  11. %
  12. % I start with some utility functions that provide something
  13. % related to a FORMAT or PRINTF facility
  14. %
  15. fluid '(C_file L_file O_file L_contents File_name);
  16. symbolic macro procedure c!:printf u;
  17. % inspired by the C printf function, but much less general.
  18. % This macro is to provide the illusion that printf can take an
  19. % arbitrary number of arguments.
  20. list('c!:printf1, cadr u, 'list . cddr u);
  21. symbolic procedure c!:printf1(fmt, args);
  22. % this is the inner works of print formatting.
  23. % the special sequences that can occur in format strings are
  24. % %s use princ (to print a name?)
  25. % %d use princ (to print a number?)
  26. % %a use prin
  27. % %t do a ttab()
  28. % %v print a variable.... magic for this compiler
  29. % \n do a terpri()
  30. % \q princ '!" to display quote marks
  31. begin
  32. scalar a, c;
  33. fmt := explode2 fmt;
  34. while fmt do <<
  35. c := car fmt;
  36. fmt := cdr fmt;
  37. if c = '!\ and (car fmt = '!n or car fmt = '!N) then <<
  38. terpri();
  39. fmt := cdr fmt >>
  40. else if c = '!\ and (car fmt = '!q or car fmt = '!Q) then <<
  41. princ '!";
  42. fmt := cdr fmt >>
  43. else if c = '!% then <<
  44. c := car fmt;
  45. if null args then a := 'missing_arg
  46. else a := car args;
  47. if c = '!v or c = '!V then
  48. if flagp(a, 'c!:live_across_call) then <<
  49. princ "stack[";
  50. princ(-get(a, 'c!:location));
  51. princ "]" >>
  52. else princ a
  53. else if c = '!a or c = '!A then prin a
  54. else if c = '!t or c = '!T then ttab a
  55. else princ a;
  56. if args then args := cdr args;
  57. fmt := cdr fmt >>
  58. else princ c >>
  59. end;
  60. % This establishes a default handler for each special form so that
  61. % any that I forget to treat more directly will cause a tidy error
  62. % if found in compiled code.
  63. symbolic procedure c!:cspecform(x, env);
  64. error(0, list("special form", x));
  65. << put('and, 'c!:code, function c!:cspecform);
  66. !#if common!-lisp!-mode
  67. put('block, 'c!:code, function c!:cspecform);
  68. !#endif
  69. put('catch, 'c!:code, function c!:cspecform);
  70. put('compiler!-let, 'c!:code, function c!:cspecform);
  71. put('cond, 'c!:code, function c!:cspecform);
  72. put('declare, 'c!:code, function c!:cspecform);
  73. put('de, 'c!:code, function c!:cspecform);
  74. !#if common!-lisp!-mode
  75. put('defun, 'c!:code, function c!:cspecform);
  76. !#endif
  77. put('eval!-when, 'c!:code, function c!:cspecform);
  78. put('flet, 'c!:code, function c!:cspecform);
  79. put('function, 'c!:code, function c!:cspecform);
  80. put('go, 'c!:code, function c!:cspecform);
  81. put('if, 'c!:code, function c!:cspecform);
  82. put('labels, 'c!:code, function c!:cspecform);
  83. !#if common!-lisp!-mode
  84. put('let, 'c!:code, function c!:cspecform);
  85. !#else
  86. put('!~let, 'c!:code, function c!:cspecform);
  87. !#endif
  88. put('let!*, 'c!:code, function c!:cspecform);
  89. put('list, 'c!:code, function c!:cspecform);
  90. put('list!*, 'c!:code, function c!:cspecform);
  91. put('macrolet, 'c!:code, function c!:cspecform);
  92. put('multiple!-value!-call, 'c!:code, function c!:cspecform);
  93. put('multiple!-value!-prog1, 'c!:code, function c!:cspecform);
  94. put('or, 'c!:code, function c!:cspecform);
  95. put('prog, 'c!:code, function c!:cspecform);
  96. put('prog!*, 'c!:code, function c!:cspecform);
  97. put('prog1, 'c!:code, function c!:cspecform);
  98. put('prog2, 'c!:code, function c!:cspecform);
  99. put('progn, 'c!:code, function c!:cspecform);
  100. put('progv, 'c!:code, function c!:cspecform);
  101. put('quote, 'c!:code, function c!:cspecform);
  102. put('return, 'c!:code, function c!:cspecform);
  103. put('return!-from, 'c!:code, function c!:cspecform);
  104. put('setq, 'c!:code, function c!:cspecform);
  105. put('tagbody, 'c!:code, function c!:cspecform);
  106. put('the, 'c!:code, function c!:cspecform);
  107. put('throw, 'c!:code, function c!:cspecform);
  108. put('unless, 'c!:code, function c!:cspecform);
  109. put('unwind!-protect, 'c!:code, function c!:cspecform);
  110. put('when, 'c!:code, function c!:cspecform) >>;
  111. fluid '(current_procedure current_args current_block current_contents
  112. all_blocks registers stacklocs);
  113. fluid '(available used);
  114. available := used := nil;
  115. symbolic procedure c!:reset_gensyms();
  116. << remflag(used, 'c!:live_across_call);
  117. remflag(used, 'c!:visited);
  118. while used do <<
  119. remprop(car used, 'c!:contents);
  120. remprop(car used, 'c!:why);
  121. remprop(car used, 'c!:where_to);
  122. remprop(car used, 'c!:count);
  123. remprop(car used, 'c!:live);
  124. remprop(car used, 'c!:clash);
  125. remprop(car used, 'c!:chosen);
  126. remprop(car used, 'c!:location);
  127. if plist car used then begin
  128. scalar o; o := wrs nil;
  129. princ "+++++ "; prin car used; princ " ";
  130. prin plist car used; terpri();
  131. wrs o end;
  132. available := car used . available;
  133. used := cdr used >> >>;
  134. !#if common!-lisp!-mode
  135. fluid '(my_gensym_counter);
  136. my_gensym_counter := 0;
  137. !#endif
  138. symbolic procedure c!:my_gensym();
  139. begin
  140. scalar w;
  141. if available then << w := car available; available := cdr available >>
  142. !#if common!-lisp!-mode
  143. else w := compress1
  144. ('!v . explodec (my_gensym_counter := my_gensym_counter + 1));
  145. !#else
  146. else w := gensym1 "v";
  147. !#endif
  148. used := w . used;
  149. if plist w then << princ "????? "; prin w; princ " => "; prin plist w; terpri() >>;
  150. return w
  151. end;
  152. symbolic procedure c!:newreg();
  153. begin
  154. scalar r;
  155. r := c!:my_gensym();
  156. registers := r . registers;
  157. return r
  158. end;
  159. symbolic procedure c!:startblock s;
  160. << current_block := s;
  161. current_contents := nil
  162. >>;
  163. symbolic procedure c!:outop(a,b,c,d);
  164. if current_block then
  165. current_contents := list(a,b,c,d) . current_contents;
  166. symbolic procedure c!:endblock(why, where_to);
  167. if current_block then <<
  168. % Note that the operations within a block are in reversed order.
  169. put(current_block, 'c!:contents, current_contents);
  170. put(current_block, 'c!:why, why);
  171. put(current_block, 'c!:where_to, where_to);
  172. all_blocks := current_block . all_blocks;
  173. current_contents := nil;
  174. current_block := nil >>;
  175. %
  176. % Now for a general driver for compilation
  177. %
  178. symbolic procedure c!:cval_inner(x, env);
  179. begin
  180. scalar helper;
  181. % NB use the "improve" function from the regular compiler here...
  182. x := s!:improve x;
  183. % atoms and embedded lambda expressions need their own treatment.
  184. if atom x then return c!:catom(x, env)
  185. else if eqcar(car x, 'lambda) then
  186. return c!:clambda(cadar x, 'progn . cddar x, cdr x, env)
  187. % a c!:code property gives direct control over compilation
  188. else if helper := get(car x, 'c!:code) then
  189. return funcall(helper, x, env)
  190. % compiler-macros take precedence over regular macros, so that I can
  191. % make special expansions in the context of compilation. Only used if the
  192. % expansion is non-nil
  193. else if (helper := get(car x, 'c!:compile_macro)) and
  194. (helper := funcall(helper, x)) then
  195. return c!:cval(helper, env)
  196. % regular Lisp macros get expanded
  197. else if idp car x and (helper := macro!-function car x) then
  198. return c!:cval(funcall(helper, x), env)
  199. % anything not recognised as special will be turned into a
  200. % function call, but there will still be special cases, such as
  201. % calls to the current function, calls into the C-coded kernel, etc.
  202. else return c!:ccall(car x, cdr x, env)
  203. end;
  204. symbolic procedure c!:cval(x, env);
  205. begin
  206. scalar r;
  207. r := c!:cval_inner(x, env);
  208. if r and not member!*!*(r, registers) then
  209. error(0, list(r, "not a register", x));
  210. return r
  211. end;
  212. symbolic procedure c!:clambda(bvl, body, args, env);
  213. begin
  214. scalar w, fluids, env1;
  215. env1 := car env;
  216. w := for each a in args collect c!:cval(a, env);
  217. for each v in bvl do <<
  218. if globalp v then begin scalar oo;
  219. oo := wrs nil;
  220. princ "+++++ "; prin v;
  221. princ " converted from GLOBAL to FLUID"; terpri();
  222. wrs oo;
  223. unglobal list v;
  224. fluid list v end;
  225. if fluidp v then <<
  226. fluids := (v . c!:newreg()) . fluids;
  227. flag(list cdar fluids, 'c!:live_across_call); % silly if not
  228. env1 := ('c!:dummy!:name . cdar fluids) . env1;
  229. c!:outop('ldrglob, cdar fluids, v, c!:find_literal v);
  230. c!:outop('strglob, car w, v, c!:find_literal v) >>
  231. else <<
  232. env1 := (v . c!:newreg()) . env1;
  233. c!:outop('movr, cdar env1, nil, car w) >>;
  234. w := cdr w >>;
  235. if fluids then c!:outop('fluidbind, nil, nil, fluids);
  236. env := env1 . append(fluids, cdr env);
  237. w := c!:cval(body, env);
  238. for each v in fluids do
  239. c!:outop('strglob, cdr v, car v, c!:find_literal car v);
  240. return w
  241. end;
  242. symbolic procedure c!:locally_bound(x, env);
  243. atsoc(x, car env);
  244. flag('(nil t), 'c!:constant);
  245. fluid '(literal_vector);
  246. symbolic procedure c!:find_literal x;
  247. begin
  248. scalar n, w;
  249. w := literal_vector;
  250. n := 0;
  251. while w and not (car w = x) do <<
  252. n := n + 1;
  253. w := cdr w >>;
  254. if null w then literal_vector := append(literal_vector, list x);
  255. return n
  256. end;
  257. symbolic procedure c!:catom(x, env);
  258. begin
  259. scalar v, w;
  260. v := c!:newreg();
  261. if idp x and (w := c!:locally_bound(x, env)) then
  262. c!:outop('movr, v, nil, cdr w)
  263. else if null x or x = 't or c!:small_number x then
  264. c!:outop('movk1, v, nil, x)
  265. else if not idp x or flagp(x, 'c!:constant) then
  266. c!:outop('movk, v, x, c!:find_literal x)
  267. else c!:outop('ldrglob, v, x, c!:find_literal x);
  268. return v
  269. end;
  270. symbolic procedure c!:cjumpif(x, env, d1, d2);
  271. begin
  272. scalar helper, r;
  273. x := s!:improve x;
  274. if atom x and (not idp x or
  275. (flagp(x, 'c!:constant) and not c!:locally_bound(x, env))) then
  276. c!:endblock('goto, list (if x then d1 else d2))
  277. else if not atom x and (helper := get(car x, 'c!:ctest)) then
  278. return funcall(helper, x, env, d1, d2)
  279. else <<
  280. r := c!:cval(x, env);
  281. c!:endblock(list('ifnull, r), list(d2, d1)) >>
  282. end;
  283. fluid '(current);
  284. symbolic procedure c!:ccall(fn, args, env);
  285. c!:ccall1(fn, args, env);
  286. fluid '(visited);
  287. symbolic procedure c!:has_calls(a, b);
  288. begin
  289. scalar visited;
  290. return c!:has_calls_1(a, b)
  291. end;
  292. symbolic procedure c!:has_calls_1(a, b);
  293. % true if there is a path from node a to node b that has a call instruction
  294. % on the way.
  295. if a = b or not atom a or memq(a, visited) then nil
  296. else begin
  297. scalar has_call;
  298. visited := a . visited;
  299. for each z in get(a, 'c!:contents) do
  300. if eqcar(z, 'call) then has_call := t;
  301. if has_call then return
  302. begin scalar visited;
  303. return c!:can_reach(a, b) end;
  304. for each d in get(a, 'c!:where_to) do
  305. if c!:has_calls_1(d, b) then has_call := t;
  306. return has_call
  307. end;
  308. symbolic procedure c!:can_reach(a, b);
  309. if a = b then t
  310. else if not atom a or memq(a, visited) then nil
  311. else <<
  312. visited := a . visited;
  313. c!:any_can_reach(get(a, 'c!:where_to), b) >>;
  314. symbolic procedure c!:any_can_reach(l, b);
  315. if null l then nil
  316. else if c!:can_reach(car l, b) then t
  317. else c!:any_can_reach(cdr l, b);
  318. symbolic procedure c!:pareval(args, env);
  319. begin
  320. scalar tasks, tasks1, merge, split, r;
  321. tasks := for each a in args collect (c!:my_gensym() . c!:my_gensym());
  322. split := c!:my_gensym();
  323. c!:endblock('goto, list split);
  324. for each a in args do begin
  325. scalar s;
  326. % I evaluate each arg as what is (at this stage) a separate task
  327. s := car tasks;
  328. tasks := cdr tasks;
  329. c!:startblock car s;
  330. r := c!:cval(a, env) . r;
  331. c!:endblock('goto, list cdr s);
  332. % If the task did no procedure calls (or only tail calls) then it can be
  333. % executed sequentially with the other args without need for stacking
  334. % anything. Otherwise it more care will be needed. Put the hard
  335. % cases onto tasks1.
  336. !#if common!-lisp!-mode
  337. tasks1 := s . tasks1
  338. !#else
  339. if c!:has_calls(car s, cdr s) then tasks1 := s . tasks1
  340. else merge := s . merge
  341. !#endif
  342. end;
  343. %-- % if there are zero or one items in tasks1 then again it is easy -
  344. %-- % otherwise I flag the problem with a notionally parallel construction.
  345. %-- if tasks1 then <<
  346. %-- if null cdr tasks1 then merge := car tasks1 . merge
  347. %-- else <<
  348. %-- c!:startblock split;
  349. %-- printc "***** ParEval needed parallel block here...";
  350. %-- c!:endblock('par, for each v in tasks1 collect car v);
  351. %-- split := c!:my_gensym();
  352. %-- for each v in tasks1 do <<
  353. %-- c!:startblock cdr v;
  354. %-- c!:endblock('goto, list split) >> >> >>;
  355. for each z in tasks1 do merge := z . merge; % do sequentially
  356. %--
  357. %--
  358. % Finally string end-to-end all the bits of sequential code I have left over.
  359. for each v in merge do <<
  360. c!:startblock split;
  361. c!:endblock('goto, list car v);
  362. split := cdr v >>;
  363. c!:startblock split;
  364. return reversip r
  365. end;
  366. symbolic procedure c!:ccall1(fn, args, env);
  367. begin
  368. scalar tasks, merge, r, val;
  369. fn := list(fn, cdr env);
  370. val := c!:newreg();
  371. if null args then c!:outop('call, val, nil, fn)
  372. else if null cdr args then
  373. c!:outop('call, val, list c!:cval(car args, env), fn)
  374. else <<
  375. r := c!:pareval(args, env);
  376. c!:outop('call, val, r, fn) >>;
  377. c!:outop('reloadenv, 'env, nil, nil);
  378. return val
  379. end;
  380. fluid '(restart_label reloadenv does_call current_c_name);
  381. %
  382. % The "proper" recipe here arranges that functions that expect over 2 args use
  383. % the "va_arg" mechanism to pick up ALL their args. This would be pretty
  384. % heavy-handed, and at least on a lot of machines it does not seem to
  385. % be necessary. I will duck it for a while more at least.
  386. %
  387. fluid '(proglabs blockstack);
  388. symbolic procedure c!:cfndef(current_procedure, current_c_name, argsbody);
  389. begin
  390. scalar env, n, w, current_args, current_block, restart_label,
  391. current_contents, all_blocks, entrypoint, exitpoint, args1,
  392. registers, stacklocs, literal_vector, reloadenv, does_call,
  393. blockstack, proglabs, checksum, args, body;
  394. checksum := md60 argsbody;
  395. args := car argsbody;
  396. body := cdr argsbody;
  397. if atom body then body := nil
  398. else if atom cdr body then body := car body
  399. else body := 'progn . body;
  400. % print list(current_procedure, current_c_name, argsbody, checksum);
  401. c!:reset_gensyms();
  402. wrs C_file;
  403. linelength 200;
  404. c!:printf("\n\n/* Code for %a */\n\n", current_procedure);
  405. c!:find_literal current_procedure; % For benefit of backtraces
  406. %
  407. % cope with fluid vars in an argument list by mapping the definition
  408. % (de f (a B C d) body) B and C fluid
  409. % onto
  410. % (de f (a x y c) (prog (B C) (setq B x) (setq C y) (return body)))
  411. % so that the fluids get bound by PROG.
  412. %
  413. current_args := args;
  414. for each v in args do
  415. if v = '!&optional or v = '!&rest then
  416. error(0, "&optional and &rest not supported by this compiler (yet)")
  417. else if globalp v then begin scalar oo;
  418. oo := wrs nil;
  419. princ "+++++ "; prin v;
  420. princ " converted from GLOBAL to FLUID"; terpri();
  421. wrs oo;
  422. unglobal list v;
  423. fluid list v;
  424. n := (v . c!:my_gensym()) . n end
  425. else if fluidp v then n := (v . c!:my_gensym()) . n;
  426. restart_label := c!:my_gensym();
  427. body := list('c!:private_tagbody, restart_label, body);
  428. if n then <<
  429. body := list list('return, body);
  430. args := subla(n, args);
  431. for each v in n do
  432. body := list('setq, car v, cdr v) . body;
  433. body := 'prog . (for each v in reverse n collect car v) . body >>;
  434. c!:printf "static Lisp_Object ";
  435. if null args or length args >= 3 then c!:printf("MS_CDECL ");
  436. c!:printf("%s(Lisp_Object env", current_c_name);
  437. if null args or length args >= 3 then c!:printf(", int nargs");
  438. n := t;
  439. env := nil;
  440. for each x in args do begin
  441. scalar aa;
  442. c!:printf ",";
  443. if n then << c!:printf "\n "; n := nil >>
  444. else n := t;
  445. aa := c!:my_gensym();
  446. env := (x . aa) . env;
  447. registers := aa . registers;
  448. args1 := aa . args1;
  449. c!:printf(" Lisp_Object %s", aa) end;
  450. if null args or length args >= 3 then c!:printf(", ...");
  451. c!:printf(")\n{\n");
  452. c!:startblock (entrypoint := c!:my_gensym());
  453. exitpoint := current_block;
  454. c!:endblock('goto, list list c!:cval(body, env . nil));
  455. c!:optimise_flowgraph(entrypoint, all_blocks, env,
  456. length args . current_procedure, args1);
  457. c!:printf("}\n\n");
  458. wrs O_file;
  459. L_contents := (current_procedure . literal_vector .checksum) .
  460. L_contents;
  461. return nil
  462. end;
  463. % c!:ccompile1 directs the compilation of a single function, and bind all the
  464. % major fluids used by the compilation process
  465. flag('(rds deflist flag fluid global
  466. remprop remflag unfluid
  467. unglobal dm carcheck C!-end), 'eval);
  468. flag('(rds), 'ignore);
  469. fluid '(!*backtrace);
  470. symbolic procedure c!:ccompilesupervisor;
  471. begin
  472. scalar u, w;
  473. top:u := errorset('(read), t, !*backtrace);
  474. if atom u then return; % failed, or maybe EOF
  475. u := car u;
  476. if u = !$eof!$ then return; % end of file
  477. if atom u then go to top
  478. % the apply('C!-end, nil) is here because C!-end has a "stat"
  479. % property and so it will mis-parse if I just write "C!-end()". Yuk.
  480. else if eqcar(u, 'C!-end) then return apply('C!-end, nil)
  481. else if eqcar(u, 'rdf) then <<
  482. !#if common!-lisp!-mode
  483. w := open(u := eval cadr u, !:direction, !:input,
  484. !:if!-does!-not!-exist, nil);
  485. !#else
  486. w := open(u := eval cadr u, 'input);
  487. !#endif
  488. if w then <<
  489. terpri();
  490. princ "Reading file "; print u;
  491. w := rds w;
  492. c!:ccompilesupervisor();
  493. princ "End of file "; print u;
  494. close rds w >>
  495. else << princ "Failed to open file "; print u >> >>
  496. else c!:ccmpout1 u;
  497. go to top
  498. end;
  499. global '(c!:char_mappings);
  500. c!:char_mappings := '(
  501. (! . !A) (!! . !B) (!# . !C) (!$ . !D)
  502. (!% . !E) (!^ . !F) (!& . !G) (!* . !H)
  503. (!( . !I) (!) . !J) (!- . !K) (!+ . !L)
  504. (!= . !M) (!\ . !N) (!| . !O) (!, . !P)
  505. (!. . !Q) (!< . !R) (!> . !S) (!: . !T)
  506. (!; . !U) (!/ . !V) (!? . !W) (!~ . !X)
  507. (!` . !Y));
  508. symbolic procedure c!:inv_name n;
  509. begin
  510. scalar r, w;
  511. r := '(_ !C !C !");
  512. !#if common!-lisp!-mode
  513. for each c in explode2 package!-name symbol!-package n do <<
  514. if c = '_ then r := '_ . r
  515. else if alpha!-char!-p c or digit c then r := c . r
  516. else if w := atsoc(c, c!:char_mappings) then r := cdr w . r
  517. else r := '!Z . r >>;
  518. r := '!_ . '!_ . r;
  519. !#endif
  520. for each c in explode2 n do <<
  521. if c = '_ then r := '_ . r
  522. !#if common!-lisp!-mode
  523. else if alpha!-char!-p c or digit c then r := c . r
  524. !#else
  525. else if liter c or digit c then r := c . r
  526. !#endif
  527. else if w := atsoc(c, c!:char_mappings) then r := cdr w . r
  528. else r := '!Z . r >>;
  529. r := '!" . r;
  530. !#if common!-lisp!-mode
  531. return compress1 reverse r
  532. !#else
  533. return compress reverse r
  534. !#endif
  535. end;
  536. fluid '(defnames pending_functions);
  537. symbolic procedure c!:ccmpout1 u;
  538. begin
  539. scalar pending_functions;
  540. pending_functions := list u;
  541. while pending_functions do <<
  542. u := car pending_functions;
  543. pending_functions := cdr pending_functions;
  544. c!:ccmpout1a u >>
  545. end;
  546. symbolic procedure c!:ccmpout1a u;
  547. begin
  548. scalar w;
  549. if atom u then return
  550. else if eqcar(u, 'progn) then <<
  551. for each v in cdr u do c!:ccmpout1a v;
  552. return >>
  553. else if eqcar(u, 'C!-end) then nil
  554. else if flagp(car u, 'eval) or
  555. (car u = 'setq and not atom caddr u and flagp(caaddr u, 'eval)) then
  556. errorset(u, t, !*backtrace);
  557. if eqcar(u, 'rdf) then begin
  558. !#if common!-lisp!-mode
  559. w := open(u := eval cadr u, !:direction, !:input,
  560. !:if!-does!_not!-exist, nil);
  561. !#else
  562. w := open(u := eval cadr u, 'input);
  563. !#endif
  564. if w then <<
  565. princ "Reading file "; print u;
  566. w := rds w;
  567. c!:ccompilesupervisor();
  568. princ "End of file "; print u;
  569. close rds w >>
  570. else << princ "Failed to open file "; print u >> end
  571. !#if common!-lisp!-mode
  572. else if eqcar(u, 'defun) then return c!:ccmpout1a macroexpand u
  573. !#endif
  574. else if eqcar(u, 'de) then <<
  575. u := cdr u;
  576. !#if common!-lisp!-mode
  577. w := compress1 ('!" . append(explodec package!-name
  578. symbol!-package car u,
  579. '!@ . '!@ . append(explodec symbol!-name car u,
  580. append(explodec "@@Builtin", '(!")))));
  581. w := intern w;
  582. defnames := list(car u, c!:inv_name car u, length cadr u, w) . defnames;
  583. !#else
  584. defnames := list(car u, c!:inv_name car u, length cadr u) . defnames;
  585. !#endif
  586. if posn() neq 0 then terpri();
  587. princ "Compiling "; prin caar defnames; princ " ... ";
  588. c!:cfndef(caar defnames, cadar defnames, cdr u);
  589. !#if common!-lisp!-mode
  590. L_contents := (w . car L_contents) . cdr L_contents;
  591. !#endif
  592. terpri() >>
  593. end;
  594. fluid '(!*defn dfprint!* dfprintsave);
  595. !#if common!-lisp!-mode
  596. symbolic procedure c!:concat(a, b);
  597. compress1('!" . append(explode2 a, append(explode2 b, '(!"))));
  598. !#else
  599. symbolic procedure c!:concat(a, b);
  600. compress('!" . append(explode2 a, append(explode2 b, '(!"))));
  601. !#endif
  602. symbolic procedure c!:ccompilestart(name, !&optional, dir);
  603. begin
  604. scalar o, d, w;
  605. File_name := name;
  606. if dir then name := c!:concat(dir, c!:concat("/", name));
  607. !#if common!-lisp!-mode
  608. C_file := open(c!:concat(name, ".c"), !:direction, !:output);
  609. !#else
  610. C_file := open(c!:concat(name, ".c"), 'output);
  611. !#endif
  612. L_file := c!:concat(name, ".lsp");
  613. L_contents := nil;
  614. % Here I turn a date into a form like "12-Oct-1993" as expected by the
  615. % file signature mechanism that I use. This seems a pretty ugly process.
  616. o := reverse explode date();
  617. for i := 1:5 do << d := car o . d; o := cdr o >>;
  618. d := '!- . d;
  619. o := cdddr cdddr cddddr o;
  620. w := o;
  621. o := cdddr o;
  622. d := caddr o . cadr o . car o . d;
  623. !#if common!-lisp!-mode
  624. d := compress1('!" . cadr w . car w . '!- . d);
  625. !#else
  626. d := compress('!" . cadr w . car w . '!- . d);
  627. !#endif
  628. O_file := wrs C_file;
  629. defnames := nil;
  630. c!:printf("\n/* %s.c%tMachine generated C code */\n\n", name, 25);
  631. c!:printf("/* Signature: 00000000 %s */\n\n", d);
  632. % c!:printf "#include <stdio.h>\n"; Included by "machine.h"
  633. % c!:printf "#include <stdlib.h>\n";
  634. c!:printf "#include <stdarg.h>\n";
  635. c!:printf "#include <string.h>\n";
  636. % c!:printf "#include <time.h>\n";
  637. c!:printf "#include <ctype.h>\n\n";
  638. c!:printf "#include \qmachine.h\q\n";
  639. c!:printf "#include \qtags.h\q\n";
  640. c!:printf "#include \qcslerror.h\q\n";
  641. c!:printf "#include \qexterns.h\q\n";
  642. c!:printf "#include \qarith.h\q\n";
  643. c!:printf "#include \qentries.h\q\n\n\n";
  644. wrs O_file;
  645. return nil
  646. end;
  647. symbolic procedure C!-end;
  648. begin
  649. scalar checksum, c1, c2, c3;
  650. wrs C_file;
  651. c!:printf("\n\nsetup_type const %s_setup[] =\n{\n", File_name);
  652. defnames := reverse defnames;
  653. while defnames do begin
  654. scalar name, nargs, f1, f2, cast, fn;
  655. !#if common!-lisp!-mode
  656. name := cadddr car defnames;
  657. !#else
  658. name := caar defnames;
  659. !#endif
  660. f1 := cadar defnames;
  661. nargs := caddar defnames;
  662. cast := "(n_args *)";
  663. if nargs = 1 then <<
  664. f2 := '!t!o!o_!m!a!n!y_1; cast := ""; fn := '!w!r!o!n!g_!n!o_1 >>
  665. else if nargs = 2 then <<
  666. f2 := f1; f1 := '!t!o!o_!f!e!w_2; cast := "";
  667. fn := '!w!r!o!n!g_!n!o_2 >>
  668. else << fn := f1; f1 := '!w!r!o!n!g_!n!o_!n!a;
  669. f2 := '!w!r!o!n!g_!n!o_!n!b >>;
  670. c!:printf(" {\q%s\q,%t%s,%t%s,%t%s%s},\n",
  671. name, 32, f1, 48, f2, 63, cast, fn);
  672. defnames := cdr defnames end;
  673. c3 := checksum := md60 L_contents;
  674. c1 := remainder(c3, 10000000);
  675. c3 := c3 / 10000000;
  676. c2 := remainder(c3, 10000000);
  677. c3 := c3 / 10000000;
  678. checksum := list!-to!-string append(explodec c3,
  679. '! . append(explodec c2, '! . explodec c1));
  680. c!:printf(" {NULL, (one_args *)%a, (two_args *)%a, 0}\n};\n\n",
  681. list!-to!-string explodec File_name, checksum);
  682. c!:printf "/* end of generated code */\n";
  683. close C_file;
  684. !#if common!-lisp!-mode
  685. L_file := open(L_file, !:direction, !:output);
  686. !#else
  687. L_file := open(L_file, 'output);
  688. !#endif
  689. wrs L_file;
  690. linelength 72;
  691. terpri();
  692. !#if common!-lisp!-mode
  693. princ ";;; ";
  694. !#else
  695. princ "% ";
  696. !#endif
  697. princ File_name;
  698. princ ".lsp"; ttab 20;
  699. princ "Machine generated Lisp";
  700. % princ " "; princ date();
  701. terpri(); terpri();
  702. !#if common!-lisp!-mode
  703. princ "(in-package lisp)"; terpri(); terpri();
  704. princ "(c::install ";
  705. !#else
  706. princ "(c!:install ";
  707. !#endif
  708. princ '!"; princ File_name; princ '!";
  709. princ " "; princ checksum; printc ")";
  710. terpri();
  711. for each x in reverse L_contents do <<
  712. !#if common!-lisp!-mode
  713. princ "(c::install '";
  714. prin car x;
  715. princ " '";
  716. x := cdr x;
  717. !#else
  718. princ "(c!:install '";
  719. !#endif
  720. prin car x;
  721. princ " '";
  722. prin cadr x;
  723. !#if (not common!-lisp!-mode)
  724. princ " ";
  725. prin cddr x;
  726. !#endif
  727. princ ")";
  728. terpri(); terpri() >>;
  729. terpri();
  730. !#if common!-lisp!-mode
  731. princ ";;; End of generated Lisp code";
  732. !#else
  733. princ "% End of generated Lisp code";
  734. !#endif
  735. terpri(); terpri();
  736. L_contents := nil;
  737. wrs O_file;
  738. close L_file;
  739. !*defn := nil;
  740. dfprint!* := dfprintsave
  741. end;
  742. put('C!-end, 'stat, 'endstat);
  743. symbolic procedure C!-compile u;
  744. begin
  745. terpri();
  746. princ "C!-COMPILE ";
  747. prin u; princ ": IN files; or type in expressions"; terpri();
  748. princ "When all done, execute C!-END;"; terpri();
  749. verbos nil;
  750. c!:ccompilestart car u;
  751. dfprintsave := dfprint!*;
  752. dfprint!* := 'c!:ccmpout1;
  753. !*defn := t;
  754. if getd 'begin then return nil;
  755. c!:ccompilesupervisor();
  756. end;
  757. put('C!-compile, 'stat, 'rlis);
  758. %
  759. % Global treatment of a flow-graph...
  760. %
  761. symbolic procedure c!:print_opcode(s, depth);
  762. begin
  763. scalar op, r1, r2, r3, helper;
  764. op := car s; r1 := cadr s; r2 := caddr s; r3 := cadddr s;
  765. helper := get(op, 'c!:opcode_printer);
  766. if helper then funcall(helper, op, r1, r2, r3, depth)
  767. else << prin s; terpri() >>
  768. end;
  769. symbolic procedure c!:print_exit_condition(why, where_to, depth);
  770. begin
  771. scalar helper, lab1, drop1, lab2, drop2, negate;
  772. % An exit condition is one of
  773. % goto (lab)
  774. % goto ((return-register))
  775. % (ifnull v) (lab1 lab2) ) etc, where v is a register and
  776. % (ifatom v) (lab1 lab2) ) lab1, lab2 are labels for true & false
  777. % (ifeq v1 v2) (lab1 lab2) ) and various predicates are supported
  778. % ((call fn) a1 a2) () tail-call to given function
  779. %
  780. if why = 'goto then <<
  781. where_to := car where_to;
  782. if atom where_to then <<
  783. c!:printf(" goto %s;\n", where_to);
  784. c!:display_flowgraph(where_to, depth, t) >>
  785. else << c!:printf " "; c!:pgoto(where_to, depth) >>;
  786. return nil >>
  787. else if eqcar(car why, 'call) then return begin
  788. scalar args, locs, g, w;
  789. if w := get(cadar why, 'c!:direct_entrypoint) then <<
  790. for each a in cdr why do
  791. if flagp(a, 'c!:live_across_call) then <<
  792. if null g then c!:printf " {\n";
  793. g := c!:my_gensym();
  794. c!:printf(" Lisp_Object %s = %v;\n", g, a);
  795. args := g . args >>
  796. else args := a . args;
  797. if depth neq 0 then <<
  798. if g then c!:printf " ";
  799. c!:printf(" popv(%s);\n", depth) >>;
  800. if g then c!:printf " ";
  801. !#if common!-lisp!-mode
  802. c!:printf(" { Lisp_Object retVal = %s(", cdr w);
  803. !#else
  804. c!:printf(" return %s(", cdr w);
  805. !#endif
  806. args := reversip args;
  807. if args then <<
  808. c!:printf("%v", car args);
  809. for each a in cdr args do c!:printf(", %v", a) >>;
  810. c!:printf(");\n");
  811. !#if common!-lisp!-mode
  812. if g then c!:printf " ";
  813. c!:printf(" errexit();\n");
  814. if g then c!:printf " ";
  815. c!:printf(" return onevalue(retVal); }\n");
  816. !#endif
  817. if g then c!:printf " }\n" >>
  818. else if w := get(cadar why, 'c!:c_entrypoint) then <<
  819. for each a in cdr why do
  820. if flagp(a, 'c!:live_across_call) then <<
  821. if null g then c!:printf " {\n";
  822. g := c!:my_gensym();
  823. c!:printf(" Lisp_Object %s = %v;\n", g, a);
  824. args := g . args >>
  825. else args := a . args;
  826. if depth neq 0 then c!:printf(" popv(%s);\n", depth);
  827. c!:printf(" return %s(nil", w);
  828. if null args or length args >= 3 then c!:printf(", %s", length args);
  829. for each a in reversip args do c!:printf(", %v", a);
  830. c!:printf(");\n");
  831. if g then c!:printf " }\n" >>
  832. else begin
  833. scalar nargs;
  834. nargs := length cdr why;
  835. c!:printf " {\n";
  836. for each a in cdr why do
  837. if flagp(a, 'c!:live_across_call) then <<
  838. g := c!:my_gensym();
  839. c!:printf(" Lisp_Object %s = %v;\n", g, a);
  840. args := g . args >>
  841. else args := a . args;
  842. if depth neq 0 then c!:printf(" popv(%s);\n", depth);
  843. c!:printf(" fn = elt(env, %s); /* %a */\n",
  844. c!:find_literal cadar why, cadar why);
  845. if nargs = 1 then c!:printf(" return (*qfn1(fn))(qenv(fn)")
  846. else if nargs = 2 then c!:printf(" return (*qfn2(fn))(qenv(fn)")
  847. else c!:printf(" return (*qfnn(fn))(qenv(fn), %s", nargs);
  848. for each a in reversip args do c!:printf(", %s", a);
  849. c!:printf(");\n }\n") end;
  850. return nil end;
  851. lab1 := car where_to;
  852. drop1 := atom lab1 and not flagp(lab1, 'c!:visited);
  853. lab2 := cadr where_to;
  854. drop2 := atom lab2 and not flagp(drop2, 'c!:visited);
  855. if drop2 and get(lab2, 'c!:count) = 1 then <<
  856. where_to := list(lab2, lab1);
  857. drop1 := t >>
  858. else if drop1 then negate := t;
  859. helper := get(car why, 'c!:exit_helper);
  860. if null helper then error(0, list("Bad exit condition", why));
  861. c!:printf(" if (");
  862. if negate then <<
  863. c!:printf("!(");
  864. funcall(helper, cdr why, depth);
  865. c!:printf(")") >>
  866. else funcall(helper, cdr why, depth);
  867. c!:printf(") ");
  868. if not drop1 then <<
  869. c!:pgoto(car where_to, depth);
  870. c!:printf(" else ") >>;
  871. c!:pgoto(cadr where_to, depth);
  872. if atom car where_to then c!:display_flowgraph(car where_to, depth, drop1);
  873. if atom cadr where_to then c!:display_flowgraph(cadr where_to, depth, nil)
  874. end;
  875. symbolic procedure c!:pmovr(op, r1, r2, r3, depth);
  876. c!:printf(" %v = %v;\n", r1, r3);
  877. put('movr, 'c!:opcode_printer, function c!:pmovr);
  878. symbolic procedure c!:pmovk(op, r1, r2, r3, depth);
  879. c!:printf(" %v = elt(env, %s); /* %a */\n", r1, r3, r2);
  880. put('movk, 'c!:opcode_printer, function c!:pmovk);
  881. symbolic procedure c!:pmovk1(op, r1, r2, r3, depth);
  882. if null r3 then c!:printf(" %v = nil;\n", r1)
  883. else if r3 = 't then c!:printf(" %v = lisp_true;\n", r1)
  884. else c!:printf(" %v = (Lisp_Object)%s; /* %a */\n", r1, 16*r3+1, r3);
  885. put('movk1, 'c!:opcode_printer, function c!:pmovk1);
  886. symbolic procedure c!:preloadenv(op, r1, r2, r3, depth);
  887. % will not be encountered unless reloadenv variable has been set up.
  888. c!:printf(" env = stack[%s];\n", -reloadenv);
  889. put('reloadenv, 'c!:opcode_printer, function c!:preloadenv);
  890. symbolic procedure c!:pldrglob(op, r1, r2, r3, depth);
  891. c!:printf(" %v = qvalue(elt(env, %s)); /* %a */\n", r1, r3, r2);
  892. put('ldrglob, 'c!:opcode_printer, function c!:pldrglob);
  893. symbolic procedure c!:pstrglob(op, r1, r2, r3, depth);
  894. c!:printf(" qvalue(elt(env, %s)) = %v; /* %a */\n", r3, r1, r2);
  895. put('strglob, 'c!:opcode_printer, function c!:pstrglob);
  896. symbolic procedure c!:pnilglob(op, r1, r2, r3, depth);
  897. c!:printf(" qvalue(elt(env, %s)) = nil; /* %a */\n", r3, r2);
  898. put('nilglob, 'c!:opcode_printer, function c!:pnilglob);
  899. symbolic procedure c!:pnull(op, r1, r2, r3, depth);
  900. c!:printf(" %v = (%v == nil ? lisp_true : nil);\n", r1, r3);
  901. put('null, 'c!:opcode_printer, function c!:pnull);
  902. put('not, 'c!:opcode_printer, function c!:pnull);
  903. flag('(null not), 'c!:uses_nil);
  904. symbolic procedure c!:pfastget(op, r1, r2, r3, depth);
  905. <<
  906. c!:printf(" if (!symbolp(%v)) %v = nil;\n", r2, r1);
  907. c!:printf(" else { %v = qfastgets(%v);\n", r1, r2);
  908. c!:printf(" if (%v != nil) { %v = elt(%v, %s); /* %s */\n",
  909. r1, r1, r1, car r3, cdr r3);
  910. c!:printf("#ifdef RECORD_GET\n");
  911. c!:printf(" if (%v != SPID_NOPROP)\n", r1);
  912. c!:printf(" record_get(elt(fastget_names, %s), 1);\n", car r3);
  913. c!:printf(" else record_get(elt(fastget_names, %s), 0),\n", car r3);
  914. c!:printf(" %v = nil; }\n", r1);
  915. c!:printf(" else record_get(elt(fastget_names, %s), 0); }\n", car r3);
  916. c!:printf("#else\n");
  917. c!:printf(" if (%v == SPID_NOPROP) %v = nil; }}\n", r1, r1);
  918. c!:printf("#endif\n");
  919. >>;
  920. put('fastget, 'c!:opcode_printer, function c!:pfastget);
  921. flag('(fastget), 'c!:uses_nil);
  922. symbolic procedure c!:pfastflag(op, r1, r2, r3, depth);
  923. <<
  924. c!:printf(" if (!symbolp(%v)) %v = nil;\n", r2, r1);
  925. c!:printf(" else { %v = qfastgets(%v);\n", r1, r2);
  926. c!:printf(" if (%v != nil) { %v = elt(%v, %s); /* %s */\n",
  927. r1, r1, r1, car r3, cdr r3);
  928. c!:printf("#ifdef RECORD_GET\n");
  929. c!:printf(" if (%v == SPID_NOPROP)\n", r1);
  930. c!:printf(" record_get(elt(fastget_names, %s), 0),\n", car r3);
  931. c!:printf(" %v = nil;\n", r1);
  932. c!:printf(" else record_get(elt(fastget_names, %s), 1),\n", car r3);
  933. c!:printf(" %v = lisp_true; }\n", r1);
  934. c!:printf(" else record_get(elt(fastget_names, %s), 0); }\n", car r3);
  935. c!:printf("#else\n");
  936. c!:printf(" if (%v == SPID_NOPROP) %v = nil; else %v = lisp_true; }}\n", r1, r1, r1);
  937. c!:printf("#endif\n");
  938. >>;
  939. put('fastflag, 'c!:opcode_printer, function c!:pfastflag);
  940. flag('(fastflag), 'c!:uses_nil);
  941. symbolic procedure c!:pcar(op, r1, r2, r3, depth);
  942. begin
  943. if not !*unsafecar then <<
  944. c!:printf(" if (!car_legal(%v)) ", r3);
  945. c!:pgoto(c!:find_error_label(list('car, r3), r2, depth), depth) >>;
  946. c!:printf(" %v = qcar(%v);\n", r1, r3)
  947. end;
  948. put('car, 'c!:opcode_printer, function c!:pcar);
  949. symbolic procedure c!:pcdr(op, r1, r2, r3, depth);
  950. begin
  951. if not !*unsafecar then <<
  952. c!:printf(" if (!car_legal(%v)) ", r3);
  953. c!:pgoto(c!:find_error_label(list('cdr, r3), r2, depth), depth) >>;
  954. c!:printf(" %v = qcdr(%v);\n", r1, r3)
  955. end;
  956. put('cdr, 'c!:opcode_printer, function c!:pcdr);
  957. symbolic procedure c!:pqcar(op, r1, r2, r3, depth);
  958. c!:printf(" %v = qcar(%v);\n", r1, r3);
  959. put('qcar, 'c!:opcode_printer, function c!:pqcar);
  960. symbolic procedure c!:pqcdr(op, r1, r2, r3, depth);
  961. c!:printf(" %v = qcdr(%v);\n", r1, r3);
  962. put('qcdr, 'c!:opcode_printer, function c!:pqcdr);
  963. symbolic procedure c!:patom(op, r1, r2, r3, depth);
  964. c!:printf(" %v = (!consp(%v) ? lisp_true : nil);\n", r1, r3);
  965. put('atom, 'c!:opcode_printer, function c!:patom);
  966. symbolic procedure c!:pnumberp(op, r1, r2, r3, depth);
  967. c!:printf(" %v = (is_number(%v) ? lisp_true : nil);\n", r1, r3);
  968. put('numberp, 'c!:opcode_printer, function c!:pnumberp);
  969. symbolic procedure c!:pfixp(op, r1, r2, r3, depth);
  970. c!:printf(" %v = integerp(%v);\n", r1, r3);
  971. put('fixp, 'c!:opcode_printer, function c!:pfixp);
  972. symbolic procedure c!:piminusp(op, r1, r2, r3, depth);
  973. c!:printf(" %v = ((int32)(%v) < 0 ? lisp_true : nil);\n", r1, r3);
  974. put('iminusp, 'c!:opcode_printer, function c!:piminusp);
  975. symbolic procedure c!:pilessp(op, r1, r2, r3, depth);
  976. c!:printf(" %v = ((int32)%v < (int32)%v) ? lisp_true : nil;\n",
  977. r1, r2, r3);
  978. put('ilessp, 'c!:opcode_printer, function c!:pilessp);
  979. symbolic procedure c!:pigreaterp(op, r1, r2, r3, depth);
  980. c!:printf(" %v = ((int32)%v > (int32)%v) ? lisp_true : nil;\n",
  981. r1, r2, r3);
  982. put('igreaterp, 'c!:opcode_printer, function c!:pigreaterp);
  983. symbolic procedure c!:piminus(op, r1, r2, r3, depth);
  984. c!:printf(" %v = (Lisp_Object)(2-((int32)(%v)));\n", r1, r3);
  985. put('iminus, 'c!:opcode_printer, function c!:piminus);
  986. symbolic procedure c!:piadd1(op, r1, r2, r3, depth);
  987. c!:printf(" %v = (Lisp_Object)((int32)(%v) + 0x10);\n", r1, r3);
  988. put('iadd1, 'c!:opcode_printer, function c!:piadd1);
  989. symbolic procedure c!:pisub1(op, r1, r2, r3, depth);
  990. c!:printf(" %v = (Lisp_Object)((int32)(%v) - 0x10);\n", r1, r3);
  991. put('isub1, 'c!:opcode_printer, function c!:pisub1);
  992. symbolic procedure c!:piplus2(op, r1, r2, r3, depth);
  993. c!:printf(" %v = (Lisp_Object)((int32)%v + (int32)%v - TAG_FIXNUM);\n",
  994. r1, r2, r3);
  995. put('iplus2, 'c!:opcode_printer, function c!:piplus2);
  996. symbolic procedure c!:pidifference(op, r1, r2, r3, depth);
  997. c!:printf(" %v = (Lisp_Object)((int32)%v - (int32)%v + TAG_FIXNUM);\n",
  998. r1, r2, r3);
  999. put('idifference, 'c!:opcode_printer, function c!:pidifference);
  1000. symbolic procedure c!:pitimes2(op, r1, r2, r3, depth);
  1001. c!:printf(" %v = fixnum_of_int(int_of_fixnum(%v) * int_of_fixnum(%v));\n",
  1002. r1, r2, r3);
  1003. put('itimes2, 'c!:opcode_printer, function c!:pitimes2);
  1004. symbolic procedure c!:pmodular_plus(op, r1, r2, r3, depth);
  1005. <<
  1006. c!:printf(" { int32 w = int_of_fixnum(%v) + int_of_fixnum(%v);\n",
  1007. r2, r3);
  1008. c!:printf(" if (w >= current_modulus) w -= current_modulus;\n");
  1009. c!:printf(" %v = fixnum_of_int(w);\n", r1);
  1010. c!:printf(" }\n")
  1011. >>;
  1012. put('modular!-plus, 'c!:opcode_printer, function c!:pmodular_plus);
  1013. symbolic procedure c!:pmodular_difference(op, r1, r2, r3, depth);
  1014. <<
  1015. c!:printf(" { int32 w = int_of_fixnum(%v) - int_of_fixnum(%v);\n",
  1016. r2, r3);
  1017. c!:printf(" if (w < 0) w += current_modulus;\n");
  1018. c!:printf(" %v = fixnum_of_int(w);\n", r1);
  1019. c!:printf(" }\n")
  1020. >>;
  1021. put('modular!-difference, 'c!:opcode_printer, function c!:pmodular_difference);
  1022. symbolic procedure c!:pmodular_minus(op, r1, r2, r3, depth);
  1023. <<
  1024. c!:printf(" { int32 w = int_of_fixnum(%v);\n", r3);
  1025. c!:printf(" if (w != 0) w = current_modulus - w;\n");
  1026. c!:printf(" %v = fixnum_of_int(w);\n", r1);
  1027. c!:printf(" }\n")
  1028. >>;
  1029. put('modular!-minus, 'c!:opcode_printer, function c!:pmodular_minus);
  1030. !#if (not common!-lisp!-mode)
  1031. symbolic procedure c!:passoc(op, r1, r2, r3, depth);
  1032. c!:printf(" %v = Lassoc(nil, %v, %v);\n", r1, r2, r3);
  1033. put('assoc, 'c!:opcode_printer, function c!:passoc);
  1034. flag('(assoc), 'c!:uses_nil);
  1035. !#endif
  1036. symbolic procedure c!:patsoc(op, r1, r2, r3, depth);
  1037. c!:printf(" %v = Latsoc(nil, %v, %v);\n", r1, r2, r3);
  1038. put('atsoc, 'c!:opcode_printer, function c!:patsoc);
  1039. flag('(atsoc), 'c!:uses_nil);
  1040. !#if (not common!-lisp!-mode)
  1041. symbolic procedure c!:pmember(op, r1, r2, r3, depth);
  1042. c!:printf(" %v = Lmember(nil, %v, %v);\n", r1, r2, r3);
  1043. put('member, 'c!:opcode_printer, function c!:pmember);
  1044. flag('(member), 'c!:uses_nil);
  1045. !#endif
  1046. symbolic procedure c!:pmemq(op, r1, r2, r3, depth);
  1047. c!:printf(" %v = Lmemq(nil, %v, %v);\n", r1, r2, r3);
  1048. put('memq, 'c!:opcode_printer, function c!:pmemq);
  1049. flag('(memq), 'c!:uses_nil);
  1050. !#if common!-lisp!-mode
  1051. symbolic procedure c!:pget(op, r1, r2, r3, depth);
  1052. c!:printf(" %v = get(%v, %v, nil);\n", r1, r2, r3);
  1053. flag('(get), 'c!:uses_nil);
  1054. !#else
  1055. symbolic procedure c!:pget(op, r1, r2, r3, depth);
  1056. c!:printf(" %v = get(%v, %v);\n", r1, r2, r3);
  1057. !#endif
  1058. put('get, 'c!:opcode_printer, function c!:pget);
  1059. symbolic procedure c!:pqgetv(op, r1, r2, r3, depth);
  1060. << c!:printf(" %v = *(Lisp_Object *)((char *)%v + (4L-TAG_VECTOR) +",
  1061. r1, r2);
  1062. c!:printf(" ((int32)%v>>2));\n", r3) >>;
  1063. put('qgetv, 'c!:opcode_printer, function c!:pqgetv);
  1064. symbolic procedure c!:pqputv(op, r1, r2, r3, depth);
  1065. <<
  1066. c!:printf(" *(Lisp_Object *)((char *)%v + (4L-TAG_VECTOR) +", r2);
  1067. c!:printf(" ((int32)%v>>2)) = %v;\n", r3, r1) >>;
  1068. put('qputv, 'c!:opcode_printer, function c!:pqputv);
  1069. symbolic procedure c!:peq(op, r1, r2, r3, depth);
  1070. c!:printf(" %v = (%v == %v ? lisp_true : nil);\n", r1, r2, r3);
  1071. put('eq, 'c!:opcode_printer, function c!:peq);
  1072. flag('(eq), 'c!:uses_nil);
  1073. !#if common!-lisp!-mode
  1074. symbolic procedure c!:pequal(op, r1, r2, r3, depth);
  1075. c!:printf(" %v = (cl_equal(%v, %v) ? lisp_true : nil);\n",
  1076. r1, r2, r3, r2, r3);
  1077. !#else
  1078. symbolic procedure c!:pequal(op, r1, r2, r3, depth);
  1079. c!:printf(" %v = (equal(%v, %v) ? lisp_true : nil);\n",
  1080. r1, r2, r3, r2, r3);
  1081. !#endif
  1082. put('equal, 'c!:opcode_printer, function c!:pequal);
  1083. flag('(equal), 'c!:uses_nil);
  1084. symbolic procedure c!:pfluidbind(op, r1, r2, r3, depth);
  1085. nil;
  1086. put('fluidbind, 'c!:opcode_printer, function c!:pfluidbind);
  1087. symbolic procedure c!:pcall(op, r1, r2, r3, depth);
  1088. begin
  1089. % r3 is (name <fluids to unbind on error>)
  1090. scalar w, boolfn;
  1091. if w := get(car r3, 'c!:direct_entrypoint) then <<
  1092. c!:printf(" %v = %s(", r1, cdr w);
  1093. if r2 then <<
  1094. c!:printf("%v", car r2);
  1095. for each a in cdr r2 do c!:printf(", %v", a) >>;
  1096. c!:printf(");\n") >>
  1097. else if w := get(car r3, 'c!:direct_predicate) then <<
  1098. boolfn := t;
  1099. c!:printf(" %v = (Lisp_Object)%s(", r1, cdr w);
  1100. if r2 then <<
  1101. c!:printf("%v", car r2);
  1102. for each a in cdr r2 do c!:printf(", %v", a) >>;
  1103. c!:printf(");\n") >>
  1104. else if car r3 = current_procedure then <<
  1105. c!:printf(" %v = %s(env", r1, current_c_name);
  1106. if null r2 or length r2 >= 3 then c!:printf(", %s", length r2);
  1107. for each a in r2 do c!:printf(", %v", a);
  1108. c!:printf(");\n") >>
  1109. else if w := get(car r3, 'c!:c_entrypoint) then <<
  1110. c!:printf(" %v = %s(nil", r1, w);
  1111. if null r2 or length r2 >= 3 then c!:printf(", %s", length r2);
  1112. for each a in r2 do c!:printf(", %v", a);
  1113. c!:printf(");\n") >>
  1114. else begin
  1115. scalar nargs;
  1116. nargs := length r2;
  1117. c!:printf(" fn = elt(env, %s); /* %a */\n",
  1118. c!:find_literal car r3, car r3);
  1119. if nargs = 1 then c!:printf(" %v = (*qfn1(fn))(qenv(fn)", r1)
  1120. else if nargs = 2 then c!:printf(" %v = (*qfn2(fn))(qenv(fn)", r1)
  1121. else c!:printf(" %v = (*qfnn(fn))(qenv(fn), %s", r1, nargs);
  1122. for each a in r2 do c!:printf(", %v", a);
  1123. c!:printf(");\n") end;
  1124. if not flagp(car r3, 'c!:no_errors) then <<
  1125. if null cadr r3 and depth = 0 then c!:printf(" errexit();\n")
  1126. else <<
  1127. c!:printf(" nil = C_nil;\n");
  1128. c!:printf(" if (exception_pending()) ");
  1129. c!:pgoto(c!:find_error_label(nil, cadr r3, depth) , depth) >> >>;
  1130. if boolfn then c!:printf(" %v = %v ? lisp_true : nil;\n", r1, r1);
  1131. end;
  1132. put('call, 'c!:opcode_printer, function c!:pcall);
  1133. symbolic procedure c!:pgoto(lab, depth);
  1134. begin
  1135. if atom lab then return c!:printf("goto %s;\n", lab);
  1136. lab := get(car lab, 'c!:chosen);
  1137. if zerop depth then c!:printf("return onevalue(%v);\n", lab)
  1138. else if flagp(lab, 'c!:live_across_call) then
  1139. c!:printf("{ Lisp_Object res = %v; popv(%s); return onevalue(res); }\n", lab, depth)
  1140. else c!:printf("{ popv(%s); return onevalue(%v); }\n", depth, lab)
  1141. end;
  1142. symbolic procedure c!:pifnull(s, depth);
  1143. c!:printf("%v == nil", car s);
  1144. put('ifnull, 'c!:exit_helper, function c!:pifnull);
  1145. symbolic procedure c!:pifatom(s, depth);
  1146. c!:printf("!consp(%v)", car s);
  1147. put('ifatom, 'c!:exit_helper, function c!:pifatom);
  1148. symbolic procedure c!:pifsymbol(s, depth);
  1149. c!:printf("symbolp(%v)", car s);
  1150. put('ifsymbol, 'c!:exit_helper, function c!:pifsymbol);
  1151. symbolic procedure c!:pifnumber(s, depth);
  1152. c!:printf("is_number(%v)", car s);
  1153. put('ifnumber, 'c!:exit_helper, function c!:pifnumber);
  1154. symbolic procedure c!:pifizerop(s, depth);
  1155. c!:printf("(%v) == 1", car s);
  1156. put('ifizerop, 'c!:exit_helper, function c!:pifizerop);
  1157. symbolic procedure c!:pifeq(s, depth);
  1158. c!:printf("%v == %v", car s, cadr s);
  1159. put('ifeq, 'c!:exit_helper, function c!:pifeq);
  1160. !#if common!-lisp!-mode
  1161. symbolic procedure c!:pifequal(s, depth);
  1162. c!:printf("cl_equal(%v, %v)",
  1163. car s, cadr s, car s, cadr s);
  1164. !#else
  1165. symbolic procedure c!:pifequal(s, depth);
  1166. c!:printf("equal(%v, %v)",
  1167. car s, cadr s, car s, cadr s);
  1168. !#endif
  1169. put('ifequal, 'c!:exit_helper, function c!:pifequal);
  1170. symbolic procedure c!:pifilessp(s, depth);
  1171. c!:printf("((int32)(%v)) < ((int32)(%v))", car s, cadr s);
  1172. put('ifilessp, 'c!:exit_helper, function c!:pifilessp);
  1173. symbolic procedure c!:pifigreaterp(s, depth);
  1174. c!:printf("((int32)(%v)) > ((int32)(%v))", car s, cadr s);
  1175. put('ifigreaterp, 'c!:exit_helper, function c!:pifigreaterp);
  1176. symbolic procedure c!:display_flowgraph(s, depth, dropping_through);
  1177. if not atom s then <<
  1178. c!:printf " ";
  1179. c!:pgoto(s, depth) >>
  1180. else if not flagp(s, 'c!:visited) then begin
  1181. scalar why, where_to;
  1182. flag(list s, 'c!:visited);
  1183. if not dropping_through or not (get(s, 'c!:count) = 1) then
  1184. c!:printf("\n%s:\n", s);
  1185. for each k in reverse get(s, 'c!:contents) do c!:print_opcode(k, depth);
  1186. why := get(s, 'c!:why);
  1187. where_to := get(s, 'c!:where_to);
  1188. if why = 'goto and (not atom car where_to or
  1189. (not flagp(car where_to, 'c!:visited) and
  1190. get(car where_to, 'c!:count) = 1)) then
  1191. c!:display_flowgraph(car where_to, depth, t)
  1192. else c!:print_exit_condition(why, where_to, depth);
  1193. end;
  1194. fluid '(startpoint);
  1195. symbolic procedure c!:branch_chain(s, count);
  1196. begin
  1197. scalar contents, why, where_to, n;
  1198. % do nothing to blocks already visted or return blocks.
  1199. if not atom s then return s
  1200. else if flagp(s, 'c!:visited) then <<
  1201. n := get(s, 'c!:count);
  1202. if null n then n := 1 else n := n + 1;
  1203. put(s, 'c!:count, n);
  1204. return s >>;
  1205. flag(list s, 'c!:visited);
  1206. contents := get(s, 'c!:contents);
  1207. why := get(s, 'c!:why);
  1208. where_to := for each z in get(s, 'c!:where_to) collect
  1209. c!:branch_chain(z, count);
  1210. % Turn movr a,b; return a; into return b;
  1211. while contents and eqcar(car contents, 'movr) and
  1212. why = 'goto and not atom car where_to and
  1213. caar where_to = cadr car contents do <<
  1214. where_to := list list cadddr car contents;
  1215. contents := cdr contents >>;
  1216. put(s, 'c!:contents, contents);
  1217. put(s, 'c!:where_to, where_to);
  1218. % discard empty blocks
  1219. if null contents and why = 'goto then <<
  1220. remflag(list s, 'c!:visited);
  1221. return car where_to >>;
  1222. if count then <<
  1223. n := get(s, 'c!:count);
  1224. if null n then n := 1
  1225. else n := n + 1;
  1226. put(s, 'c!:count, n) >>;
  1227. return s
  1228. end;
  1229. symbolic procedure c!:one_operand op;
  1230. << flag(list op, 'c!:set_r1);
  1231. flag(list op, 'c!:read_r3);
  1232. put(op, 'c!:code, function c!:builtin_one) >>;
  1233. symbolic procedure c!:two_operands op;
  1234. << flag(list op, 'c!:set_r1);
  1235. flag(list op, 'c!:read_r2);
  1236. flag(list op, 'c!:read_r3);
  1237. put(op, 'c!:code, function c!:builtin_two) >>;
  1238. for each n in '(car cdr qcar qcdr null not atom numberp fixp iminusp
  1239. iminus iadd1 isub1 modular!-minus) do c!:one_operand n;
  1240. !#if common!-lisp!-mode
  1241. for each n in '(eq equal atsoc memq iplus2 idifference
  1242. itimes2 ilessp igreaterp qgetv get
  1243. modular!-plus modular!-difference
  1244. ) do c!:two_operands n;
  1245. !#else
  1246. for each n in '(eq equal atsoc memq iplus2 idifference
  1247. assoc member
  1248. itimes2 ilessp igreaterp qgetv get
  1249. modular!-plus modular!-difference
  1250. ) do c!:two_operands n;
  1251. !#endif
  1252. flag('(movr movk movk1 ldrglob call reloadenv fastget fastflag), 'c!:set_r1);
  1253. flag('(strglob qputv), 'c!:read_r1);
  1254. flag('(qputv fastget fastflag), 'c!:read_r2);
  1255. flag('(movr qputv), 'c!:read_r3);
  1256. flag('(ldrglob strglob nilglob movk call), 'c!:read_env);
  1257. % special opcodes:
  1258. % call fluidbind
  1259. fluid '(fn_used nil_used nilbase_used);
  1260. symbolic procedure c!:live_variable_analysis all_blocks;
  1261. begin
  1262. scalar changed, z;
  1263. repeat <<
  1264. changed := nil;
  1265. for each b in all_blocks do
  1266. begin
  1267. scalar w, live;
  1268. for each x in get(b, 'c!:where_to) do
  1269. if atom x then live := union(live, get(x, 'c!:live))
  1270. else live := union(live, x);
  1271. w := get(b, 'c!:why);
  1272. if not atom w then <<
  1273. if eqcar(w, 'ifnull) or eqcar(w, 'ifequal) then nil_used := t;
  1274. live := union(live, cdr w);
  1275. if eqcar(car w, 'call) and
  1276. (flagp(cadar w, 'c!:direct_predicate) or
  1277. (flagp(cadar w, 'c!:c_entrypoint) and
  1278. not flagp(cadar w, 'c!:direct_entrypoint))) then
  1279. nil_used := t;
  1280. if eqcar(car w, 'call) and
  1281. not (cadar w = current_procedure) and
  1282. not get(cadar w, 'c!:direct_entrypoint) and
  1283. not get(cadar w, 'c!:c_entrypoint) then <<
  1284. fn_used := t; live := union('(env), live) >> >>;
  1285. for each s in get(b, 'c!:contents) do
  1286. begin % backwards over contents
  1287. scalar op, r1, r2, r3;
  1288. op := car s; r1 := cadr s; r2 := caddr s; r3 := cadddr s;
  1289. if op = 'movk1 then <<
  1290. if r3 = nil then nil_used := t
  1291. else if r3 = 't then nilbase_used := t >>
  1292. else if atom op and flagp(op, 'c!:uses_nil) then nil_used := t;
  1293. if flagp(op, 'c!:set_r1) then
  1294. !#if common!-lisp!-mode
  1295. if memq(r1, live) then live := remove(r1, live)
  1296. !#else
  1297. if memq(r1, live) then live := delete(r1, live)
  1298. !#endif
  1299. else if op = 'call then nil % Always needed
  1300. else op := 'nop;
  1301. if flagp(op, 'c!:read_r1) then live := union(live, list r1);
  1302. if flagp(op, 'c!:read_r2) then live := union(live, list r2);
  1303. if flagp(op, 'c!:read_r3) then live := union(live, list r3);
  1304. if op = 'call then <<
  1305. if not flagp(car r3, 'c!:no_errors) or
  1306. flagp(car r3, 'c!:c_entrypoint) or
  1307. get(car r3, 'c!:direct_predicate) then nil_used := t;
  1308. does_call := t;
  1309. if not eqcar(r3, current_procedure) and
  1310. not get(car r3, 'c!:direct_entrypoint) and
  1311. not get(car r3, 'c!:c_entrypoint) then fn_used := t;
  1312. if not flagp(car r3, 'c!:no_errors) then
  1313. flag(live, 'c!:live_across_call);
  1314. live := union(live, r2) >>;
  1315. if flagp(op, 'c!:read_env) then live := union(live, '(env))
  1316. end;
  1317. !#if common!-lisp!-mode
  1318. live := append(live, nil); % because CL sort is destructive!
  1319. !#endif
  1320. live := sort(live, function orderp);
  1321. if not (live = get(b, 'c!:live)) then <<
  1322. put(b, 'c!:live, live);
  1323. changed := t >>
  1324. end
  1325. >> until not changed;
  1326. z := registers;
  1327. registers := stacklocs := nil;
  1328. for each r in z do
  1329. if flagp(r, 'c!:live_across_call) then stacklocs := r . stacklocs
  1330. else registers := r . registers
  1331. end;
  1332. symbolic procedure c!:insert1(a, b);
  1333. if memq(a, b) then b
  1334. else a . b;
  1335. symbolic procedure c!:clash(a, b);
  1336. if flagp(a, 'c!:live_across_call) = flagp(b, 'c!:live_across_call) then <<
  1337. put(a, 'c!:clash, c!:insert1(b, get(a, 'c!:clash)));
  1338. put(b, 'c!:clash, c!:insert1(a, get(b, 'c!:clash))) >>;
  1339. symbolic procedure c!:build_clash_matrix all_blocks;
  1340. begin
  1341. for each b in all_blocks do
  1342. begin
  1343. scalar live, w;
  1344. for each x in get(b, 'c!:where_to) do
  1345. if atom x then live := union(live, get(x, 'c!:live))
  1346. else live := union(live, x);
  1347. w := get(b, 'c!:why);
  1348. if not atom w then <<
  1349. live := union(live, cdr w);
  1350. if eqcar(car w, 'call) and
  1351. not get(cadar w, 'c!:direct_entrypoint) and
  1352. not get(cadar w, 'c!:c_entrypoint) then
  1353. live := union('(env), live) >>;
  1354. for each s in get(b, 'c!:contents) do
  1355. begin
  1356. scalar op, r1, r2, r3;
  1357. op := car s; r1 := cadr s; r2 := caddr s; r3 := cadddr s;
  1358. if flagp(op, 'c!:set_r1) then
  1359. if memq(r1, live) then <<
  1360. !#if common!-lisp!-mode
  1361. live := remove(r1, live);
  1362. !#else
  1363. live := delete(r1, live);
  1364. !#endif
  1365. if op = 'reloadenv then reloadenv := t;
  1366. for each v in live do c!:clash(r1, v) >>
  1367. else if op = 'call then nil
  1368. else <<
  1369. op := 'nop;
  1370. rplacd(s, car s . cdr s); % Leaves original instrn visible
  1371. rplaca(s, op) >>;
  1372. if flagp(op, 'c!:read_r1) then live := union(live, list r1);
  1373. if flagp(op, 'c!:read_r2) then live := union(live, list r2);
  1374. if flagp(op, 'c!:read_r3) then live := union(live, list r3);
  1375. % Maybe CALL should be a little more selective about need for "env"?
  1376. if op = 'call then live := union(live, r2);
  1377. if flagp(op, 'c!:read_env) then live := union(live, '(env))
  1378. end
  1379. end;
  1380. % The next few lines are for debugging...
  1381. %%- c!:printf "Scratch registers:\n";
  1382. %%- for each r in registers do
  1383. %%- c!:printf("%s clashes: %s\n", r, get(r, 'c!:clash));
  1384. %%- c!:printf "Stack items:\n";
  1385. %%- for each r in stacklocs do
  1386. %%- c!:printf("%s clashes: %s\n", r, get(r, 'c!:clash));
  1387. return nil
  1388. end;
  1389. symbolic procedure c!:allocate_registers rl;
  1390. begin
  1391. scalar schedule, neighbours, allocation;
  1392. neighbours := 0;
  1393. while rl do begin
  1394. scalar w, x;
  1395. w := rl;
  1396. while w and length (x := get(car w, 'c!:clash)) > neighbours do
  1397. w := cdr w;
  1398. if w then <<
  1399. schedule := car w . schedule;
  1400. rl := deleq(car w, rl);
  1401. for each r in x do put(r, 'c!:clash, deleq(car w, get(r, 'c!:clash))) >>
  1402. else neighbours := neighbours + 1
  1403. end;
  1404. for each r in schedule do begin
  1405. scalar poss;
  1406. poss := allocation;
  1407. for each x in get(r, 'c!:clash) do
  1408. poss := deleq(get(x, 'c!:chosen), poss);
  1409. if null poss then <<
  1410. poss := c!:my_gensym();
  1411. allocation := append(allocation, list poss) >>
  1412. else poss := car poss;
  1413. % c!:printf("/* Allocate %s to %s, to miss %s */\n",
  1414. % r, poss, get(r, 'c!:clash));
  1415. put(r, 'c!:chosen, poss)
  1416. end;
  1417. return allocation
  1418. end;
  1419. symbolic procedure c!:remove_nops all_blocks;
  1420. % Remove no-operation instructions, and map registers to reflect allocation
  1421. for each b in all_blocks do
  1422. begin
  1423. scalar r;
  1424. for each s in get(b, 'c!:contents) do
  1425. if not eqcar(s, 'nop) then
  1426. begin
  1427. scalar op, r1, r2, r3;
  1428. op := car s; r1 := cadr s; r2 := caddr s; r3 := cadddr s;
  1429. if flagp(op, 'c!:set_r1) or flagp(op, 'c!:read_r1) then
  1430. r1 := get(r1, 'c!:chosen);
  1431. if flagp(op, 'c!:read_r2) then r2 := get(r2, 'c!:chosen);
  1432. if flagp(op, 'c!:read_r3) then r3 := get(r3, 'c!:chosen);
  1433. if op = 'call then
  1434. r2 := for each v in r2 collect get(v, 'c!:chosen);
  1435. if not (op = 'movr and r1 = r3) then
  1436. r := list(op, r1, r2, r3) . r
  1437. end;
  1438. put(b, 'c!:contents, reversip r);
  1439. r := get(b, 'c!:why);
  1440. if not atom r then
  1441. put(b, 'c!:why,
  1442. car r . for each v in cdr r collect get(v, 'c!:chosen))
  1443. end;
  1444. fluid '(error_labels);
  1445. symbolic procedure c!:find_error_label(why, env, depth);
  1446. begin
  1447. scalar w, z;
  1448. z := list(why, env, depth);
  1449. w := assoc!*!*(z, error_labels);
  1450. if null w then <<
  1451. w := z . c!:my_gensym();
  1452. error_labels := w . error_labels >>;
  1453. return cdr w
  1454. end;
  1455. symbolic procedure c!:assign(u, v, c);
  1456. if flagp(u, 'fluid) then list('strglob, v, u, c!:find_literal u) . c
  1457. else list('movr, u, nil, v) . c;
  1458. symbolic procedure c!:insert_tailcall b;
  1459. begin
  1460. scalar why, dest, contents, fcall, res, w;
  1461. why := get(b, 'c!:why);
  1462. dest := get(b, 'c!:where_to);
  1463. contents := get(b, 'c!:contents);
  1464. while contents and not eqcar(car contents, 'call) do <<
  1465. w := car contents . w;
  1466. contents := cdr contents >>;
  1467. if null contents then return nil;
  1468. fcall := car contents;
  1469. contents := cdr contents;
  1470. res := cadr fcall;
  1471. while w do <<
  1472. if eqcar(car w, 'reloadenv) then w := cdr w
  1473. else if eqcar(car w, 'movr) and cadddr car w = res then <<
  1474. res := cadr car w;
  1475. w := cdr w >>
  1476. else res := w := nil >>;
  1477. if null res then return nil;
  1478. if c!:does_return(res, why, dest) then
  1479. if car cadddr fcall = current_procedure then <<
  1480. for each p in pair(current_args, caddr fcall) do
  1481. contents := c!:assign(car p, cdr p, contents);
  1482. put(b, 'c!:contents, contents);
  1483. put(b, 'c!:why, 'goto);
  1484. put(b, 'c!:where_to, list restart_label) >>
  1485. else <<
  1486. nil_used := t;
  1487. put(b, 'c!:contents, contents);
  1488. put(b, 'c!:why, list('call, car cadddr fcall) . caddr fcall);
  1489. put(b, 'c!:where_to, nil) >>
  1490. end;
  1491. symbolic procedure c!:does_return(res, why, where_to);
  1492. if not (why = 'goto) then nil
  1493. else if not atom car where_to then res = caar where_to
  1494. else begin
  1495. scalar contents;
  1496. where_to := car where_to;
  1497. contents := reverse get(where_to, 'c!:contents);
  1498. why := get(where_to, 'c!:why);
  1499. where_to := get(where_to, 'c!:where_to);
  1500. while contents do
  1501. if eqcar(car contents, 'reloadenv) then contents := cdr contents
  1502. else if eqcar(car contents, 'movr) and cadddr car contents = res then <<
  1503. res := cadr car contents;
  1504. contents := cdr contents >>
  1505. else res := contents := nil;
  1506. if null res then return nil
  1507. else return c!:does_return(res, why, where_to)
  1508. end;
  1509. symbolic procedure c!:pushpop(op, v);
  1510. % for each x in v do c!:printf(" %s(%s);\n", op, x);
  1511. begin
  1512. scalar n, w;
  1513. if null v then return nil;
  1514. n := length v;
  1515. if n = 1 then return c!:printf(" %s(%s);\n", op, car v);
  1516. while n > 0 do <<
  1517. w := n;
  1518. if w > 6 then w := 6;
  1519. n := n-w;
  1520. c!:printf(" %s%d(%s", op, w, car v);
  1521. v := cdr v;
  1522. for i := 2:w do <<
  1523. c!:printf(",%s", car v);
  1524. v := cdr v >>;
  1525. c!:printf(");\n") >>
  1526. end;
  1527. symbolic procedure c!:optimise_flowgraph(startpoint, all_blocks,
  1528. env, argch, args);
  1529. begin
  1530. scalar w, n, locs, stacks, error_labels, fn_used, nil_used, nilbase_used;
  1531. !#if common!-lisp!-mode
  1532. nilbase_used := t; % For onevalue(xxx) at least
  1533. !#endif
  1534. for each b in all_blocks do c!:insert_tailcall b;
  1535. startpoint := c!:branch_chain(startpoint, nil);
  1536. remflag(all_blocks, 'c!:visited);
  1537. c!:live_variable_analysis all_blocks;
  1538. c!:build_clash_matrix all_blocks;
  1539. if error_labels and env then reloadenv := t;
  1540. for each u in env do
  1541. for each v in env do c!:clash(cdr u, cdr v); % keep all args distinct
  1542. locs := c!:allocate_registers registers;
  1543. stacks := c!:allocate_registers stacklocs;
  1544. flag(stacks, 'c!:live_across_call);
  1545. c!:remove_nops all_blocks;
  1546. startpoint := c!:branch_chain(startpoint, nil); % after tailcall insertion
  1547. remflag(all_blocks, 'c!:visited);
  1548. startpoint := c!:branch_chain(startpoint, t); % ... AGAIN to tidy up
  1549. remflag(all_blocks, 'c!:visited);
  1550. if does_call then nil_used := t;
  1551. if nil_used then c!:printf " Lisp_Object nil = C_nil;\n"
  1552. else if nilbase_used then c!:printf " nil_as_base\n";
  1553. if locs then <<
  1554. c!:printf(" Lisp_Object %s", car locs);
  1555. for each v in cdr locs do c!:printf(", %s", v);
  1556. c!:printf ";\n" >>;
  1557. if fn_used then c!:printf " Lisp_Object fn;\n";
  1558. if car argch = 0 or car argch >= 3 then
  1559. c!:printf(" argcheck(nargs, %s, \q%s\q);\n", car argch, cdr argch);
  1560. % I will not do a stack check if I have a leaf procedure, and I hope
  1561. % that this policy will speed up code a bit.
  1562. if does_call then <<
  1563. c!:printf " if (stack >= stacklimit)\n";
  1564. c!:printf " {\n";
  1565. % This is slightly clumsy code to save all args on the stack across the
  1566. % call to reclaim(), but it is not executed often...
  1567. c!:pushpop('push, args);
  1568. c!:printf " env = reclaim(env, \qstack\q, GC_STACK, 0);\n";
  1569. c!:pushpop('pop, reverse args);
  1570. c!:printf " nil = C_nil;\n";
  1571. c!:printf " if (exception_pending()) return nil;\n";
  1572. c!:printf " }\n" >>;
  1573. if reloadenv then c!:printf(" push(env);\n")
  1574. else c!:printf(" CSL_IGNORE(env);\n");
  1575. n := 0;
  1576. if stacks then <<
  1577. c!:printf "/* space for vars preserved across procedure calls */\n";
  1578. for each v in stacks do <<
  1579. put(v, 'c!:location, n);
  1580. n := n+1 >>;
  1581. w := n;
  1582. while w >= 5 do <<
  1583. c!:printf " push5(nil, nil, nil, nil, nil);\n";
  1584. w := w - 5 >>;
  1585. if w neq 0 then <<
  1586. if w = 1 then c!:printf " push(nil);\n"
  1587. else <<
  1588. c!:printf(" push%s(nil", w);
  1589. for i := 2:w do c!:printf ", nil";
  1590. c!:printf ");\n" >> >> >>;
  1591. if reloadenv then <<
  1592. reloadenv := n;
  1593. n := n + 1 >>;
  1594. if env then c!:printf "/* copy arguments values to proper place */\n";
  1595. for each v in env do
  1596. if flagp(cdr v, 'c!:live_across_call) then
  1597. c!:printf(" stack[%s] = %s;\n",
  1598. -get(get(cdr v, 'c!:chosen), 'c!:location), cdr v)
  1599. else c!:printf(" %s = %s;\n", get(cdr v, 'c!:chosen), cdr v);
  1600. c!:printf "/* end of prologue */\n";
  1601. c!:display_flowgraph(startpoint, n, t);
  1602. if error_labels then <<
  1603. c!:printf "/* error exit handlers */\n";
  1604. for each x in error_labels do <<
  1605. c!:printf("%s:\n", cdr x);
  1606. c!:print_error_return(caar x, cadar x, caddar x) >> >>;
  1607. remflag(all_blocks, 'c!:visited);
  1608. end;
  1609. symbolic procedure c!:print_error_return(why, env, depth);
  1610. begin
  1611. if reloadenv and env then
  1612. c!:printf(" env = stack[%s];\n", -reloadenv);
  1613. if null why then <<
  1614. % One could imagine generating backtrace entries here...
  1615. for each v in env do
  1616. c!:printf(" qvalue(elt(env, %s)) = %v; /* %a */\n",
  1617. c!:find_literal car v, get(cdr v, 'c!:chosen), car v);
  1618. if depth neq 0 then c!:printf(" popv(%s);\n", depth);
  1619. c!:printf " return nil;\n" >>
  1620. else if flagp(cadr why, 'c!:live_across_call) then <<
  1621. c!:printf(" { Lisp_Object res = %v;\n", cadr why);
  1622. for each v in env do
  1623. c!:printf(" qvalue(elt(env, %s)) = %v;\n",
  1624. c!:find_literal car v, get(cdr v, 'c!:chosen));
  1625. if depth neq 0 then c!:printf(" popv(%s);\n", depth);
  1626. c!:printf(" return error(1, %s, res); }\n",
  1627. if eqcar(why, 'car) then "err_bad_car"
  1628. else if eqcar(why, 'cdr) then "err_bad_cdr"
  1629. else error(0, list(why, "unknown_error"))) >>
  1630. else <<
  1631. for each v in env do
  1632. c!:printf(" qvalue(elt(env, %s)) = %v;\n",
  1633. c!:find_literal car v, get(cdr v, 'c!:chosen));
  1634. if depth neq 0 then c!:printf(" popv(%s);\n", depth);
  1635. c!:printf(" return error(1, %s, %v);\n",
  1636. (if eqcar(why, 'car) then "err_bad_car"
  1637. else if eqcar(why, 'cdr) then "err_bad_cdr"
  1638. else error(0, list(why, "unknown_error"))),
  1639. cadr why) >>
  1640. end;
  1641. %
  1642. % Now I have a series of separable sections each of which gives a special
  1643. % recipe that implements or optimises compilation of some specific Lisp
  1644. % form.
  1645. %
  1646. symbolic procedure c!:cand(u, env);
  1647. begin
  1648. scalar w, r;
  1649. w := reverse cdr u;
  1650. if null w then return c!:cval(nil, env);
  1651. r := list(list('t, car w));
  1652. w := cdr w;
  1653. for each z in w do
  1654. r := list(list('null, z), nil) . r;
  1655. r := 'cond . r;
  1656. return c!:cval(r, env)
  1657. end;
  1658. %-- scalar next, done, v, r;
  1659. %-- v := c!:newreg();
  1660. %-- done := c!:my_gensym();
  1661. %-- u := cdr u;
  1662. %-- while cdr u do <<
  1663. %-- next := c!:my_gensym();
  1664. %-- c!:outop('movr, v, nil, c!:cval(car u, env));
  1665. %-- u := cdr u;
  1666. %-- c!:endblock(list('ifnull, v), list(done, next));
  1667. %-- c!:startblock next >>;
  1668. %-- c!:outop('movr, v, nil, c!:cval(car u, env));
  1669. %-- c!:endblock('goto, list done);
  1670. %-- c!:startblock done;
  1671. %-- return v
  1672. %-- end;
  1673. put('and, 'c!:code, function c!:cand);
  1674. !#if common!-lisp!-mode
  1675. symbolic procedure c!:cblock(u, env);
  1676. begin
  1677. scalar progret, progexit, r;
  1678. progret := c!:newreg();
  1679. progexit := c!:my_gensym();
  1680. blockstack := (cadr u . progret . progexit) . blockstack;
  1681. u := cddr u;
  1682. for each a in u do r := c!:cval(a, env);
  1683. c!:outop('movr, progret, nil, r);
  1684. c!:endblock('goto, list progexit);
  1685. c!:startblock progexit;
  1686. blockstack := cdr blockstack;
  1687. return progret
  1688. end;
  1689. put('block, 'c!:code, function c!:cblock);
  1690. !#endif
  1691. symbolic procedure c!:ccatch(u, env);
  1692. error(0, "catch");
  1693. put('catch, 'c!:code, function c!:ccatch);
  1694. symbolic procedure c!:ccompile_let(u, env);
  1695. error(0, "compiler-let");
  1696. put('compiler!-let, 'c!:code, function c!:ccompiler_let);
  1697. symbolic procedure c!:ccond(u, env);
  1698. begin
  1699. scalar v, join;
  1700. v := c!:newreg();
  1701. join := c!:my_gensym();
  1702. for each c in cdr u do begin
  1703. scalar l1, l2;
  1704. l1 := c!:my_gensym(); l2 := c!:my_gensym();
  1705. if atom cdr c then <<
  1706. c!:outop('movr, v, nil, c!:cval(car c, env));
  1707. c!:endblock(list('ifnull, v), list(l2, join)) >>
  1708. else <<
  1709. c!:cjumpif(car c, env, l1, l2);
  1710. c!:startblock l1; % if the condition is true
  1711. c!:outop('movr, v, nil, c!:cval('progn . cdr c, env));
  1712. c!:endblock('goto, list join) >>;
  1713. c!:startblock l2 end;
  1714. c!:outop('movk1, v, nil, nil);
  1715. c!:endblock('goto, list join);
  1716. c!:startblock join;
  1717. return v
  1718. end;
  1719. put('cond, 'c!:code, function c!:ccond);
  1720. symbolic procedure c!:cdeclare(u, env);
  1721. error(0, "declare");
  1722. put('declare, 'c!:code, function c!:cdeclare);
  1723. symbolic procedure c!:cde(u, env);
  1724. error(0, "de");
  1725. put('de, 'c!:code, function c!:cde);
  1726. symbolic procedure c!:cdefun(u, env);
  1727. error(0, "defun");
  1728. put('!~defun, 'c!:code, function c!:cdefun);
  1729. symbolic procedure c!:ceval_when(u, env);
  1730. error(0, "eval-when");
  1731. put('eval!-when, 'c!:code, function c!:ceval_when);
  1732. symbolic procedure c!:cflet(u, env);
  1733. error(0, "flet");
  1734. put('flet, 'c!:code, function c!:cflet);
  1735. symbolic procedure c!:cfunction(u, env);
  1736. begin
  1737. scalar v;
  1738. u := cadr u;
  1739. if not atom u then <<
  1740. if not eqcar(u, 'lambda) then
  1741. error(0, list("lambda expression needed", u));
  1742. v := dated!-name 'lambda;
  1743. pending_functions :=
  1744. ('de . v . cdr u) . pending_functions;
  1745. u := v >>;
  1746. v := c!:newreg();
  1747. c!:outop('movk, v, u, c!:find_literal u);
  1748. return v;
  1749. end;
  1750. put('function, 'c!:code, function c!:cfunction);
  1751. symbolic procedure c!:cgo(u, env);
  1752. begin
  1753. scalar w, w1;
  1754. w1 := proglabs;
  1755. while null w and w1 do <<
  1756. w := assoc!*!*(cadr u, car w1);
  1757. w1 := cdr w1 >>;
  1758. if null w then error(0, list(u, "label not set"));
  1759. c!:endblock('goto, list cadr w);
  1760. return nil % value should not be used
  1761. end;
  1762. put('go, 'c!:code, function c!:cgo);
  1763. symbolic procedure c!:cif(u, env);
  1764. begin
  1765. scalar v, join, l1, l2;
  1766. v := c!:newreg();
  1767. join := c!:my_gensym();
  1768. l1 := c!:my_gensym();
  1769. l2 := c!:my_gensym();
  1770. c!:cjumpif(cadr u, env, l1, l2);
  1771. c!:startblock l1;
  1772. c!:outop('movr, v, nil, c!:cval(car (u := cddr u), env));
  1773. c!:endblock('goto, list join);
  1774. c!:startblock l2;
  1775. c!:outop('movr, v, nil, c!:cval(cadr u, env));
  1776. c!:endblock('goto, list join);
  1777. c!:startblock join;
  1778. return v
  1779. end;
  1780. put('if, 'c!:code, function c!:cif);
  1781. symbolic procedure c!:clabels(u, env);
  1782. error(0, "labels");
  1783. put('labels, 'c!:code, function c!:clabels);
  1784. symbolic procedure c!:expand!-let(vl, b);
  1785. if null vl then 'progn . b
  1786. else if null cdr vl then c!:expand!-let!*(vl, b)
  1787. else begin scalar vars, vals;
  1788. for each v in vl do
  1789. if atom v then << vars := v . vars; vals := nil . vals >>
  1790. else if atom cdr v then << vars := car v . vars; vals := nil . vals >>
  1791. else << vars := car v . vars; vals := cadr v . vals >>;
  1792. return ('lambda . vars . b) . vals
  1793. end;
  1794. symbolic procedure c!:clet(x, env);
  1795. c!:cval(c!:expand!-let(cadr x, cddr x), env);
  1796. !#if common!-lisp!-mode
  1797. put('let, 'c!:code, function c!:clet);
  1798. !#else
  1799. put('!~let, 'c!:code, function c!:clet);
  1800. !#endif
  1801. symbolic procedure c!:expand!-let!*(vl, b);
  1802. if null vl then 'progn . b
  1803. else begin scalar var, val;
  1804. var := car vl;
  1805. if not atom var then <<
  1806. val := cdr var;
  1807. var := car var;
  1808. if not atom val then val := car val >>;
  1809. b := list list('return, c!:expand!-let!*(cdr vl, b));
  1810. if val then b := list('setq, var, val) . b;
  1811. return 'prog . list var . b
  1812. end;
  1813. symbolic procedure c!:clet!*(x, env);
  1814. c!:cval(c!:expand!-let!*(cadr x, cddr x), env);
  1815. put('let!*, 'c!:code, function c!:clet!*);
  1816. symbolic procedure c!:clist(u, env);
  1817. if null cdr u then c!:cval(nil, env)
  1818. else if null cddr u then c!:cval('ncons . cdr u, env)
  1819. else if eqcar(cadr u, 'cons) then
  1820. c!:cval(list('acons, cadr cadr u, caddr cadr u, 'list . cddr u), env)
  1821. else if null cdddr u then c!:cval('list2 . cdr u, env)
  1822. else c!:cval(list('list2!*, cadr u, caddr u, 'list . cdddr u), env);
  1823. put('list, 'c!:code, function c!:clist);
  1824. symbolic procedure c!:clist!*(u, env);
  1825. begin
  1826. scalar v;
  1827. u := reverse cdr u;
  1828. v := car u;
  1829. for each a in cdr u do
  1830. v := list('cons, a, v);
  1831. return c!:cval(v, env)
  1832. end;
  1833. put('list!*, 'c!:code, function c!:clist!*);
  1834. symbolic procedure c!:ccons(u, env);
  1835. begin
  1836. scalar a1, a2;
  1837. a1 := s!:improve cadr u;
  1838. a2 := s!:improve caddr u;
  1839. if a2 = nil or a2 = '(quote nil) or a2 = '(list) then
  1840. return c!:cval(list('ncons, a1), env);
  1841. if eqcar(a1, 'cons) then
  1842. return c!:cval(list('acons, cadr a1, caddr a1, a2), env);
  1843. if eqcar(a2, 'cons) then
  1844. return c!:cval(list('list2!*, a1, cadr a2, caddr a2), env);
  1845. if eqcar(a2, 'list) then
  1846. return c!:cval(list('cons, a1,
  1847. list('cons, cadr a2, 'list . cddr a2)), env);
  1848. return c!:ccall(car u, cdr u, env)
  1849. end;
  1850. put('cons, 'c!:code, function c!:ccons);
  1851. symbolic procedure c!:cget(u, env);
  1852. begin
  1853. scalar a1, a2, w, r, r1;
  1854. a1 := s!:improve cadr u;
  1855. a2 := s!:improve caddr u;
  1856. if eqcar(a2, 'quote) and idp(w := cadr a2) and
  1857. (w := symbol!-make!-fastget(w, nil)) then <<
  1858. r := c!:newreg();
  1859. c!:outop('fastget, r, c!:cval(a1, env), w . cadr a2);
  1860. return r >>
  1861. else return c!:ccall(car u, cdr u, env)
  1862. end;
  1863. put('get, 'c!:code, function c!:cget);
  1864. symbolic procedure c!:cflag(u, env);
  1865. begin
  1866. scalar a1, a2, w, r, r1;
  1867. a1 := s!:improve cadr u;
  1868. a2 := s!:improve caddr u;
  1869. if eqcar(a2, 'quote) and idp(w := cadr a2) and
  1870. (w := symbol!-make!-fastget(w, nil)) then <<
  1871. r := c!:newreg();
  1872. c!:outop('fastflag, r, c!:cval(a1, env), w . cadr a2);
  1873. return r >>
  1874. else return c!:ccall(car u, cdr u, env)
  1875. end;
  1876. put('flagp, 'c!:code, function c!:cflag);
  1877. symbolic procedure c!:cgetv(u, env);
  1878. if not !*fastvector then c!:ccall(car u, cdr u, env)
  1879. else c!:cval('qgetv . cdr u, env);
  1880. put('getv, 'c!:code, function c!:cgetv);
  1881. !#if common!-lisp!-mode
  1882. put('svref, 'c!:code, function c!:cgetv);
  1883. !#endif
  1884. symbolic procedure c!:cputv(u, env);
  1885. if not !*fastvector then c!:ccall(car u, cdr u, env)
  1886. else c!:cval('qputv . cdr u, env);
  1887. put('putv, 'c!:code, function c!:cputv);
  1888. symbolic procedure c!:cqputv(x, env);
  1889. begin
  1890. scalar rr;
  1891. rr := c!:pareval(cdr x, env);
  1892. c!:outop('qputv, caddr rr, car rr, cadr rr);
  1893. return caddr rr
  1894. end;
  1895. put('qputv, 'c!:code, function c!:cqputv);
  1896. symbolic procedure c!:cmacrolet(u, env);
  1897. error(0, "macrolet");
  1898. put('macrolet, 'c!:code, function c!:cmacrolet);
  1899. symbolic procedure c!:cmultiple_value_call(u, env);
  1900. error(0, "multiple_value_call");
  1901. put('multiple!-value!-call, 'c!:code, function c!:cmultiple_value_call);
  1902. symbolic procedure c!:cmultiple_value_prog1(u, env);
  1903. error(0, "multiple_value_prog1");
  1904. put('multiple!-value!-prog1, 'c!:code, function c!:cmultiple_value_prog1);
  1905. symbolic procedure c!:cor(u, env);
  1906. begin
  1907. scalar next, done, v, r;
  1908. v := c!:newreg();
  1909. done := c!:my_gensym();
  1910. u := cdr u;
  1911. while cdr u do <<
  1912. next := c!:my_gensym();
  1913. c!:outop('movr, v, nil, c!:cval(car u, env));
  1914. u := cdr u;
  1915. c!:endblock(list('ifnull, v), list(next, done));
  1916. c!:startblock next >>;
  1917. c!:outop('movr, v, nil, c!:cval(car u, env));
  1918. c!:endblock('goto, list done);
  1919. c!:startblock done;
  1920. return v
  1921. end;
  1922. put('or, 'c!:code, function c!:cor);
  1923. symbolic procedure c!:cprog(u, env);
  1924. begin
  1925. scalar w, w1, bvl, local_proglabs, progret, progexit, fluids, env1;
  1926. env1 := car env;
  1927. bvl := cadr u;
  1928. for each v in bvl do
  1929. if globalp v then error(0, list(v, "attempt to bind a global"))
  1930. else if fluidp v then <<
  1931. fluids := (v . c!:newreg()) . fluids;
  1932. flag(list cdar fluids, 'c!:live_across_call); % silly if not
  1933. env1 := ('c!:dummy!:name . cdar fluids) . env1;
  1934. c!:outop('ldrglob, cdar fluids, v, c!:find_literal v);
  1935. c!:outop('nilglob, nil, v, c!:find_literal v) >>
  1936. else <<
  1937. env1 := (v . c!:newreg()) . env1;
  1938. c!:outop('movk1, cdar env1, nil, nil) >>;
  1939. if fluids then c!:outop('fluidbind, nil, nil, fluids);
  1940. env := env1 . append(fluids, cdr env);
  1941. u := cddr u;
  1942. progret := c!:newreg();
  1943. progexit := c!:my_gensym();
  1944. blockstack := (nil . progret . progexit) . blockstack;
  1945. for each a in u do if atom a then
  1946. if atsoc(a, local_proglabs) then <<
  1947. if not null a then <<
  1948. w := wrs nil;
  1949. princ "+++++ multiply defined label: "; prin a; terpri(); wrs w >> >>
  1950. else local_proglabs := list(a, c!:my_gensym()) . local_proglabs;
  1951. proglabs := local_proglabs . proglabs;
  1952. for each a in u do
  1953. if atom a then <<
  1954. w := cdr(assoc!*!*(a, local_proglabs));
  1955. if null cdr w then <<
  1956. rplacd(w, t);
  1957. c!:endblock('goto, list car w);
  1958. c!:startblock car w >> >>
  1959. else c!:cval(a, env);
  1960. c!:outop('movk1, progret, nil, nil);
  1961. c!:endblock('goto, list progexit);
  1962. c!:startblock progexit;
  1963. for each v in fluids do
  1964. c!:outop('strglob, cdr v, car v, c!:find_literal car v);
  1965. blockstack := cdr blockstack;
  1966. proglabs := cdr proglabs;
  1967. return progret
  1968. end;
  1969. put('prog, 'c!:code, function c!:cprog);
  1970. symbolic procedure c!:cprog!*(u, env);
  1971. error(0, "prog*");
  1972. put('prog!*, 'c!:code, function c!:cprog!*);
  1973. symbolic procedure c!:cprog1(u, env);
  1974. begin
  1975. scalar g;
  1976. g := c!:my_gensym();
  1977. g := list('prog, list g,
  1978. list('setq, g, cadr u),
  1979. 'progn . cddr u,
  1980. list('return, g));
  1981. return c!:cval(g, env)
  1982. end;
  1983. put('prog1, 'c!:code, function c!:cprog1);
  1984. symbolic procedure c!:cprog2(u, env);
  1985. begin
  1986. scalar g;
  1987. u := cdr u;
  1988. g := c!:my_gensym();
  1989. g := list('prog, list g,
  1990. list('setq, g, cadr u),
  1991. 'progn . cddr u,
  1992. list('return, g));
  1993. g := list('progn, car u, g);
  1994. return c!:cval(g, env)
  1995. end;
  1996. put('prog2, 'c!:code, function c!:cprog2);
  1997. symbolic procedure c!:cprogn(u, env);
  1998. begin
  1999. scalar r;
  2000. u := cdr u;
  2001. if u = nil then u := '(nil);
  2002. for each s in u do r := c!:cval(s, env);
  2003. return r
  2004. end;
  2005. put('progn, 'c!:code, function c!:cprogn);
  2006. symbolic procedure c!:cprogv(u, env);
  2007. error(0, "progv");
  2008. put('progv, 'c!:code, function c!:cprogv);
  2009. symbolic procedure c!:cquote(u, env);
  2010. begin
  2011. scalar v;
  2012. u := cadr u;
  2013. v := c!:newreg();
  2014. if null u or u = 't or c!:small_number u then
  2015. c!:outop('movk1, v, nil, u)
  2016. else c!:outop('movk, v, u, c!:find_literal u);
  2017. return v;
  2018. end;
  2019. put('quote, 'c!:code, function c!:cquote);
  2020. symbolic procedure c!:creturn(u, env);
  2021. begin
  2022. scalar w;
  2023. w := assoc!*!*(nil, blockstack);
  2024. if null w then error "RETURN out of context";
  2025. c!:outop('movr, cadr w, nil, c!:cval(cadr u, env));
  2026. c!:endblock('goto, list cddr w);
  2027. return nil % value should not be used
  2028. end;
  2029. put('return, 'c!:code, function c!:creturn);
  2030. !#if common!-lisp!-mode
  2031. symbolic procedure c!:creturn_from(u, env);
  2032. begin
  2033. scalar w;
  2034. w := assoc!*!*(cadr u, blockstack);
  2035. if null w then error "RETURN-FROM out of context";
  2036. c!:outop('movr, cadr w, nil, c!:cval(caddr u, env));
  2037. c!:endblock('goto, list cddr w);
  2038. return nil % value should not be used
  2039. end;
  2040. !#endif
  2041. put('return!-from, 'c!:code, function c!:creturn_from);
  2042. symbolic procedure c!:csetq(u, env);
  2043. begin
  2044. scalar v, w;
  2045. v := c!:cval(caddr u, env);
  2046. u := cadr u;
  2047. if not idp u then error(0, list(u, "bad variable in setq"))
  2048. else if (w := c!:locally_bound(u, env)) then
  2049. c!:outop('movr, cdr w, nil, v)
  2050. else if flagp(u, 'c!:constant) then
  2051. error(0, list(u, "attempt to use setq on a constant"))
  2052. else c!:outop('strglob, v, u, c!:find_literal u);
  2053. return v
  2054. end;
  2055. put('setq, 'c!:code, function c!:csetq);
  2056. put('noisy!-setq, 'c!:code, function c!:csetq);
  2057. !#if common!-lisp!-mode
  2058. symbolic procedure c!:ctagbody(u, env);
  2059. begin
  2060. scalar w, bvl, local_proglabs, res;
  2061. u := cdr u;
  2062. for each a in u do if atom a then
  2063. if atsoc(a, local_proglabs) then <<
  2064. if not null a then <<
  2065. w := wrs nil;
  2066. princ "+++++ multiply defined label: "; prin a; terpri(); wrs w >> >>
  2067. else local_proglabs := list(a, c!:my_gensym()) . local_proglabs;
  2068. proglabs := local_proglabs . proglabs;
  2069. for each a in u do
  2070. if atom a then <<
  2071. w := cdr(assoc!*!*(a, local_proglabs));
  2072. if null cdr w then <<
  2073. rplacd(w, t);
  2074. c!:endblock('goto, list car w);
  2075. c!:startblock car w >> >>
  2076. else res := c!:cval(a, env);
  2077. if null res then res := c!:cval(nil, env);
  2078. proglabs := cdr proglabs;
  2079. return res
  2080. end;
  2081. put('tagbody, 'c!:code, function c!:ctagbody);
  2082. !#endif
  2083. symbolic procedure c!:cprivate_tagbody(u, env);
  2084. % This sets a label for use for tail-call to self.
  2085. begin
  2086. u := cdr u;
  2087. c!:endblock('goto, list car u);
  2088. c!:startblock car u;
  2089. % This seems to be the proper place to capture the internal names associated
  2090. % with argument-vars that must be reset if a tail-call is mapped into a loop.
  2091. current_args := for each v in current_args collect begin
  2092. scalar z;
  2093. z := assoc!*!*(v, car env);
  2094. return if z then cdr z else v end;
  2095. return c!:cval(cadr u, env)
  2096. end;
  2097. put('c!:private_tagbody, 'c!:code, function c!:cprivate_tagbody);
  2098. symbolic procedure c!:cthe(u, env);
  2099. c!:cval(caddr u, env);
  2100. put('the, 'c!:code, function c!:cthe);
  2101. symbolic procedure c!:cthrow(u, env);
  2102. error(0, "throw");
  2103. put('throw, 'c!:code, function c!:cthrow);
  2104. symbolic procedure c!:cunless(u, env);
  2105. begin
  2106. scalar v, join, l1, l2;
  2107. v := c!:newreg();
  2108. join := c!:my_gensym();
  2109. l1 := c!:my_gensym();
  2110. l2 := c!:my_gensym();
  2111. c!:cjumpif(cadr u, env, l2, l1);
  2112. c!:startblock l1;
  2113. c!:outop('movr, v, nil, c!:cval('progn . cddr u, env));
  2114. c!:endblock('goto, list join);
  2115. c!:startblock l2;
  2116. c!:outop('movk1, v, nil, nil);
  2117. c!:endblock('goto, list join);
  2118. c!:startblock join;
  2119. return v
  2120. end;
  2121. put('unless, 'c!:code, function c!:cunless);
  2122. symbolic procedure c!:cunwind_protect(u, env);
  2123. error(0, "unwind_protect");
  2124. put('unwind!-protect, 'c!:code, function c!:cunwind_protect);
  2125. symbolic procedure c!:cwhen(u, env);
  2126. begin
  2127. scalar v, join, l1, l2;
  2128. v := c!:newreg();
  2129. join := c!:my_gensym();
  2130. l1 := c!:my_gensym();
  2131. l2 := c!:my_gensym();
  2132. c!:cjumpif(cadr u, env, l1, l2);
  2133. c!:startblock l1;
  2134. c!:outop('movr, v, nil, c!:cval('progn . cddr u, env));
  2135. c!:endblock('goto, list join);
  2136. c!:startblock l2;
  2137. c!:outop('movk1, v, nil, nil);
  2138. c!:endblock('goto, list join);
  2139. c!:startblock join;
  2140. return v
  2141. end;
  2142. put('when, 'c!:code, function c!:cwhen);
  2143. %
  2144. % End of code to handle special forms - what comes from here on is
  2145. % more concerned with performance than with speed.
  2146. %
  2147. !#if (not common!-lisp!-mode)
  2148. % mapcar etc are compiled specially as a fudge to achieve an effect as
  2149. % if proper environment-capture was implemented for the functional
  2150. % argument (which I do not support at present).
  2151. symbolic procedure c!:expand_map(fnargs);
  2152. begin
  2153. scalar carp, fn, fn1, args, var, avar, moveon, l1, r, s, closed;
  2154. fn := car fnargs;
  2155. % if the value of a mapping function is not needed I demote from mapcar to
  2156. % mapc or from maplist to map.
  2157. % if context > 1 then <<
  2158. % if fn = 'mapcar then fn := 'mapc
  2159. % else if fn = 'maplist then fn := 'map >>;
  2160. if fn = 'mapc or fn = 'mapcar or fn = 'mapcan then carp := t;
  2161. fnargs := cdr fnargs;
  2162. if atom fnargs then error(0,"bad arguments to map function");
  2163. fn1 := cadr fnargs;
  2164. while eqcar(fn1, 'function) or
  2165. (eqcar(fn1, 'quote) and eqcar(cadr fn1, 'lambda)) do <<
  2166. fn1 := cadr fn1;
  2167. closed := t >>;
  2168. % if closed is false I will insert FUNCALL since I am invoking a function
  2169. % stored in a variable - NB this means that the word FUNCTION becomes
  2170. % essential when using mapping operators - this is because I have built
  2171. % a 2-Lisp rather than a 1-Lisp.
  2172. args := car fnargs;
  2173. l1 := c!:my_gensym();
  2174. r := c!:my_gensym();
  2175. s := c!:my_gensym();
  2176. var := c!:my_gensym();
  2177. avar := var;
  2178. if carp then avar := list('car, avar);
  2179. if closed then fn1 := list(fn1, avar)
  2180. else fn1 := list('apply1, fn1, avar);
  2181. moveon := list('setq, var, list('cdr, var));
  2182. if fn = 'map or fn = 'mapc then fn := sublis(
  2183. list('l1 . l1, 'var . var,
  2184. 'fn . fn1, 'args . args, 'moveon . moveon),
  2185. '(prog (var)
  2186. (setq var args)
  2187. l1 (cond
  2188. ((not var) (return nil)))
  2189. fn
  2190. moveon
  2191. (go l1)))
  2192. else if fn = 'maplist or fn = 'mapcar then fn := sublis(
  2193. list('l1 . l1, 'var . var,
  2194. 'fn . fn1, 'args . args, 'moveon . moveon, 'r . r),
  2195. '(prog (var r)
  2196. (setq var args)
  2197. l1 (cond
  2198. ((not var) (return (reversip r))))
  2199. (setq r (cons fn r))
  2200. moveon
  2201. (go l1)))
  2202. else fn := sublis(
  2203. list('l1 . l1, 'l2 . c!:my_gensym(), 'var . var,
  2204. 'fn . fn1, 'args . args, 'moveon . moveon,
  2205. 'r . c!:my_gensym(), 's . c!:my_gensym()),
  2206. '(prog (var r s)
  2207. (setq var args)
  2208. (setq r (setq s (list nil)))
  2209. l1 (cond
  2210. ((not var) (return (cdr r))))
  2211. (rplacd s fn)
  2212. l2 (cond
  2213. ((not (atom (cdr s))) (setq s (cdr s)) (go l2)))
  2214. moveon
  2215. (go l1)));
  2216. return fn
  2217. end;
  2218. put('map, 'c!:compile_macro, function c!:expand_map);
  2219. put('maplist, 'c!:compile_macro, function c!:expand_map);
  2220. put('mapc, 'c!:compile_macro, function c!:expand_map);
  2221. put('mapcar, 'c!:compile_macro, function c!:expand_map);
  2222. put('mapcon, 'c!:compile_macro, function c!:expand_map);
  2223. put('mapcan, 'c!:compile_macro, function c!:expand_map);
  2224. !#endif
  2225. % caaar to cddddr get expanded into compositions of
  2226. % car, cdr which are compiled in-line
  2227. symbolic procedure c!:expand_carcdr(x);
  2228. begin
  2229. scalar name;
  2230. name := cdr reverse cdr explode2 car x;
  2231. x := cadr x;
  2232. for each v in name do
  2233. x := list(if v = 'a then 'car else 'cdr, x);
  2234. return x
  2235. end;
  2236. << put('caar, 'c!:compile_macro, function c!:expand_carcdr);
  2237. put('cadr, 'c!:compile_macro, function c!:expand_carcdr);
  2238. put('cdar, 'c!:compile_macro, function c!:expand_carcdr);
  2239. put('cddr, 'c!:compile_macro, function c!:expand_carcdr);
  2240. put('caaar, 'c!:compile_macro, function c!:expand_carcdr);
  2241. put('caadr, 'c!:compile_macro, function c!:expand_carcdr);
  2242. put('cadar, 'c!:compile_macro, function c!:expand_carcdr);
  2243. put('caddr, 'c!:compile_macro, function c!:expand_carcdr);
  2244. put('cdaar, 'c!:compile_macro, function c!:expand_carcdr);
  2245. put('cdadr, 'c!:compile_macro, function c!:expand_carcdr);
  2246. put('cddar, 'c!:compile_macro, function c!:expand_carcdr);
  2247. put('cdddr, 'c!:compile_macro, function c!:expand_carcdr);
  2248. put('caaaar, 'c!:compile_macro, function c!:expand_carcdr);
  2249. put('caaadr, 'c!:compile_macro, function c!:expand_carcdr);
  2250. put('caadar, 'c!:compile_macro, function c!:expand_carcdr);
  2251. put('caaddr, 'c!:compile_macro, function c!:expand_carcdr);
  2252. put('cadaar, 'c!:compile_macro, function c!:expand_carcdr);
  2253. put('cadadr, 'c!:compile_macro, function c!:expand_carcdr);
  2254. put('caddar, 'c!:compile_macro, function c!:expand_carcdr);
  2255. put('cadddr, 'c!:compile_macro, function c!:expand_carcdr);
  2256. put('cdaaar, 'c!:compile_macro, function c!:expand_carcdr);
  2257. put('cdaadr, 'c!:compile_macro, function c!:expand_carcdr);
  2258. put('cdadar, 'c!:compile_macro, function c!:expand_carcdr);
  2259. put('cdaddr, 'c!:compile_macro, function c!:expand_carcdr);
  2260. put('cddaar, 'c!:compile_macro, function c!:expand_carcdr);
  2261. put('cddadr, 'c!:compile_macro, function c!:expand_carcdr);
  2262. put('cdddar, 'c!:compile_macro, function c!:expand_carcdr);
  2263. put('cddddr, 'c!:compile_macro, function c!:expand_carcdr) >>;
  2264. symbolic procedure c!:builtin_one(x, env);
  2265. begin
  2266. scalar r1, r2;
  2267. r1 := c!:cval(cadr x, env);
  2268. c!:outop(car x, r2:=c!:newreg(), cdr env, r1);
  2269. return r2
  2270. end;
  2271. symbolic procedure c!:builtin_two(x, env);
  2272. begin
  2273. scalar a1, a2, r, rr;
  2274. a1 := cadr x;
  2275. a2 := caddr x;
  2276. rr := c!:pareval(list(a1, a2), env);
  2277. c!:outop(car x, r:=c!:newreg(), car rr, cadr rr);
  2278. return r
  2279. end;
  2280. symbolic procedure c!:narg(x, env);
  2281. c!:cval(expand(cdr x, get(car x, 'c!:binary_version)), env);
  2282. for each n in
  2283. '((plus plus2)
  2284. (times times2)
  2285. (iplus iplus2)
  2286. (itimes itimes2)) do <<
  2287. put(car n, 'c!:binary_version, cadr n);
  2288. put(car n, 'c!:code, function c!:narg) >>;
  2289. !#if common!-lisp!-mode
  2290. for each n in
  2291. '((!+ plus2)
  2292. (!* times2)) do <<
  2293. put(car n, 'c!:binary_version, cadr n);
  2294. put(car n, 'c!:code, function c!:narg) >>;
  2295. !#endif
  2296. symbolic procedure c!:cplus2(u, env);
  2297. begin
  2298. scalar a, b;
  2299. a := s!:improve cadr u;
  2300. b := s!:improve caddr u;
  2301. return if numberp a and numberp b then c!:cval(a+b, env)
  2302. else if a = 0 then c!:cval(b, env)
  2303. else if a = 1 then c!:cval(list('add1, b), env)
  2304. else if b = 0 then c!:cval(a, env)
  2305. else if b = 1 then c!:cval(list('add1, a), env)
  2306. else if b = -1 then c!:cval(list('sub1, a), env)
  2307. else c!:ccall(car u, cdr u, env)
  2308. end;
  2309. put('plus2, 'c!:code, function c!:cplus2);
  2310. symbolic procedure c!:ciplus2(u, env);
  2311. begin
  2312. scalar a, b;
  2313. a := s!:improve cadr u;
  2314. b := s!:improve caddr u;
  2315. return if numberp a and numberp b then c!:cval(a+b, env)
  2316. else if a = 0 then c!:cval(b, env)
  2317. else if a = 1 then c!:cval(list('iadd1, b), env)
  2318. else if b = 0 then c!:cval(a, env)
  2319. else if b = 1 then c!:cval(list('iadd1, a), env)
  2320. else if b = -1 then c!:cval(list('isub1, a), env)
  2321. else c!:builtin_two(u, env)
  2322. end;
  2323. put('iplus2, 'c!:code, function c!:ciplus2);
  2324. symbolic procedure c!:cdifference(u, env);
  2325. begin
  2326. scalar a, b;
  2327. a := s!:improve cadr u;
  2328. b := s!:improve caddr u;
  2329. return if numberp a and numberp b then c!:cval(a-b, env)
  2330. else if a = 0 then c!:cval(list('minus, b), env)
  2331. else if b = 0 then c!:cval(a, env)
  2332. else if b = 1 then c!:cval(list('sub1, a), env)
  2333. else if b = -1 then c!:cval(list('add1, a), env)
  2334. else c!:ccall(car u, cdr u, env)
  2335. end;
  2336. put('difference, 'c!:code, function c!:cdifference);
  2337. symbolic procedure c!:cidifference(u, env);
  2338. begin
  2339. scalar a, b;
  2340. a := s!:improve cadr u;
  2341. b := s!:improve caddr u;
  2342. return if numberp a and numberp b then c!:cval(a-b, env)
  2343. else if a = 0 then c!:cval(list('iminus, b), env)
  2344. else if b = 0 then c!:cval(a, env)
  2345. else if b = 1 then c!:cval(list('isub1, a), env)
  2346. else if b = -1 then c!:cval(list('iadd1, a), env)
  2347. else c!:builtin_two(u, env)
  2348. end;
  2349. put('idifference, 'c!:code, function c!:cidifference);
  2350. symbolic procedure c!:ctimes2(u, env);
  2351. begin
  2352. scalar a, b;
  2353. a := s!:improve cadr u;
  2354. b := s!:improve caddr u;
  2355. return if numberp a and numberp b then c!:cval(a*b, env)
  2356. else if a = 0 or b = 0 then c!:cval(0, env)
  2357. else if a = 1 then c!:cval(b, env)
  2358. else if b = 1 then c!:cval(a, env)
  2359. else if a = -1 then c!:cval(list('minus, b), env)
  2360. else if b = -1 then c!:cval(list('minus, a), env)
  2361. else c!:ccall(car u, cdr u, env)
  2362. end;
  2363. put('times2, 'c!:code, function c!:ctimes2);
  2364. symbolic procedure c!:citimes2(u, env);
  2365. begin
  2366. scalar a, b;
  2367. a := s!:improve cadr u;
  2368. b := s!:improve caddr u;
  2369. return if numberp a and numberp b then c!:cval(a*b, env)
  2370. else if a = 0 or b = 0 then c!:cval(0, env)
  2371. else if a = 1 then c!:cval(b, env)
  2372. else if b = 1 then c!:cval(a, env)
  2373. else if a = -1 then c!:cval(list('iminus, b), env)
  2374. else if b = -1 then c!:cval(list('iminus, a), env)
  2375. else c!:builtin_two(u, env)
  2376. end;
  2377. put('itimes2, 'c!:code, function c!:citimes2);
  2378. symbolic procedure c!:cminus(u, env);
  2379. begin
  2380. scalar a, b;
  2381. a := s!:improve cadr u;
  2382. return if numberp a then c!:cval(-a, env)
  2383. else if eqcar(a, 'minus) then c!:cval(cadr a, env)
  2384. else c!:ccall(car u, cdr u, env)
  2385. end;
  2386. put('minus, 'c!:code, function c!:cminus);
  2387. symbolic procedure c!:ceq(x, env);
  2388. begin
  2389. scalar a1, a2, r, rr;
  2390. a1 := s!:improve cadr x;
  2391. a2 := s!:improve caddr x;
  2392. if a1 = nil then return c!:cval(list('null, a2), env)
  2393. else if a2 = nil then return c!:cval(list('null, a1), env);
  2394. rr := c!:pareval(list(a1, a2), env);
  2395. c!:outop('eq, r:=c!:newreg(), car rr, cadr rr);
  2396. return r
  2397. end;
  2398. put('eq, 'c!:code, function c!:ceq);
  2399. symbolic procedure c!:cequal(x, env);
  2400. begin
  2401. scalar a1, a2, r, rr;
  2402. a1 := s!:improve cadr x;
  2403. a2 := s!:improve caddr x;
  2404. if a1 = nil then return c!:cval(list('null, a2), env)
  2405. else if a2 = nil then return c!:cval(list('null, a1), env);
  2406. rr := c!:pareval(list(a1, a2), env);
  2407. c!:outop((if c!:eqvalid a1 or c!:eqvalid a2 then 'eq else 'equal),
  2408. r:=c!:newreg(), car rr, cadr rr);
  2409. return r
  2410. end;
  2411. put('equal, 'c!:code, function c!:cequal);
  2412. %
  2413. % The next few cases are concerned with demoting functions that use
  2414. % equal tests into ones that use eq instead
  2415. symbolic procedure c!:is_fixnum x;
  2416. fixp x and x >= -134217728 and x <= 134217727;
  2417. symbolic procedure c!:certainlyatom x;
  2418. null x or x=t or c!:is_fixnum x or
  2419. (eqcar(x, 'quote) and (symbolp cadr x or c!:is_fixnum cadr x));
  2420. symbolic procedure c!:atomlist1 u;
  2421. atom u or
  2422. ((symbolp car u or c!:is_fixnum car u) and c!:atomlist1 cdr u);
  2423. symbolic procedure c!:atomlist x;
  2424. null x or
  2425. (eqcar(x, 'quote) and c!:atomlist1 cadr x) or
  2426. (eqcar(x, 'list) and
  2427. (null cdr x or
  2428. (c!:certainlyatom cadr x and
  2429. c!:atomlist ('list . cddr x)))) or
  2430. (eqcar(x, 'cons) and
  2431. c!:certainlyatom cadr x and
  2432. c!:atomlist caddr x);
  2433. symbolic procedure c!:atomcar x;
  2434. (eqcar(x, 'cons) or eqcar(x, 'list)) and
  2435. not null cdr x and
  2436. c!:certainlyatom cadr x;
  2437. symbolic procedure c!:atomkeys1 u;
  2438. atom u or
  2439. (not atom car u and
  2440. (symbolp caar u or c!:is_fixnum caar u) and
  2441. c!:atomlist1 cdr u);
  2442. symbolic procedure c!:atomkeys x;
  2443. null x or
  2444. (eqcar(x, 'quote) and c!:atomkeys1 cadr x) or
  2445. (eqcar(x, 'list) and
  2446. (null cdr x or
  2447. (c!:atomcar cadr x and
  2448. c!:atomkeys ('list . cddr x)))) or
  2449. (eqcar(x, 'cons) and
  2450. c!:atomcar cadr x and
  2451. c!:atomkeys caddr x);
  2452. !#if (not common!-lisp!-mode)
  2453. symbolic procedure c!:comsublis x;
  2454. if c!:atomkeys cadr x then 'subla . cdr x
  2455. else nil;
  2456. put('sublis, 'c!:compile_macro, function c!:comsublis);
  2457. symbolic procedure c!:comassoc x;
  2458. if c!:certainlyatom cadr x or c!:atomkeys caddr x then 'atsoc . cdr x
  2459. else nil;
  2460. put('assoc, 'c!:compile_macro, function c!:comassoc);
  2461. put('assoc!*!*, 'c!:compile_macro, function c!:comassoc);
  2462. symbolic procedure c!:commember x;
  2463. if c!:certainlyatom cadr x or c!:atomlist caddr x then 'memq . cdr x
  2464. else nil;
  2465. put('member, 'c!:compile_macro, function c!:commember);
  2466. symbolic procedure c!:comdelete x;
  2467. if c!:certainlyatom cadr x or c!:atomlist caddr x then 'deleq . cdr x
  2468. else nil;
  2469. put('delete, 'c!:compile_macro, function c!:comdelete);
  2470. !#endif
  2471. symbolic procedure c!:ctestif(x, env, d1, d2);
  2472. begin
  2473. scalar l1, l2;
  2474. l1 := c!:my_gensym();
  2475. l2 := c!:my_gensym();
  2476. c!:jumpif(cadr x, l1, l2);
  2477. x := cddr x;
  2478. c!:startblock l1;
  2479. c!:jumpif(car x, d1, d2);
  2480. c!:startblock l2;
  2481. c!:jumpif(cadr x, d1, d2)
  2482. end;
  2483. put('if, 'c!:ctest, function c!:ctestif);
  2484. symbolic procedure c!:ctestnull(x, env, d1, d2);
  2485. c!:cjumpif(cadr x, env, d2, d1);
  2486. put('null, 'c!:ctest, function c!:ctestnull);
  2487. put('not, 'c!:ctest, function c!:ctestnull);
  2488. symbolic procedure c!:ctestatom(x, env, d1, d2);
  2489. begin
  2490. x := c!:cval(cadr x, env);
  2491. c!:endblock(list('ifatom, x), list(d1, d2))
  2492. end;
  2493. put('atom, 'c!:ctest, function c!:ctestatom);
  2494. symbolic procedure c!:ctestconsp(x, env, d1, d2);
  2495. begin
  2496. x := c!:cval(cadr x, env);
  2497. c!:endblock(list('ifatom, x), list(d2, d1))
  2498. end;
  2499. put('consp, 'c!:ctest, function c!:ctestconsp);
  2500. symbolic procedure c!:ctestsymbol(x, env, d1, d2);
  2501. begin
  2502. x := c!:cval(cadr x, env);
  2503. c!:endblock(list('ifsymbol, x), list(d1, d2))
  2504. end;
  2505. put('idp, 'c!:ctest, function c!:ctestsymbol);
  2506. symbolic procedure c!:ctestnumberp(x, env, d1, d2);
  2507. begin
  2508. x := c!:cval(cadr x, env);
  2509. c!:endblock(list('ifnumber, x), list(d1, d2))
  2510. end;
  2511. put('numberp, 'c!:ctest, function c!:ctestnumberp);
  2512. symbolic procedure c!:ctestizerop(x, env, d1, d2);
  2513. begin
  2514. x := c!:cval(cadr x, env);
  2515. c!:endblock(list('ifizerop, x), list(d1, d2))
  2516. end;
  2517. put('izerop, 'c!:ctest, function c!:ctestizerop);
  2518. symbolic procedure c!:ctesteq(x, env, d1, d2);
  2519. begin
  2520. scalar a1, a2, r;
  2521. a1 := cadr x;
  2522. a2 := caddr x;
  2523. if a1 = nil then return c!:cjumpif(a2, env, d2, d1)
  2524. else if a2 = nil then return c!:cjumpif(a1, env, d2, d1);
  2525. r := c!:pareval(list(a1, a2), env);
  2526. c!:endblock('ifeq . r, list(d1, d2))
  2527. end;
  2528. put('eq, 'c!:ctest, function c!:ctesteq);
  2529. symbolic procedure c!:ctesteqcar(x, env, d1, d2);
  2530. begin
  2531. scalar a1, a2, r, d3;
  2532. a1 := cadr x;
  2533. a2 := caddr x;
  2534. d3 := c!:my_gensym();
  2535. r := c!:pareval(list(a1, a2), env);
  2536. c!:endblock(list('ifatom, car r), list(d2, d3));
  2537. c!:startblock d3;
  2538. c!:outop('qcar, car r, nil, car r);
  2539. c!:endblock('ifeq . r, list(d1, d2))
  2540. end;
  2541. put('eqcar, 'c!:ctest, function c!:ctesteqcar);
  2542. global '(least_fixnum greatest_fixnum);
  2543. least_fixnum := -expt(2, 27);
  2544. greatest_fixnum := expt(2, 27) - 1;
  2545. symbolic procedure c!:small_number x;
  2546. fixp x and x >= least_fixnum and x <= greatest_fixnum;
  2547. symbolic procedure c!:eqvalid x;
  2548. if atom x then c!:small_number x
  2549. else if flagp(car x, 'c!:fixnum_fn) then t
  2550. else car x = 'quote and (idp cadr x or c!:small_number cadr x);
  2551. flag('(iplus iplus2 idifference iminus itimes itimes2), 'c!:fixnum_fn);
  2552. symbolic procedure c!:ctestequal(x, env, d1, d2);
  2553. begin
  2554. scalar a1, a2, r;
  2555. a1 := s!:improve cadr x;
  2556. a2 := s!:improve caddr x;
  2557. if a1 = nil then return c!:cjumpif(a2, env, d2, d1)
  2558. else if a2 = nil then return c!:cjumpif(a1, env, d2, d1);
  2559. r := c!:pareval(list(a1, a2), env);
  2560. c!:endblock((if c!:eqvalid a1 or c!:eqvalid a2 then 'ifeq else 'ifequal) .
  2561. r, list(d1, d2))
  2562. end;
  2563. put('equal, 'c!:ctest, function c!:ctestequal);
  2564. symbolic procedure c!:ctestilessp(x, env, d1, d2);
  2565. begin
  2566. scalar r;
  2567. r := c!:pareval(list(cadr x, caddr x), env);
  2568. c!:endblock('ifilessp . r, list(d1, d2))
  2569. end;
  2570. put('ilessp, 'c!:ctest, function c!:ctestilessp);
  2571. symbolic procedure c!:ctestigreaterp(x, env, d1, d2);
  2572. begin
  2573. scalar r;
  2574. r := c!:pareval(list(cadr x, caddr x), env);
  2575. c!:endblock('ifigreaterp . r, list(d1, d2))
  2576. end;
  2577. put('igreaterp, 'c!:ctest, function c!:ctestigreaterp);
  2578. symbolic procedure c!:ctestand(x, env, d1, d2);
  2579. begin
  2580. scalar next;
  2581. for each a in cdr x do <<
  2582. next := c!:my_gensym();
  2583. c!:cjumpif(a, env, next, d2);
  2584. c!:startblock next >>;
  2585. c!:endblock('goto, list d1)
  2586. end;
  2587. put('and, 'c!:ctest, function c!:ctestand);
  2588. symbolic procedure c!:ctestor(x, env, d1, d2);
  2589. begin
  2590. scalar next;
  2591. for each a in cdr x do <<
  2592. next := c!:my_gensym();
  2593. c!:cjumpif(a, env, d1, next);
  2594. c!:startblock next >>;
  2595. c!:endblock('goto, list d2)
  2596. end;
  2597. put('or, 'c!:ctest, function c!:ctestor);
  2598. % Here are some of the things that are built into the Lisp kernel
  2599. % and that I am happy to allow the compiler to generate direct calls to.
  2600. << put('abs, 'c!:c_entrypoint, "Labsval");
  2601. % put('acons, 'c!:c_entrypoint, "Lacons");
  2602. % put('add1, 'c!:c_entrypoint, "Ladd1");
  2603. !#if common!-lisp!-mode
  2604. put('!1!+, 'c!:c_entrypoint, "Ladd1");
  2605. !#endif
  2606. !#if (not common!-lisp!-mode)
  2607. put('append, 'c!:c_entrypoint, "Lappend");
  2608. !#endif
  2609. % put('apply, 'c!:c_entrypoint, "Lapply");
  2610. put('apply0, 'c!:c_entrypoint, "Lapply0");
  2611. put('apply1, 'c!:c_entrypoint, "Lapply1");
  2612. put('apply2, 'c!:c_entrypoint, "Lapply2");
  2613. put('apply3, 'c!:c_entrypoint, "Lapply3");
  2614. % put('ash, 'c!:c_entrypoint, "Lash");
  2615. put('ash1, 'c!:c_entrypoint, "Lash1");
  2616. !#if (not common!-lisp!-mode)
  2617. put('assoc, 'c!:c_entrypoint, "Lassoc");
  2618. !#endif
  2619. put('atan, 'c!:c_entrypoint, "Latan");
  2620. put('atom, 'c!:c_entrypoint, "Latom");
  2621. put('atsoc, 'c!:c_entrypoint, "Latsoc");
  2622. put('batchp, 'c!:c_entrypoint, "Lbatchp");
  2623. put('boundp, 'c!:c_entrypoint, "Lboundp");
  2624. put('bps!-putv, 'c!:c_entrypoint, "Lbpsputv");
  2625. put('caaaar, 'c!:c_entrypoint, "Lcaaaar");
  2626. put('caaadr, 'c!:c_entrypoint, "Lcaaadr");
  2627. put('caaar, 'c!:c_entrypoint, "Lcaaar");
  2628. put('caadar, 'c!:c_entrypoint, "Lcaadar");
  2629. put('caaddr, 'c!:c_entrypoint, "Lcaaddr");
  2630. put('caadr, 'c!:c_entrypoint, "Lcaadr");
  2631. put('caar, 'c!:c_entrypoint, "Lcaar");
  2632. put('cadaar, 'c!:c_entrypoint, "Lcadaar");
  2633. put('cadadr, 'c!:c_entrypoint, "Lcadadr");
  2634. put('cadar, 'c!:c_entrypoint, "Lcadar");
  2635. put('caddar, 'c!:c_entrypoint, "Lcaddar");
  2636. put('cadddr, 'c!:c_entrypoint, "Lcadddr");
  2637. put('caddr, 'c!:c_entrypoint, "Lcaddr");
  2638. put('cadr, 'c!:c_entrypoint, "Lcadr");
  2639. put('car, 'c!:c_entrypoint, "Lcar");
  2640. put('cdaaar, 'c!:c_entrypoint, "Lcdaaar");
  2641. put('cdaadr, 'c!:c_entrypoint, "Lcdaadr");
  2642. put('cdaar, 'c!:c_entrypoint, "Lcdaar");
  2643. put('cdadar, 'c!:c_entrypoint, "Lcdadar");
  2644. put('cdaddr, 'c!:c_entrypoint, "Lcdaddr");
  2645. put('cdadr, 'c!:c_entrypoint, "Lcdadr");
  2646. put('cdar, 'c!:c_entrypoint, "Lcdar");
  2647. put('cddaar, 'c!:c_entrypoint, "Lcddaar");
  2648. put('cddadr, 'c!:c_entrypoint, "Lcddadr");
  2649. put('cddar, 'c!:c_entrypoint, "Lcddar");
  2650. put('cdddar, 'c!:c_entrypoint, "Lcdddar");
  2651. put('cddddr, 'c!:c_entrypoint, "Lcddddr");
  2652. put('cdddr, 'c!:c_entrypoint, "Lcdddr");
  2653. put('cddr, 'c!:c_entrypoint, "Lcddr");
  2654. put('cdr, 'c!:c_entrypoint, "Lcdr");
  2655. put('char!-code, 'c!:c_entrypoint, "Lchar_code");
  2656. put('close, 'c!:c_entrypoint, "Lclose");
  2657. put('code!-char, 'c!:c_entrypoint, "Lcode_char");
  2658. put('codep, 'c!:c_entrypoint, "Lcodep");
  2659. !#if (not common!-lisp!-mode)
  2660. put('compress, 'c!:c_entrypoint, "Lcompress");
  2661. !#endif
  2662. put('constantp, 'c!:c_entrypoint, "Lconstantp");
  2663. % put('cons, 'c!:c_entrypoint, "Lcons");
  2664. put('date, 'c!:c_entrypoint, "Ldate");
  2665. put('deleq, 'c!:c_entrypoint, "Ldeleq");
  2666. !#if (not common!-lisp!-mode)
  2667. put('delete, 'c!:c_entrypoint, "Ldelete");
  2668. !#endif
  2669. % put('difference, 'c!:c_entrypoint, "Ldifference2");
  2670. put('digit, 'c!:c_entrypoint, "Ldigitp");
  2671. !#if (not common!-lisp!-mode)
  2672. put('divide, 'c!:c_entrypoint, "Ldivide");
  2673. !#endif
  2674. put('eject, 'c!:c_entrypoint, "Leject");
  2675. put('endp, 'c!:c_entrypoint, "Lendp");
  2676. put('eq, 'c!:c_entrypoint, "Leq");
  2677. put('eqcar, 'c!:c_entrypoint, "Leqcar");
  2678. put('eql, 'c!:c_entrypoint, "Leql");
  2679. put('eqn, 'c!:c_entrypoint, "Leqn");
  2680. !#if common!-lisp!-mode
  2681. put('equal, 'c!:c_entrypoint, "Lcl_equal");
  2682. !#else
  2683. put('equal, 'c!:c_entrypoint, "Lequal");
  2684. !#endif
  2685. put('error, 'c!:c_entrypoint, "Lerror");
  2686. put('error1, 'c!:c_entrypoint, "Lerror1");
  2687. % put('errorset, 'c!:c_entrypoint, "Lerrorset");
  2688. put('evenp, 'c!:c_entrypoint, "Levenp");
  2689. put('evlis, 'c!:c_entrypoint, "Levlis");
  2690. put('explode, 'c!:c_entrypoint, "Lexplode");
  2691. put('explode2, 'c!:c_entrypoint, "Lexplodec");
  2692. put('explodec, 'c!:c_entrypoint, "Lexplodec");
  2693. put('expt, 'c!:c_entrypoint, "Lexpt");
  2694. put('fasldef, 'c!:c_entrypoint, "Lfasldef");
  2695. put('faslstart, 'c!:c_entrypoint, "Lfaslstart");
  2696. put('faslwrite, 'c!:c_entrypoint, "Lfaslwrite");
  2697. put('fix, 'c!:c_entrypoint, "Ltruncate");
  2698. put('fixp, 'c!:c_entrypoint, "Lfixp");
  2699. put('flag, 'c!:c_entrypoint, "Lflag");
  2700. put('flagp!*!*, 'c!:c_entrypoint, "Lflagp");
  2701. put('flagp, 'c!:c_entrypoint, "Lflagp");
  2702. put('flagpcar, 'c!:c_entrypoint, "Lflagpcar");
  2703. put('float, 'c!:c_entrypoint, "Lfloat");
  2704. put('floatp, 'c!:c_entrypoint, "Lfloatp");
  2705. put('fluidp, 'c!:c_entrypoint, "Lsymbol_specialp");
  2706. put('gcdn, 'c!:c_entrypoint, "Lgcd");
  2707. put('gctime, 'c!:c_entrypoint, "Lgctime");
  2708. put('gensym, 'c!:c_entrypoint, "Lgensym");
  2709. put('gensym1, 'c!:c_entrypoint, "Lgensym1");
  2710. put('geq, 'c!:c_entrypoint, "Lgeq");
  2711. put('get!*, 'c!:c_entrypoint, "Lget");
  2712. % put('get, 'c!:c_entrypoint, "Lget");
  2713. put('getenv, 'c!:c_entrypoint, "Lgetenv");
  2714. put('getv, 'c!:c_entrypoint, "Lgetv");
  2715. !#if common!-lisp!-mode
  2716. put('svref, 'c!:c_entrypoint, "Lgetv");
  2717. !#endif
  2718. put('globalp, 'c!:c_entrypoint, "Lsymbol_globalp");
  2719. put('greaterp, 'c!:c_entrypoint, "Lgreaterp");
  2720. put('iadd1, 'c!:c_entrypoint, "Liadd1");
  2721. put('idifference, 'c!:c_entrypoint, "Lidifference");
  2722. put('idp, 'c!:c_entrypoint, "Lsymbolp");
  2723. put('igreaterp, 'c!:c_entrypoint, "Ligreaterp");
  2724. put('ilessp, 'c!:c_entrypoint, "Lilessp");
  2725. put('iminus, 'c!:c_entrypoint, "Liminus");
  2726. put('iminusp, 'c!:c_entrypoint, "Liminusp");
  2727. put('indirect, 'c!:c_entrypoint, "Lindirect");
  2728. put('integerp, 'c!:c_entrypoint, "Lintegerp");
  2729. !#if (not common!-lisp!-mode)
  2730. put('intern, 'c!:c_entrypoint, "Lintern");
  2731. !#endif
  2732. put('iplus2, 'c!:c_entrypoint, "Liplus2");
  2733. put('iquotient, 'c!:c_entrypoint, "Liquotient");
  2734. put('iremainder, 'c!:c_entrypoint, "Liremainder");
  2735. put('irightshift, 'c!:c_entrypoint, "Lirightshift");
  2736. put('isub1, 'c!:c_entrypoint, "Lisub1");
  2737. put('itimes2, 'c!:c_entrypoint, "Litimes2");
  2738. % put('lcm, 'c!:c_entrypoint, "Llcm");
  2739. put('length, 'c!:c_entrypoint, "Llength");
  2740. put('lengthc, 'c!:c_entrypoint, "Llengthc");
  2741. put('leq, 'c!:c_entrypoint, "Lleq");
  2742. put('lessp, 'c!:c_entrypoint, "Llessp");
  2743. put('linelength, 'c!:c_entrypoint, "Llinelength");
  2744. % put('list2!*, 'c!:c_entrypoint, "Llist2star");
  2745. % put('list2, 'c!:c_entrypoint, "Llist2");
  2746. % put('list3, 'c!:c_entrypoint, "Llist3");
  2747. !#if (not common!-lisp!-mode)
  2748. put('liter, 'c!:c_entrypoint, "Lalpha_char_p");
  2749. !#endif
  2750. put('load!-module, 'c!:c_entrypoint, "Lload_module");
  2751. % put('lognot, 'c!:c_entrypoint, "Llognot");
  2752. put('lposn, 'c!:c_entrypoint, "Llposn");
  2753. put('macro!-function, 'c!:c_entrypoint, "Lmacro_function");
  2754. put('macroexpand!-1, 'c!:c_entrypoint, "Lmacroexpand_1");
  2755. put('macroexpand, 'c!:c_entrypoint, "Lmacroexpand");
  2756. put('make!-bps, 'c!:c_entrypoint, "Lget_bps");
  2757. put('make!-global, 'c!:c_entrypoint, "Lmake_global");
  2758. put('make!-simple!-string, 'c!:c_entrypoint, "Lsmkvect");
  2759. put('make!-special, 'c!:c_entrypoint, "Lmake_special");
  2760. put('mapstore, 'c!:c_entrypoint, "Lmapstore");
  2761. put('max2, 'c!:c_entrypoint, "Lmax2");
  2762. !#if (not common!-lisp!-mode)
  2763. put('member, 'c!:c_entrypoint, "Lmember");
  2764. !#endif
  2765. put('memq, 'c!:c_entrypoint, "Lmemq");
  2766. put('min2, 'c!:c_entrypoint, "Lmin2");
  2767. put('minus, 'c!:c_entrypoint, "Lminus");
  2768. put('minusp, 'c!:c_entrypoint, "Lminusp");
  2769. put('mkquote, 'c!:c_entrypoint, "Lmkquote");
  2770. put('mkvect, 'c!:c_entrypoint, "Lmkvect");
  2771. put('mod, 'c!:c_entrypoint, "Lmod");
  2772. put('modular!-difference, 'c!:c_entrypoint, "Lmodular_difference");
  2773. put('modular!-expt, 'c!:c_entrypoint, "Lmodular_expt");
  2774. put('modular!-minus, 'c!:c_entrypoint, "Lmodular_minus");
  2775. put('modular!-number, 'c!:c_entrypoint, "Lmodular_number");
  2776. put('modular!-plus, 'c!:c_entrypoint, "Lmodular_plus");
  2777. put('modular!-quotient, 'c!:c_entrypoint, "Lmodular_quotient");
  2778. put('modular!-reciprocal, 'c!:c_entrypoint, "Lmodular_reciprocal");
  2779. put('modular!-times, 'c!:c_entrypoint, "Lmodular_times");
  2780. put('nconc, 'c!:c_entrypoint, "Lnconc");
  2781. % put('ncons, 'c!:c_entrypoint, "Lncons");
  2782. put('neq, 'c!:c_entrypoint, "Lneq");
  2783. % put('next!-random!-number, 'c!:c_entrypoint, "Lnext_random");
  2784. put('not, 'c!:c_entrypoint, "Lnull");
  2785. put('null, 'c!:c_entrypoint, "Lnull");
  2786. put('numberp, 'c!:c_entrypoint, "Lnumberp");
  2787. put('oddp, 'c!:c_entrypoint, "Loddp");
  2788. put('onep, 'c!:c_entrypoint, "Lonep");
  2789. put('orderp, 'c!:c_entrypoint, "Lorderp");
  2790. % put('ordp, 'c!:c_entrypoint, "Lorderp");
  2791. put('pagelength, 'c!:c_entrypoint, "Lpagelength");
  2792. put('pairp, 'c!:c_entrypoint, "Lconsp");
  2793. put('plist, 'c!:c_entrypoint, "Lplist");
  2794. % put('plus2, 'c!:c_entrypoint, "Lplus2");
  2795. put('plusp, 'c!:c_entrypoint, "Lplusp");
  2796. put('posn, 'c!:c_entrypoint, "Lposn");
  2797. !#if (not common!-lisp!-mode)
  2798. put('prin, 'c!:c_entrypoint, "Lprin");
  2799. put('prin1, 'c!:c_entrypoint, "Lprin");
  2800. put('prin2, 'c!:c_entrypoint, "Lprinc");
  2801. put('princ, 'c!:c_entrypoint, "Lprinc");
  2802. put('print, 'c!:c_entrypoint, "Lprint");
  2803. put('printc, 'c!:c_entrypoint, "Lprintc");
  2804. !#endif
  2805. put('put, 'c!:c_entrypoint, "Lputprop");
  2806. put('putv!-char, 'c!:c_entrypoint, "Lsputv");
  2807. put('putv, 'c!:c_entrypoint, "Lputv");
  2808. put('qcaar, 'c!:c_entrypoint, "Lcaar");
  2809. put('qcadr, 'c!:c_entrypoint, "Lcadr");
  2810. put('qcar, 'c!:c_entrypoint, "Lcar");
  2811. put('qcdar, 'c!:c_entrypoint, "Lcdar");
  2812. put('qcddr, 'c!:c_entrypoint, "Lcddr");
  2813. put('qcdr, 'c!:c_entrypoint, "Lcdr");
  2814. put('qgetv, 'c!:c_entrypoint, "Lgetv");
  2815. % put('quotient, 'c!:c_entrypoint, "Lquotient");
  2816. % put('random, 'c!:c_entrypoint, "Lrandom");
  2817. % put('rational, 'c!:c_entrypoint, "Lrational");
  2818. put('rdf, 'c!:c_entrypoint, "Lrdf");
  2819. put('rds, 'c!:c_entrypoint, "Lrds");
  2820. !#if (not common!-lisp!-mode)
  2821. put('read, 'c!:c_entrypoint, "Lread");
  2822. put('readch, 'c!:c_entrypoint, "Lreadch");
  2823. !#endif
  2824. put('reclaim, 'c!:c_entrypoint, "Lgc");
  2825. % put('remainder, 'c!:c_entrypoint, "Lrem");
  2826. put('remd, 'c!:c_entrypoint, "Lremd");
  2827. put('remflag, 'c!:c_entrypoint, "Lremflag");
  2828. put('remob, 'c!:c_entrypoint, "Lunintern");
  2829. put('remprop, 'c!:c_entrypoint, "Lremprop");
  2830. put('representation, 'c!:c_entrypoint, "Lrepresentation");
  2831. put('reverse, 'c!:c_entrypoint, "Lreverse");
  2832. put('reversip, 'c!:c_entrypoint, "Lnreverse");
  2833. put('rplaca, 'c!:c_entrypoint, "Lrplaca");
  2834. put('rplacd, 'c!:c_entrypoint, "Lrplacd");
  2835. put('schar, 'c!:c_entrypoint, "Lsgetv");
  2836. put('seprp, 'c!:c_entrypoint, "Lwhitespace_char_p");
  2837. put('set!-small!-modulus, 'c!:c_entrypoint, "Lset_small_modulus");
  2838. put('set, 'c!:c_entrypoint, "Lset");
  2839. put('smemq, 'c!:c_entrypoint, "Lsmemq");
  2840. put('spaces, 'c!:c_entrypoint, "Lxtab");
  2841. put('special!-char, 'c!:c_entrypoint, "Lspecial_char");
  2842. put('special!-form!-p, 'c!:c_entrypoint, "Lspecial_form_p");
  2843. put('spool, 'c!:c_entrypoint, "Lspool");
  2844. put('stop, 'c!:c_entrypoint, "Lstop");
  2845. put('stringp, 'c!:c_entrypoint, "Lstringp");
  2846. % put('sub1, 'c!:c_entrypoint, "Lsub1");
  2847. !#if common!-lisp!-mode
  2848. put('!1!-, 'c!:c_entrypoint, "Lsub1");
  2849. !#endif
  2850. put('subla, 'c!:c_entrypoint, "Lsubla");
  2851. !#if (not common!-lisp!-mode)
  2852. put('sublis, 'c!:c_entrypoint, "Lsublis");
  2853. !#endif
  2854. put('subst, 'c!:c_entrypoint, "Lsubst");
  2855. put('symbol!-env, 'c!:c_entrypoint, "Lsymbol_env");
  2856. put('symbol!-function, 'c!:c_entrypoint, "Lsymbol_function");
  2857. put('symbol!-name, 'c!:c_entrypoint, "Lsymbol_name");
  2858. put('symbol!-set!-definition, 'c!:c_entrypoint, "Lsymbol_set_definition");
  2859. put('symbol!-set!-env, 'c!:c_entrypoint, "Lsymbol_set_env");
  2860. put('symbol!-value, 'c!:c_entrypoint, "Lsymbol_value");
  2861. put('system, 'c!:c_entrypoint, "Lsystem");
  2862. put('terpri, 'c!:c_entrypoint, "Lterpri");
  2863. put('threevectorp, 'c!:c_entrypoint, "Lthreevectorp");
  2864. put('time, 'c!:c_entrypoint, "Ltime");
  2865. % put('times2, 'c!:c_entrypoint, "Ltimes2");
  2866. put('ttab, 'c!:c_entrypoint, "Lttab");
  2867. put('tyo, 'c!:c_entrypoint, "Ltyo");
  2868. put('unmake!-global, 'c!:c_entrypoint, "Lunmake_global");
  2869. put('unmake!-special, 'c!:c_entrypoint, "Lunmake_special");
  2870. put('upbv, 'c!:c_entrypoint, "Lupbv");
  2871. !#if common!-lisp!-mode
  2872. put('vectorp, 'c!:c_entrypoint, "Lvectorp");
  2873. !#else
  2874. put('vectorp, 'c!:c_entrypoint, "Lsimple_vectorp");
  2875. !#endif
  2876. put('verbos, 'c!:c_entrypoint, "Lverbos");
  2877. put('wrs, 'c!:c_entrypoint, "Lwrs");
  2878. put('xcons, 'c!:c_entrypoint, "Lxcons");
  2879. put('xtab, 'c!:c_entrypoint, "Lxtab");
  2880. % put('orderp, 'c!:c_entrypoint, "Lorderp"); being retired.
  2881. put('zerop, 'c!:c_entrypoint, "Lzerop");
  2882. % The following can be called without having to provide an environment
  2883. % or arg-count. The compiler should check the number of args being
  2884. % passed matches the expected number.
  2885. put('cons, 'c!:direct_entrypoint, 2 . "cons");
  2886. put('ncons, 'c!:direct_entrypoint, 1 . "ncons");
  2887. put('list2, 'c!:direct_entrypoint, 2 . "list2");
  2888. put('list2!*, 'c!:direct_entrypoint, 3 . "list2star");
  2889. put('acons, 'c!:direct_entrypoint, 3 . "acons");
  2890. put('list3, 'c!:direct_entrypoint, 3 . "list3");
  2891. put('plus2, 'c!:direct_entrypoint, 2 . "plus2");
  2892. put('difference, 'c!:direct_entrypoint, 2 . "difference2");
  2893. put('add1, 'c!:direct_entrypoint, 1 . "add1");
  2894. put('sub1, 'c!:direct_entrypoint, 1 . "sub1");
  2895. !#if (not common!-lisp!-mode)
  2896. put('get, 'c!:direct_entrypoint, 2 . "get");
  2897. !#endif
  2898. put('lognot, 'c!:direct_entrypoint, 1 . "lognot");
  2899. put('ash, 'c!:direct_entrypoint, 2 . "ash");
  2900. put('quotient, 'c!:direct_entrypoint, 2 . "quot2");
  2901. put('remainder, 'c!:direct_entrypoint, 2 . "Cremainder");
  2902. put('times2, 'c!:direct_entrypoint, 2 . "times2");
  2903. put('minus, 'c!:direct_entrypoint, 1 . "negate");
  2904. put('rational, 'c!:direct_entrypoint, 1 . "rational");
  2905. put('lessp, 'c!:direct_predicate, 2 . "lessp2");
  2906. put('leq, 'c!:direct_predicate, 2 . "lesseq2");
  2907. put('greaterp, 'c!:direct_predicate, 2 . "greaterp2");
  2908. put('geq, 'c!:direct_predicate, 2 . "geq2");
  2909. put('zerop, 'c!:direct_predicate, 1 . "zerop");
  2910. "C entrypoints established" >>;
  2911. flag(
  2912. '(atom atsoc codep constantp deleq digit endp eq eqcar evenp
  2913. eql fixp flagp flagpcar floatp get globalp iadd1 idifference idp
  2914. igreaterp ilessp iminus iminusp indirect integerp iplus2 irightshift
  2915. isub1 itimes2 liter memq minusp modular!-difference modular!-expt
  2916. modular!-minus modular!-number modular!-plus modular!-times not
  2917. null numberp onep pairp plusp qcaar qcadr qcar qcdar qcddr
  2918. qcdr remflag remprop reversip seprp special!-form!-p stringp
  2919. symbol!-env symbol!-name symbol!-value threevectorp vectorp zerop),
  2920. 'c!:no_errors);
  2921. end;
  2922. % End of ccomp.red