ccomp.red 120 KB

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