Lower.mod 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403
  1. IMPLEMENTATION MODULE Lower;
  2. (* Scalar/boolean/control-flow walk (L0-L2): see Lower.def and
  3. docs/plan-lower.md. No FORWARD declarations: sequence iteration and
  4. statement dispatch are merged into CanStmt / LowerStmt. *)
  5. IMPORT AST, SymTab, QbeGen;
  6. (* ---------------- self-contained symbol tables (zero SymTab surface) ----
  7. Flat arrays only, no ARRAY OF RECORD: a record's array field loses its
  8. length word in static array data, and V3 miscompiles that when the
  9. field is passed as an open array (docs/wip/nested-array-field-bug.mod).
  10. Names live in flat CHAR arrays indexed manually at slot * 64. *)
  11. CONST
  12. MaxSym = 512;
  13. MaxName = 63;
  14. MaxProc = 64;
  15. MaxPar = 32;
  16. VAR
  17. symName : ARRAY [0 .. MaxSym * 64 - 1] OF CHAR;
  18. symKind : ARRAY [0 .. MaxSym - 1] OF INTEGER;
  19. symTy : ARRAY [0 .. MaxSym - 1] OF SymTab.TypeIndex;
  20. nSyms : CARDINAL;
  21. procName : ARRAY [0 .. MaxProc * 64 - 1] OF CHAR;
  22. procUid : ARRAY [0 .. MaxProc - 1] OF CARDINAL;
  23. procRes : ARRAY [0 .. MaxProc - 1] OF SymTab.TypeIndex;
  24. procDep : ARRAY [0 .. MaxProc - 1] OF CARDINAL;
  25. procExt : ARRAY [0 .. MaxProc - 1] OF BOOLEAN;
  26. procNpar : ARRAY [0 .. MaxProc - 1] OF CARDINAL;
  27. parTy : ARRAY [0 .. MaxProc * MaxPar - 1] OF SymTab.TypeIndex;
  28. parVar : ARRAY [0 .. MaxProc * MaxPar - 1] OF BOOLEAN;
  29. parName : ARRAY [0 .. MaxProc * MaxPar * 64 - 1] OF CHAR;
  30. nProcs : CARDINAL;
  31. withRec : ARRAY [0 .. 15] OF SymTab.TypeIndex;
  32. withTop : CARDINAL;
  33. PROCEDURE CopyN (src: ARRAY OF CHAR; VAR dst: ARRAY OF CHAR);
  34. VAR i: CARDINAL;
  35. BEGIN
  36. i := 0;
  37. WHILE (i < MaxName) AND (src[i] # CHR(0)) DO dst[i] := src[i]; INC(i) END;
  38. dst[i] := CHR(0)
  39. END CopyN;
  40. PROCEDURE CopySpan (src: ARRAY OF CHAR; VAR dst: ARRAY OF CHAR;
  41. srcOff, dstOff: CARDINAL);
  42. VAR i: CARDINAL;
  43. BEGIN
  44. i := 0;
  45. WHILE (i < MaxName) AND (src[srcOff + i] # CHR(0)) DO
  46. dst[dstOff + i] := src[srcOff + i]; INC(i)
  47. END;
  48. dst[dstOff + i] := CHR(0)
  49. END CopySpan;
  50. PROCEDURE Reset;
  51. BEGIN
  52. nSyms := 0; nProcs := 0
  53. END Reset;
  54. PROCEDURE NoteVar (name: ARRAY OF CHAR; kind: INTEGER; t: SymTab.TypeIndex);
  55. BEGIN
  56. IF nSyms >= MaxSym THEN RETURN END;
  57. CopySpan(name, symName, 0, nSyms * 64);
  58. symKind[nSyms] := kind; symTy[nSyms] := t; INC(nSyms)
  59. END NoteVar;
  60. PROCEDURE ScopeEnter;
  61. BEGIN
  62. END ScopeEnter;
  63. PROCEDURE ScopeLeave;
  64. BEGIN
  65. END ScopeLeave;
  66. PROCEDURE NoteProc (name: ARRAY OF CHAR; uid: CARDINAL;
  67. res: SymTab.TypeIndex; depth: CARDINAL; ext: BOOLEAN);
  68. BEGIN
  69. IF nProcs >= MaxProc THEN RETURN END;
  70. CopySpan(name, procName, 0, nProcs * 64);
  71. procUid[nProcs] := uid; procRes[nProcs] := res;
  72. procDep[nProcs] := depth; procExt[nProcs] := ext;
  73. procNpar[nProcs] := 0;
  74. INC(nProcs)
  75. END NoteProc;
  76. PROCEDURE SetProcRes (t: SymTab.TypeIndex);
  77. BEGIN
  78. IF nProcs > 0 THEN procRes[nProcs - 1] := t END
  79. END SetProcRes;
  80. PROCEDURE NoteParam (name: ARRAY OF CHAR; t: SymTab.TypeIndex; isVar: BOOLEAN);
  81. VAR j: CARDINAL;
  82. BEGIN
  83. IF nProcs = 0 THEN RETURN END;
  84. j := procNpar[nProcs - 1];
  85. IF j >= MaxPar THEN RETURN END;
  86. CopySpan(name, parName, 0, (nProcs - 1) * MaxPar * 64 + j * 64);
  87. parTy[(nProcs - 1) * MaxPar + j] := t;
  88. parVar[(nProcs - 1) * MaxPar + j] := isVar;
  89. procNpar[nProcs - 1] := j + 1
  90. END NoteParam;
  91. PROCEDURE FindSym (name: ARRAY OF CHAR; VAR kind: INTEGER;
  92. VAR t: SymTab.TypeIndex): BOOLEAN;
  93. VAR i: CARDINAL; j: CARDINAL; ok: BOOLEAN;
  94. BEGIN
  95. i := nSyms;
  96. WHILE i > 0 DO
  97. DEC(i);
  98. ok := TRUE; j := 0;
  99. WHILE ok AND (j < 64) AND (symName[i * 64 + j] # CHR(0)) DO
  100. IF symName[i * 64 + j] # name[j] THEN ok := FALSE END;
  101. INC(j)
  102. END;
  103. IF ok AND (symName[i * 64 + j] = name[j]) THEN
  104. kind := symKind[i]; t := symTy[i]; RETURN TRUE
  105. END
  106. END;
  107. RETURN FALSE
  108. END FindSym;
  109. PROCEDURE FindProc (name: ARRAY OF CHAR): INTEGER;
  110. VAR i: CARDINAL; j: CARDINAL; ok: BOOLEAN;
  111. BEGIN
  112. i := nProcs;
  113. WHILE i > 0 DO
  114. DEC(i);
  115. ok := TRUE; j := 0;
  116. WHILE ok AND (j < 64) AND (procName[i * 64 + j] # CHR(0)) DO
  117. IF procName[i * 64 + j] # name[j] THEN ok := FALSE END;
  118. INC(j)
  119. END;
  120. IF ok AND (procName[i * 64 + j] = name[j]) THEN RETURN VAL(INTEGER, i) END
  121. END;
  122. RETURN -1
  123. END FindProc;
  124. PROCEDURE Resolve (nm: ARRAY OF CHAR; VAR k: INTEGER;
  125. VAR t: SymTab.TypeIndex): BOOLEAN;
  126. VAR kind: INTEGER; ti: SymTab.TypeIndex;
  127. BEGIN
  128. IF FindSym(nm, kind, ti) THEN k := kind; t := ti; RETURN TRUE END;
  129. IF SymTab.Lookup(nm) THEN k := SymTab.SymKind(nm); t := SymTab.SymType(nm);
  130. RETURN TRUE
  131. END;
  132. RETURN FALSE
  133. END Resolve;
  134. PROCEDURE ProcInfo (nm: ARRAY OF CHAR; VAR uid: CARDINAL;
  135. VAR res: SymTab.TypeIndex; VAR depth: CARDINAL;
  136. VAR ext: BOOLEAN; VAR npar: CARDINAL): BOOLEAN;
  137. VAR i: INTEGER;
  138. BEGIN
  139. i := FindProc(nm);
  140. IF i < 0 THEN RETURN FALSE END;
  141. uid := procUid[i]; res := procRes[i]; depth := procDep[i];
  142. ext := procExt[i]; npar := procNpar[i];
  143. RETURN TRUE
  144. END ProcInfo;
  145. PROCEDURE ParamInfo (nm: ARRAY OF CHAR; i: CARDINAL;
  146. VAR t: SymTab.TypeIndex; VAR isVar: BOOLEAN;
  147. VAR pn: ARRAY OF CHAR): BOOLEAN;
  148. VAR k: INTEGER;
  149. BEGIN
  150. k := FindProc(nm);
  151. IF (k < 0) OR (i >= procNpar[k]) THEN RETURN FALSE END;
  152. t := parTy[VAL(CARDINAL, k) * MaxPar + i];
  153. isVar := parVar[VAL(CARDINAL, k) * MaxPar + i];
  154. CopySpan(parName, pn, VAL(CARDINAL, k) * MaxPar * 64 + i * 64, 0);
  155. RETURN TRUE
  156. END ParamInfo;
  157. PROCEDURE WithField (nm: ARRAY OF CHAR; VAR k: INTEGER;
  158. VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal): BOOLEAN;
  159. (* Resolves a bare ident as a field of an open WITH record (innermost
  160. first), leaving the field address in q and k=KindField. *)
  161. VAR wt: CARDINAL; fo: INTEGER; qb: QbeGen.QVal;
  162. BEGIN
  163. wt := withTop;
  164. WHILE wt > 0 DO
  165. DEC(wt);
  166. IF SymTab.FieldExists(withRec[wt], nm) THEN
  167. t := SymTab.FieldType(withRec[wt], nm);
  168. fo := SymTab.FieldOffset(withRec[wt], nm);
  169. k := SymTab.KindField;
  170. IF QbeGen.TopWith(qb) THEN QbeGen.FieldAddr(qb, fo, q)
  171. ELSE QbeGen.CopyOp("0", q)
  172. END;
  173. RETURN TRUE
  174. END
  175. END;
  176. RETURN FALSE
  177. END WithField;
  178. PROCEDURE Name (n: AST.Node; VAR s: ARRAY OF CHAR);
  179. BEGIN
  180. IF n = AST.NoNode THEN s[0] := CHR(0)
  181. ELSE AST.Txt(AST.Child(n, 0), s)
  182. END
  183. END Name;
  184. PROCEDURE ParamName (proc: ARRAY OF CHAR; i: CARDINAL;
  185. VAR s: ARRAY OF CHAR);
  186. VAR t: SymTab.TypeIndex; isV: BOOLEAN;
  187. BEGIN
  188. IF NOT ParamInfo(proc, i, t, isV, s) THEN s[0] := CHR(0) END
  189. END ParamName;
  190. PROCEDURE IsArith (op: INTEGER): BOOLEAN;
  191. BEGIN
  192. RETURN (op = AST.OpAdd) OR (op = AST.OpSub) OR (op = AST.OpMul)
  193. OR (op = AST.OpDiv) OR (op = AST.OpMod)
  194. END IsArith;
  195. PROCEDURE IsRel (op: INTEGER): BOOLEAN;
  196. BEGIN
  197. RETURN ((op >= AST.OpEq) AND (op <= AST.OpGe)) OR (op = AST.OpIn)
  198. END IsRel;
  199. PROCEDURE RelSym (a: INTEGER; VAR s: INTEGER): BOOLEAN;
  200. BEGIN
  201. IF a = AST.OpEq THEN s := SymTab.OpEq
  202. ELSIF a = AST.OpNe THEN s := SymTab.OpNeq1
  203. ELSIF a = AST.OpLt THEN s := SymTab.OpLt
  204. ELSIF a = AST.OpLe THEN s := SymTab.OpLe
  205. ELSIF a = AST.OpGt THEN s := SymTab.OpGt
  206. ELSIF a = AST.OpGe THEN s := SymTab.OpGe
  207. ELSE RETURN FALSE
  208. END;
  209. RETURN TRUE
  210. END RelSym;
  211. PROCEDURE IsScalarClass (cls: INTEGER): BOOLEAN;
  212. BEGIN
  213. RETURN (cls = SymTab.ClInt) OR (cls = SymTab.ClBool)
  214. OR (cls = SymTab.ClChar) OR (cls = SymTab.ClUChar)
  215. OR (cls = SymTab.ClEnum)
  216. END IsScalarClass;
  217. PROCEDURE IsSimpleScalar (n: AST.Node): BOOLEAN;
  218. VAR nm: SymTab.Name; k: INTEGER; t: SymTab.TypeIndex;
  219. BEGIN
  220. IF (AST.Kind(n) # AST.NkDesignator) OR (AST.NChild(n) # 1) THEN
  221. RETURN FALSE END;
  222. IF AST.Kind(AST.Child(n, 0)) # AST.NkIdent THEN RETURN FALSE END;
  223. Name(AST.Child(n, 0), nm);
  224. IF NOT Resolve(nm, k, t) THEN RETURN FALSE END;
  225. IF (k # SymTab.KindVar) AND (k # SymTab.KindParam)
  226. AND (k # SymTab.KindConst) THEN
  227. RETURN FALSE END;
  228. IF SymTab.Equal(nm, "TRUE") OR SymTab.Equal(nm, "FALSE") THEN
  229. RETURN TRUE END;
  230. RETURN IsScalarClass(SymTab.ClassOf(t))
  231. END IsSimpleScalar;
  232. PROCEDURE CalleeName (call: AST.Node; VAR nm: SymTab.Name);
  233. (* The callee of NkCall: child 0 is a designator (or bare ident). *)
  234. VAR d: AST.Node;
  235. BEGIN
  236. nm[0] := CHR(0);
  237. d := AST.Child(call, 0);
  238. IF d = AST.NoNode THEN RETURN END;
  239. IF AST.Kind(d) = AST.NkDesignator THEN d := AST.Child(d, 0) END;
  240. IF (d # AST.NoNode) AND (AST.Kind(d) = AST.NkIdent) THEN Name(d, nm) END
  241. END CalleeName;
  242. PROCEDURE IsCall (n: AST.Node): BOOLEAN;
  243. VAR nm: SymTab.Name;
  244. BEGIN
  245. IF (AST.Kind(n) # AST.NkCall) OR (AST.NChild(n) < 1) THEN RETURN FALSE END;
  246. CalleeName(n, nm);
  247. RETURN FindProc(nm) >= 0
  248. END IsCall;
  249. PROCEDURE CanCallArgs (n: AST.Node): BOOLEAN;
  250. VAR nm: SymTab.Name; i: CARDINAL;
  251. uid, depth, np: CARDINAL; res: SymTab.TypeIndex; ext: BOOLEAN;
  252. BEGIN
  253. CalleeName(n, nm);
  254. IF NOT ProcInfo(nm, uid, res, depth, ext, np) THEN RETURN FALSE END;
  255. IF np # (AST.NChild(n) - 1) THEN RETURN FALSE END;
  256. i := 1;
  257. WHILE i < AST.NChild(n) DO
  258. IF NOT CanExpr(AST.Child(n, i)) THEN RETURN FALSE END;
  259. INC(i)
  260. END;
  261. RETURN TRUE
  262. END CanCallArgs;
  263. PROCEDURE CanType (t: SymTab.TypeIndex): BOOLEAN;
  264. VAR cls: INTEGER;
  265. BEGIN
  266. IF t = SymTab.InvalidType THEN RETURN FALSE END;
  267. cls := SymTab.ClassOf(t);
  268. RETURN (cls = SymTab.ClInt) OR (cls = SymTab.ClBool)
  269. OR (cls = SymTab.ClChar) OR (cls = SymTab.ClUChar)
  270. OR (cls = SymTab.ClEnum) OR (cls = SymTab.ClReal)
  271. OR (cls = SymTab.ClLong) OR (cls = SymTab.ClArray)
  272. OR (cls = SymTab.ClSet) OR (cls = SymTab.ClRecord)
  273. OR (cls = SymTab.ClPtr)
  274. END CanType;
  275. PROCEDURE CanWithField (nm: ARRAY OF CHAR; VAR t: SymTab.TypeIndex): BOOLEAN;
  276. VAR wt: CARDINAL;
  277. BEGIN
  278. wt := withTop;
  279. WHILE wt > 0 DO
  280. DEC(wt);
  281. IF SymTab.FieldExists(withRec[wt], nm) THEN
  282. t := SymTab.FieldType(withRec[wt], nm); RETURN TRUE
  283. END
  284. END;
  285. RETURN FALSE
  286. END CanWithField;
  287. PROCEDURE DesignTypeOf (n: AST.Node): SymTab.TypeIndex;
  288. (* Static type of a designator (no emit); used to push WITH scopes. *)
  289. VAR nm, fn: SymTab.Name; k: INTEGER; t: SymTab.TypeIndex;
  290. i: CARDINAL; sel: AST.Node;
  291. BEGIN
  292. IF (n = AST.NoNode) OR (AST.Kind(n) # AST.NkDesignator) THEN
  293. RETURN SymTab.InvalidType
  294. END;
  295. Name(AST.Child(n, 0), nm);
  296. IF NOT Resolve(nm, k, t) THEN
  297. IF NOT CanWithField(nm, t) THEN RETURN SymTab.InvalidType END
  298. END;
  299. i := 1;
  300. WHILE i < AST.NChild(n) DO
  301. sel := AST.Child(n, i);
  302. IF AST.Op(sel) = AST.SelField THEN
  303. Name(AST.Child(sel, 0), fn); t := SymTab.FieldType(t, fn)
  304. ELSIF AST.Op(sel) = AST.SelIndex THEN
  305. t := SymTab.ArrayElem(t)
  306. ELSIF AST.Op(sel) = AST.SelDeref THEN
  307. t := SymTab.PtrBase(t)
  308. END;
  309. INC(i)
  310. END;
  311. RETURN t
  312. END DesignTypeOf;
  313. PROCEDURE CanDesign (n: AST.Node): BOOLEAN;
  314. VAR nm, fn: SymTab.Name; k: INTEGER; t: SymTab.TypeIndex;
  315. i: CARDINAL; sel: AST.Node;
  316. BEGIN
  317. IF AST.Kind(n) # AST.NkDesignator THEN RETURN FALSE END;
  318. IF AST.Kind(AST.Child(n, 0)) # AST.NkIdent THEN RETURN FALSE END;
  319. Name(AST.Child(n, 0), nm);
  320. IF NOT Resolve(nm, k, t) THEN
  321. IF NOT CanWithField(nm, t) THEN RETURN FALSE END;
  322. k := SymTab.KindField
  323. END;
  324. IF (k # SymTab.KindVar) AND (k # SymTab.KindParam)
  325. AND (k # SymTab.KindConst) AND (k # SymTab.KindField) THEN
  326. RETURN FALSE
  327. END;
  328. IF NOT CanType(t) THEN RETURN FALSE END;
  329. i := 1;
  330. WHILE i < AST.NChild(n) DO
  331. sel := AST.Child(n, i);
  332. IF AST.Op(sel) = AST.SelField THEN
  333. IF (t = SymTab.InvalidType)
  334. OR ((SymTab.ClassOf(t) # SymTab.ClRecord)
  335. AND (SymTab.ClassOf(t) # SymTab.ClClass)) THEN
  336. RETURN FALSE
  337. END;
  338. Name(AST.Child(sel, 0), fn);
  339. IF NOT SymTab.FieldExists(t, fn) THEN RETURN FALSE END;
  340. t := SymTab.FieldType(t, fn)
  341. ELSIF AST.Op(sel) = AST.SelIndex THEN
  342. IF (t = SymTab.InvalidType)
  343. OR (SymTab.ClassOf(t) # SymTab.ClArray) THEN RETURN FALSE END;
  344. IF NOT CanExpr(AST.Child(sel, 0)) THEN RETURN FALSE END;
  345. t := SymTab.ArrayElem(t)
  346. ELSIF AST.Op(sel) = AST.SelDeref THEN
  347. IF (t = SymTab.InvalidType)
  348. OR (SymTab.ClassOf(t) # SymTab.ClPtr) THEN RETURN FALSE END;
  349. t := SymTab.PtrBase(t)
  350. ELSE RETURN FALSE
  351. END;
  352. IF NOT CanType(t) THEN RETURN FALSE END;
  353. INC(i)
  354. END;
  355. RETURN TRUE
  356. END CanDesign;
  357. PROCEDURE CanBuiltin (n: AST.Node): BOOLEAN;
  358. VAR i: CARDINAL;
  359. BEGIN
  360. i := 1;
  361. WHILE i < AST.NChild(n) DO
  362. IF NOT CanExpr(AST.Child(n, i)) THEN RETURN FALSE END;
  363. INC(i)
  364. END;
  365. RETURN TRUE
  366. END CanBuiltin;
  367. PROCEDURE CanCaseLabel (lab: AST.Node): BOOLEAN;
  368. BEGIN
  369. IF AST.Kind(lab) = AST.NkSubrange THEN
  370. RETURN CanExpr(AST.Child(lab, 0)) AND CanExpr(AST.Child(lab, 1))
  371. END;
  372. RETURN CanExpr(lab)
  373. END CanCaseLabel;
  374. PROCEDURE CanExpr (n: AST.Node): BOOLEAN;
  375. VAR op: INTEGER; nm: SymTab.Name; i: CARDINAL;
  376. BEGIN
  377. IF n = AST.NoNode THEN RETURN FALSE END;
  378. IF AST.Kind(n) = AST.NkIntLit THEN RETURN TRUE END;
  379. IF AST.Kind(n) = AST.NkCharLit THEN RETURN TRUE END;
  380. IF AST.Kind(n) = AST.NkRealLit THEN RETURN TRUE END;
  381. IF AST.Kind(n) = AST.NkStrLit THEN RETURN TRUE END;
  382. IF AST.Kind(n) = AST.NkSetLit THEN
  383. i := 0;
  384. WHILE i < AST.NChild(n) DO
  385. IF AST.Kind(AST.Child(n, i)) = AST.NkSubrange THEN
  386. IF NOT CanExpr(AST.Child(AST.Child(n, i), 0)) THEN RETURN FALSE END;
  387. IF NOT CanExpr(AST.Child(AST.Child(n, i), 1)) THEN RETURN FALSE END
  388. ELSIF NOT CanExpr(AST.Child(n, i)) THEN RETURN FALSE
  389. END;
  390. INC(i)
  391. END;
  392. RETURN TRUE
  393. END;
  394. IF AST.Kind(n) = AST.NkDesignator THEN RETURN CanDesign(n) END;
  395. IF AST.Kind(n) = AST.NkCall THEN
  396. CalleeName(n, nm);
  397. IF IsBuiltin(nm) THEN RETURN CanBuiltin(n) END;
  398. RETURN IsCall(n) AND CanCallArgs(n)
  399. END;
  400. IF AST.Kind(n) = AST.NkUnary THEN
  401. op := AST.Op(n);
  402. IF (op # AST.OpSub) AND (op # AST.OpNot) THEN RETURN FALSE END;
  403. RETURN CanExpr(AST.Child(n, 0))
  404. END;
  405. IF AST.Kind(n) = AST.NkBinExpr THEN
  406. op := AST.Op(n);
  407. IF NOT (IsArith(op) OR IsRel(op)
  408. OR (op = AST.OpAnd) OR (op = AST.OpOr)) THEN
  409. RETURN FALSE END;
  410. RETURN CanExpr(AST.Child(n, 0)) AND CanExpr(AST.Child(n, 1))
  411. END;
  412. RETURN FALSE
  413. END CanExpr;
  414. PROCEDURE CanStmt (n: AST.Node): BOOLEAN;
  415. VAR i: CARDINAL; k: INTEGER; by: AST.Node; nm: SymTab.Name;
  416. arm: AST.Node; j: CARDINAL; withSave: CARDINAL; ok: BOOLEAN;
  417. BEGIN
  418. IF n = AST.NoNode THEN RETURN TRUE END;
  419. k := AST.Kind(n);
  420. IF k = AST.NkBlock THEN
  421. i := 0;
  422. WHILE i < AST.NChild(n) DO
  423. IF NOT CanStmt(AST.Child(n, i)) THEN RETURN FALSE END;
  424. INC(i)
  425. END;
  426. RETURN TRUE
  427. END;
  428. IF k = AST.NkAssign THEN
  429. RETURN CanDesign(AST.Child(n, 0)) AND CanExpr(AST.Child(n, 1))
  430. END;
  431. IF k = AST.NkIf THEN
  432. RETURN CanExpr(AST.Child(n, 0)) AND CanStmt(AST.Child(n, 1))
  433. AND CanStmt(AST.Child(n, 2))
  434. END;
  435. IF k = AST.NkWhile THEN
  436. RETURN CanExpr(AST.Child(n, 0)) AND CanStmt(AST.Child(n, 1))
  437. END;
  438. IF k = AST.NkRepeat THEN
  439. RETURN CanStmt(AST.Child(n, 0)) AND CanExpr(AST.Child(n, 1))
  440. END;
  441. IF k = AST.NkLoop THEN RETURN CanStmt(AST.Child(n, 0)) END;
  442. IF k = AST.NkExit THEN RETURN TRUE END;
  443. IF k = AST.NkFor THEN
  444. by := AST.Child(n, 3);
  445. IF (by # AST.NoNode) AND (AST.Kind(by) # AST.NkIntLit) THEN
  446. RETURN FALSE END;
  447. RETURN (AST.Kind(AST.Child(n, 0)) = AST.NkIdent)
  448. AND CanExpr(AST.Child(n, 1)) AND CanExpr(AST.Child(n, 2))
  449. AND CanStmt(AST.Child(n, 4))
  450. END;
  451. IF k = AST.NkWith THEN
  452. withSave := withTop;
  453. j := 0;
  454. WHILE j + 1 < AST.NChild(n) DO
  455. IF NOT CanDesign(AST.Child(n, j)) THEN
  456. withTop := withSave; RETURN FALSE
  457. END;
  458. IF withTop <= HIGH(withRec) THEN
  459. withRec[withTop] := DesignTypeOf(AST.Child(n, j)); INC(withTop)
  460. END;
  461. INC(j)
  462. END;
  463. ok := CanStmt(AST.Child(n, AST.NChild(n) - 1));
  464. withTop := withSave;
  465. RETURN ok
  466. END;
  467. IF k = AST.NkCase THEN
  468. IF NOT CanExpr(AST.Child(n, 0)) THEN RETURN FALSE END;
  469. i := 1;
  470. WHILE i < AST.NChild(n) DO
  471. arm := AST.Child(n, i);
  472. IF AST.Op(arm) = 1 THEN
  473. IF NOT CanStmt(AST.Child(arm, 0)) THEN RETURN FALSE END
  474. ELSE
  475. j := 0;
  476. WHILE j + 1 < AST.NChild(arm) DO
  477. IF NOT CanCaseLabel(AST.Child(arm, j)) THEN RETURN FALSE END;
  478. INC(j)
  479. END;
  480. IF NOT CanStmt(AST.Child(arm, AST.NChild(arm) - 1)) THEN
  481. RETURN FALSE
  482. END
  483. END;
  484. INC(i)
  485. END;
  486. RETURN TRUE
  487. END;
  488. IF k = AST.NkHalt THEN
  489. IF AST.Child(n, 0) = AST.NoNode THEN RETURN TRUE END;
  490. RETURN CanExpr(AST.Child(n, 0))
  491. END;
  492. IF k = AST.NkReturn THEN
  493. IF AST.Child(n, 0) = AST.NoNode THEN RETURN TRUE END;
  494. RETURN CanExpr(AST.Child(n, 0))
  495. END;
  496. IF k = AST.NkCall THEN
  497. CalleeName(n, nm);
  498. IF IsBuiltin(nm) THEN RETURN CanBuiltin(n) END;
  499. RETURN IsCall(n) AND CanCallArgs(n)
  500. END;
  501. RETURN FALSE
  502. END CanStmt;
  503. PROCEDURE CanDecl (c: AST.Node): BOOLEAN;
  504. VAR i: CARDINAL;
  505. BEGIN
  506. IF AST.Kind(c) = AST.NkTypeDecl THEN RETURN TRUE END;
  507. IF AST.Kind(c) = AST.NkVarDecl THEN
  508. IF NOT CanType(AST.Ty(c)) THEN RETURN FALSE END;
  509. IF AST.NChild(c) < 1 THEN RETURN FALSE END;
  510. i := 0;
  511. WHILE i < AST.NChild(c) DO
  512. IF AST.Kind(AST.Child(c, i)) # AST.NkIdent THEN RETURN FALSE END;
  513. INC(i)
  514. END;
  515. RETURN TRUE
  516. END;
  517. IF AST.Kind(c) = AST.NkConstDecl THEN
  518. RETURN IsScalarClass(SymTab.ClassOf(AST.Ty(c)))
  519. AND (AST.Kind(AST.Child(c, 1)) = AST.NkIntLit)
  520. END;
  521. IF AST.Kind(c) = AST.NkProcDecl THEN RETURN CanProc(c) END;
  522. RETURN FALSE
  523. END CanDecl;
  524. PROCEDURE CanDecls (seq: AST.Node): BOOLEAN;
  525. VAR i: CARDINAL; c: AST.Node;
  526. BEGIN
  527. IF seq = AST.NoNode THEN RETURN TRUE END;
  528. i := 0;
  529. WHILE i < AST.NChild(seq) DO
  530. c := AST.Child(seq, i);
  531. IF i = AST.MaxChild - 1 THEN
  532. IF NOT CanDecls(c) THEN RETURN FALSE END
  533. ELSIF AST.Kind(c) = AST.NkDeclSeq THEN
  534. IF NOT CanDecls(c) THEN RETURN FALSE END
  535. ELSIF NOT CanDecl(c) THEN RETURN FALSE
  536. END;
  537. INC(i)
  538. END;
  539. RETURN TRUE
  540. END CanDecls;
  541. PROCEDURE CanLower (unit: AST.Node): BOOLEAN;
  542. BEGIN
  543. withTop := 0;
  544. IF AST.Kind(unit) # AST.NkUnit THEN RETURN FALSE END;
  545. IF AST.Kind(AST.Child(unit, 0)) # AST.NkIdent THEN RETURN FALSE END;
  546. IF AST.Child(unit, 3) # AST.NoNode THEN RETURN FALSE END;
  547. RETURN CanDecls(AST.Child(unit, 1)) AND CanStmt(AST.Child(unit, 2))
  548. END CanLower;
  549. PROCEDURE CanProc (proc: AST.Node): BOOLEAN;
  550. VAR nm: SymTab.Name; i: CARDINAL;
  551. uid, depth, np: CARDINAL; res: SymTab.TypeIndex; ext: BOOLEAN;
  552. t: SymTab.TypeIndex; isV: BOOLEAN; pn: SymTab.Name;
  553. BEGIN
  554. IF AST.Op(proc) # 0 THEN RETURN FALSE END;
  555. Name(AST.Child(proc, 0), nm);
  556. IF NOT ProcInfo(nm, uid, res, depth, ext, np) THEN RETURN FALSE END;
  557. IF (res # SymTab.InvalidType) AND NOT IsScalarClass(SymTab.ClassOf(res)) THEN
  558. RETURN FALSE END;
  559. i := 0;
  560. WHILE i < np DO
  561. IF NOT ParamInfo(nm, i, t, isV, pn) THEN RETURN FALSE END;
  562. IF NOT IsScalarClass(SymTab.ClassOf(t)) THEN RETURN FALSE END;
  563. INC(i)
  564. END;
  565. RETURN CanDecls(AST.Child(proc, 2)) AND CanStmt(AST.Child(proc, 1))
  566. END CanProc;
  567. PROCEDURE FinalLoad (t: SymTab.TypeIndex; sfx: BOOLEAN; VAR q: QbeGen.QVal);
  568. (* Fact's final load after a designator/result suffix: scalars/pointers
  569. are loaded from their address; aggregates keep the address. *)
  570. VAR cls: INTEGER; q2: QbeGen.QVal;
  571. BEGIN
  572. IF NOT sfx THEN RETURN END;
  573. IF t = SymTab.InvalidType THEN QbeGen.CopyOp("0", q); RETURN END;
  574. cls := SymTab.ClassOf(t);
  575. IF (cls # SymTab.ClRecord) AND (cls # SymTab.ClSet)
  576. AND (cls # SymTab.ClArray) AND (cls # SymTab.ClClass) THEN
  577. QbeGen.ElemLoad(q, t, q2); QbeGen.CopyOp(q2, q)
  578. END
  579. END FinalLoad;
  580. PROCEDURE LowerDesign (n: AST.Node; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
  581. VAR q: QbeGen.QVal; VAR qn: SymTab.Name;
  582. VAR sfx: BOOLEAN);
  583. (* Base ident then selectors (mirrors the grammar's Design). Leaves the
  584. address in q with sfx=TRUE for selectors; base vars/consts load. *)
  585. VAR nm, fn: SymTab.Name; cv: QbeGen.QVal; cls, op: INTEGER;
  586. i: CARDINAL; sel: AST.Node; eT, it: SymTab.TypeIndex;
  587. iq, ql, qlo, qhi, qe: QbeGen.QVal;
  588. lo, hi, fo: INTEGER; isOpen: BOOLEAN;
  589. BEGIN
  590. Name(AST.Child(n, 0), nm);
  591. QbeGen.CopyOp(nm, qn);
  592. sfx := FALSE;
  593. IF NOT Resolve(nm, k, t) THEN
  594. IF NOT WithField(nm, k, t, q) THEN
  595. t := SymTab.InvalidType; k := -1; QbeGen.CopyOp("0", q); RETURN
  596. END;
  597. sfx := TRUE
  598. END;
  599. IF k = SymTab.KindConst THEN
  600. IF SymTab.Equal(nm, "TRUE") THEN
  601. t := SymTab.BoolType(); QbeGen.CopyOp("1", q)
  602. ELSIF SymTab.Equal(nm, "FALSE") THEN
  603. t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
  604. ELSIF SymTab.Equal(nm, "NIL") THEN
  605. QbeGen.CopyOp("0", q)
  606. ELSIF SymTab.GetSymVal(nm, cv) AND QbeGen.IsImm(cv) THEN
  607. QbeGen.CopyOp(cv, q)
  608. ELSE QbeGen.CopyOp("0", q)
  609. END
  610. ELSIF (k = SymTab.KindVar) OR (k = SymTab.KindParam) THEN
  611. cls := SymTab.ClassOf(t);
  612. IF (cls = SymTab.ClInt) OR (cls = SymTab.ClBool)
  613. OR (cls = SymTab.ClChar) OR (cls = SymTab.ClUChar)
  614. OR (cls = SymTab.ClEnum) OR (cls = SymTab.ClReal) THEN
  615. QbeGen.LoadVar(nm, cls = SymTab.ClReal, q)
  616. ELSIF (cls = SymTab.ClPtr) OR (cls = SymTab.ClProc) THEN
  617. QbeGen.LoadPtr(nm, q)
  618. ELSIF cls = SymTab.ClLong THEN
  619. QbeGen.LoadLong(nm, q)
  620. ELSE QbeGen.AddrOf(nm, q)
  621. END
  622. ELSIF k = SymTab.KindField THEN
  623. (* q already holds the field address (WithField) *)
  624. ELSE QbeGen.CopyOp("0", q)
  625. END;
  626. i := 1;
  627. WHILE i < AST.NChild(n) DO
  628. sel := AST.Child(n, i);
  629. op := AST.Op(sel);
  630. IF op = AST.SelField THEN
  631. Name(AST.Child(sel, 0), fn);
  632. IF t = SymTab.InvalidType THEN
  633. ELSIF NOT SymTab.FieldExists(t, fn) THEN t := SymTab.InvalidType
  634. ELSE
  635. fo := SymTab.FieldOffset(t, fn);
  636. t := SymTab.FieldType(t, fn);
  637. QbeGen.FieldAddr(q, fo, qe);
  638. QbeGen.CopyOp(qe, q);
  639. sfx := TRUE
  640. END
  641. ELSIF op = AST.SelIndex THEN
  642. LowerExpr(AST.Child(sel, 0), it, iq);
  643. IF t = SymTab.InvalidType THEN
  644. ELSE
  645. QbeGen.WidenIndex(iq, ql);
  646. isOpen := SymTab.IsOpenArray(t);
  647. IF isOpen THEN
  648. QbeGen.CopyOp("0", qlo);
  649. IF SymTab.IsCharArray(t) OR SymTab.IsUCharArray(t) THEN
  650. QbeGen.OpenHiChar(q, qhi)
  651. ELSE QbeGen.OpenHi(q, qhi)
  652. END
  653. ELSE
  654. lo := SymTab.ArrayLo(t); hi := SymTab.ArrayHi(t);
  655. IF SymTab.IsCharArray(t) OR SymTab.IsUCharArray(t) THEN
  656. hi := hi + 1
  657. END;
  658. QbeGen.IntStr(lo, qlo); QbeGen.IntStr(hi, qhi)
  659. END;
  660. QbeGen.CheckRange(ql, qlo, qhi);
  661. eT := SymTab.ArrayElem(t);
  662. QbeGen.ElemAddr(q, ql, qlo, t, qe);
  663. IF SymTab.ClassOf(eT) = SymTab.ClArray THEN
  664. QbeGen.ElemLoad(qe, eT, q)
  665. ELSE QbeGen.CopyOp(qe, q)
  666. END;
  667. t := eT; sfx := TRUE
  668. END
  669. ELSIF op = AST.SelDeref THEN
  670. IF t = SymTab.InvalidType THEN
  671. ELSIF SymTab.ClassOf(t) # SymTab.ClPtr THEN t := SymTab.InvalidType
  672. ELSE
  673. IF sfx THEN QbeGen.ElemLoad(q, t, qe); QbeGen.CopyOp(qe, q) END;
  674. t := SymTab.PtrBase(t); sfx := TRUE
  675. END
  676. END;
  677. INC(i)
  678. END
  679. END LowerDesign;
  680. PROCEDURE LowerCall (n: AST.Node; VAR t: SymTab.TypeIndex;
  681. VAR q: QbeGen.QVal; want: BOOLEAN);
  682. VAR nm: SymTab.Name; i: CARDINAL; at, ft, res: SymTab.TypeIndex;
  683. qa, qt, qe: QbeGen.QVal; mg: QbeGen.QVal; cls: CHAR; conv, isV: BOOLEAN;
  684. uid, depth, np: CARDINAL; ext: BOOLEAN; pn: SymTab.Name;
  685. BEGIN
  686. CalleeName(n, nm);
  687. IF NOT ProcInfo(nm, uid, res, depth, ext, np) THEN END;
  688. QbeGen.Mangled(nm, uid, mg);
  689. QbeGen.CallBegin(mg, res, depth, ext);
  690. i := 1;
  691. WHILE i < AST.NChild(n) DO
  692. LowerExpr(AST.Child(n, i), at, qe);
  693. IF NOT ParamInfo(nm, i - 1, ft, isV, pn) THEN END;
  694. IF isV THEN
  695. IF QbeGen.AddrOfVal(qe, qa) THEN
  696. IF NOT QbeGen.CallArg(qa, "l") THEN END
  697. END
  698. ELSE
  699. conv := (SymTab.ClassOf(ft) = SymTab.ClReal)
  700. AND SymTab.IsIntFamily(at);
  701. IF conv THEN
  702. QbeGen.ConvIR(qe, qt);
  703. IF NOT QbeGen.CallArg(qt, "d") THEN END
  704. ELSE
  705. IF NOT QbeGen.CallArg(qe, QbeGen.ArgClass(ft)) THEN END
  706. END
  707. END;
  708. INC(i)
  709. END;
  710. IF want THEN
  711. t := res; QbeGen.CallEnd(TRUE, q)
  712. ELSE
  713. t := SymTab.InvalidType; QbeGen.CopyOp("0", q); QbeGen.CallEnd(FALSE, q)
  714. END
  715. END LowerCall;
  716. PROCEDURE IsBuiltin (nm: ARRAY OF CHAR): BOOLEAN;
  717. BEGIN
  718. RETURN SymTab.Equal(nm, "ABS") OR SymTab.Equal(nm, "CAP")
  719. OR SymTab.Equal(nm, "CHR") OR SymTab.Equal(nm, "ORD")
  720. OR SymTab.Equal(nm, "SIZE") OR SymTab.Equal(nm, "TSIZE")
  721. OR SymTab.Equal(nm, "MIN") OR SymTab.Equal(nm, "MAX")
  722. OR SymTab.Equal(nm, "SHIFT") OR SymTab.Equal(nm, "ROTATE")
  723. OR SymTab.Equal(nm, "ADR")
  724. OR SymTab.Equal(nm, "INC") OR SymTab.Equal(nm, "DEC")
  725. OR SymTab.Equal(nm, "INCL") OR SymTab.Equal(nm, "EXCL")
  726. OR SymTab.Equal(nm, "NEW") OR SymTab.Equal(nm, "DISPOSE")
  727. END IsBuiltin;
  728. PROCEDURE LowerBuiltinExpr (n: AST.Node; nm: SymTab.Name;
  729. VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal);
  730. (* Value builtins (Fact). *)
  731. VAR et, et2, dt: SymTab.TypeIndex; qa, qt, q2, qd: QbeGen.QVal;
  732. k, lo, hi: INTEGER; qn: SymTab.Name; sfx: BOOLEAN; isMax: BOOLEAN;
  733. BEGIN
  734. IF SymTab.Equal(nm, "ABS") THEN
  735. LowerExpr(AST.Child(n, 1), et, q);
  736. QbeGen.AbsQ(q, qa, SymTab.ClassOf(et) = SymTab.ClReal);
  737. QbeGen.CopyOp(qa, q); t := et
  738. ELSIF SymTab.Equal(nm, "CAP") THEN
  739. LowerExpr(AST.Child(n, 1), et, q);
  740. QbeGen.CapQ(q, qa); QbeGen.CopyOp(qa, q); t := SymTab.CharType()
  741. ELSIF SymTab.Equal(nm, "CHR") THEN
  742. LowerExpr(AST.Child(n, 1), et, q); t := SymTab.CharType()
  743. ELSIF SymTab.Equal(nm, "ORD") THEN
  744. LowerExpr(AST.Child(n, 1), et, q); t := SymTab.IntType()
  745. ELSIF SymTab.Equal(nm, "SIZE") THEN
  746. LowerDesign(AST.Child(n, 1), dt, k, qd, qn, sfx);
  747. QbeGen.IntStr(VAL(INTEGER, SymTab.ObjectSize(dt)), q);
  748. t := SymTab.IntType()
  749. ELSIF SymTab.Equal(nm, "MIN") OR SymTab.Equal(nm, "MAX") THEN
  750. isMax := SymTab.Equal(nm, "MAX");
  751. LowerDesign(AST.Child(n, 1), dt, k, qd, qn, sfx);
  752. IF SymTab.ClassOf(dt) = SymTab.ClReal THEN
  753. IF isMax THEN QbeGen.NormReal("3.402823e38", q)
  754. ELSE QbeGen.NormReal("-3.402823e38", q) END;
  755. t := SymTab.RealType()
  756. ELSIF SymTab.ClassOf(dt) = SymTab.ClLong THEN
  757. IF isMax THEN QbeGen.CopyOp("9223372036854775807", q)
  758. ELSE QbeGen.CopyOp("-9223372036854775808", q) END;
  759. t := SymTab.LongType()
  760. ELSIF SymTab.TypeBounds(dt, lo, hi) THEN
  761. IF isMax THEN QbeGen.IntStr(hi, q) ELSE QbeGen.IntStr(lo, q) END;
  762. t := SymTab.IntType()
  763. ELSE t := SymTab.InvalidType; QbeGen.CopyOp("0", q)
  764. END
  765. ELSIF SymTab.Equal(nm, "SHIFT") OR SymTab.Equal(nm, "ROTATE") THEN
  766. LowerExpr(AST.Child(n, 1), et, q);
  767. LowerExpr(AST.Child(n, 2), et2, q2);
  768. QbeGen.SetShift(q, q2, SymTab.SetWords(et), SymTab.SetCount(et),
  769. SymTab.Equal(nm, "ROTATE"), qt);
  770. t := et; QbeGen.CopyOp(qt, q)
  771. ELSIF SymTab.Equal(nm, "ADR") THEN
  772. LowerDesign(AST.Child(n, 1), dt, k, qd, qn, sfx);
  773. IF sfx THEN QbeGen.CopyOp(qd, q)
  774. ELSIF (k = SymTab.KindVar) OR (k = SymTab.KindParam) THEN
  775. QbeGen.AddrOf(qn, q)
  776. ELSE QbeGen.CopyOp("0", q)
  777. END;
  778. t := SymTab.AddrType()
  779. ELSE t := SymTab.InvalidType; QbeGen.CopyOp("0", q)
  780. END
  781. END LowerBuiltinExpr;
  782. PROCEDURE LowerBuiltinStmt (n: AST.Node; nm: SymTab.Name);
  783. (* Statement builtins (AssOrCall): INC/DEC, INCL/EXCL, NEW/DISPOSE. *)
  784. VAR dt, at, et2, bt: SymTab.TypeIndex; dk: INTEGER;
  785. qd, qv, qe, qn2, qstep, qm: QbeGen.QVal;
  786. qn: SymTab.Name; sfx, isInc: BOOLEAN;
  787. BEGIN
  788. IF SymTab.Equal(nm, "INC") OR SymTab.Equal(nm, "DEC") THEN
  789. isInc := SymTab.Equal(nm, "INC");
  790. QbeGen.CopyOp("1", qstep);
  791. LowerDesign(AST.Child(n, 1), dt, dk, qd, qn, sfx);
  792. IF AST.NChild(n) > 2 THEN LowerExpr(AST.Child(n, 2), et2, qstep) END;
  793. IF dt = SymTab.InvalidType THEN
  794. ELSE
  795. IF sfx OR (dk = SymTab.KindField) THEN QbeGen.ElemLoad(qd, dt, qv)
  796. ELSE QbeGen.LoadVar(qn, FALSE, qv)
  797. END;
  798. QbeGen.NewTemp(qn2);
  799. IF isInc THEN QbeGen.Op3("add", qn2, qv, qstep, FALSE)
  800. ELSE QbeGen.Op3("sub", qn2, qv, qstep, FALSE)
  801. END;
  802. IF sfx OR (dk = SymTab.KindField) THEN QbeGen.ElemStore(qd, qn2, dt)
  803. ELSE QbeGen.StoreVar(qn, qn2, FALSE)
  804. END
  805. END
  806. ELSIF SymTab.Equal(nm, "INCL") OR SymTab.Equal(nm, "EXCL") THEN
  807. isInc := SymTab.Equal(nm, "INCL");
  808. LowerDesign(AST.Child(n, 1), at, dk, qd, qn, sfx);
  809. LowerExpr(AST.Child(n, 2), et2, qe);
  810. IF at = SymTab.InvalidType THEN
  811. ELSIF SymTab.ClassOf(at) # SymTab.ClSet THEN
  812. ELSE
  813. IF isInc THEN QbeGen.SetBit(qd, qe, SymTab.SetBaseLo(at), SymTab.SetCount(at))
  814. ELSE QbeGen.SetClearBit(qd, qe, SymTab.SetBaseLo(at), SymTab.SetCount(at))
  815. END
  816. END
  817. ELSIF SymTab.Equal(nm, "NEW") THEN
  818. LowerDesign(AST.Child(n, 1), dt, dk, qd, qn, sfx);
  819. IF dt = SymTab.InvalidType THEN
  820. ELSIF SymTab.ClassOf(dt) # SymTab.ClPtr THEN
  821. ELSE
  822. bt := SymTab.PtrBase(dt);
  823. IF bt # SymTab.InvalidType THEN
  824. QbeGen.NewHeap(bt, qm); QbeGen.InitHeap(qm, bt);
  825. IF sfx OR (dk = SymTab.KindField) THEN QbeGen.ElemStore(qd, qm, dt)
  826. ELSE QbeGen.StorePtr(qn, qm)
  827. END
  828. END
  829. END
  830. ELSIF SymTab.Equal(nm, "DISPOSE") THEN
  831. LowerDesign(AST.Child(n, 1), dt, dk, qd, qn, sfx);
  832. IF dt = SymTab.InvalidType THEN
  833. ELSIF SymTab.ClassOf(dt) # SymTab.ClPtr THEN
  834. ELSE
  835. IF sfx OR (dk = SymTab.KindField) THEN QbeGen.ElemLoad(qd, dt, qv)
  836. ELSE QbeGen.LoadPtr(qn, qv)
  837. END;
  838. QbeGen.FreeHeap(qv);
  839. IF sfx OR (dk = SymTab.KindField) THEN QbeGen.ElemStore(qd, "0", dt)
  840. ELSE QbeGen.StorePtr(qn, "0")
  841. END
  842. END
  843. END
  844. END LowerBuiltinStmt;
  845. PROCEDURE LowerCase (n: AST.Node);
  846. (* CASE as a compare-chain (mirrors CaseStat/CaseAlt/CaseLabel). *)
  847. VAR i, j: CARDINAL; arm, lab: AST.Node; tsel, t2, t3: SymTab.TypeIndex;
  848. qsel, q2, q3, qc, qd, qe, lEnd, lBody, lAfter, lNext: QbeGen.QVal;
  849. BEGIN
  850. LowerExpr(AST.Child(n, 0), tsel, qsel);
  851. QbeGen.NewLabel(lEnd);
  852. i := 1;
  853. WHILE i < AST.NChild(n) DO
  854. arm := AST.Child(n, i);
  855. IF AST.Op(arm) = 1 THEN
  856. (* ELSE arm: emitted after the alternatives *)
  857. ELSE
  858. QbeGen.NewLabel(lBody); QbeGen.NewLabel(lAfter);
  859. j := 0;
  860. WHILE j + 1 < AST.NChild(arm) DO
  861. lab := AST.Child(arm, j);
  862. IF AST.Kind(lab) = AST.NkSubrange THEN
  863. LowerExpr(AST.Child(lab, 0), t2, q2);
  864. QbeGen.NewLabel(lNext);
  865. QbeGen.Cmp(SymTab.OpEq, qsel, q2, qc, FALSE);
  866. QbeGen.Jnz(qc, lBody, lNext);
  867. QbeGen.EmitLabel(lNext);
  868. LowerExpr(AST.Child(lab, 1), t3, q3);
  869. QbeGen.Cmp(SymTab.OpGe, qsel, q2, qc, FALSE);
  870. QbeGen.Cmp(SymTab.OpLe, qsel, q3, qd, FALSE);
  871. QbeGen.NewTemp(qe);
  872. QbeGen.Op3("and", qe, qc, qd, FALSE);
  873. QbeGen.NewLabel(lNext);
  874. QbeGen.Jnz(qe, lBody, lNext);
  875. QbeGen.EmitLabel(lNext)
  876. ELSE
  877. LowerExpr(lab, t2, q2);
  878. QbeGen.NewLabel(lNext);
  879. QbeGen.Cmp(SymTab.OpEq, qsel, q2, qc, FALSE);
  880. QbeGen.Jnz(qc, lBody, lNext);
  881. QbeGen.EmitLabel(lNext)
  882. END;
  883. INC(j)
  884. END;
  885. QbeGen.Jmp(lAfter);
  886. QbeGen.EmitLabel(lBody);
  887. LowerStmt(AST.Child(arm, AST.NChild(arm) - 1));
  888. QbeGen.Jmp(lEnd);
  889. QbeGen.EmitLabel(lAfter)
  890. END;
  891. INC(i)
  892. END;
  893. i := 1;
  894. WHILE i < AST.NChild(n) DO
  895. arm := AST.Child(n, i);
  896. IF AST.Op(arm) = 1 THEN LowerStmt(AST.Child(arm, 0)) END;
  897. INC(i)
  898. END;
  899. QbeGen.EmitLabel(lEnd)
  900. END LowerCase;
  901. PROCEDURE LowerWith (n: AST.Node);
  902. (* WITH: push each record's base address, lower the body, pop. *)
  903. VAR i: CARDINAL; dt: SymTab.TypeIndex; dk: INTEGER; qd: QbeGen.QVal;
  904. qn: SymTab.Name; sfx: BOOLEAN;
  905. BEGIN
  906. i := 0;
  907. WHILE i + 1 < AST.NChild(n) DO
  908. LowerDesign(AST.Child(n, i), dt, dk, qd, qn, sfx);
  909. QbeGen.PushWith(qd);
  910. IF withTop <= HIGH(withRec) THEN
  911. withRec[withTop] := dt; INC(withTop)
  912. END;
  913. INC(i)
  914. END;
  915. LowerStmt(AST.Child(n, AST.NChild(n) - 1));
  916. WHILE withTop > 0 DO DEC(withTop); QbeGen.PopWith END
  917. END LowerWith;
  918. PROCEDURE LowerExprFull (n: AST.Node; VAR t: SymTab.TypeIndex;
  919. VAR q: QbeGen.QVal; VAR k: INTEGER;
  920. VAR qn: SymTab.Name; VAR sfx: BOOLEAN;
  921. asAddr: BOOLEAN);
  922. VAR t2: SymTab.TypeIndex; q2, qt, qf, qs, qr: QbeGen.QVal;
  923. lNext, lFalse, lTrue, lDone: QbeGen.QVal;
  924. kind, op, rop: INTEGER;
  925. folded, isR, isCh: BOOLEAN;
  926. i: CARDINAL; el: AST.Node;
  927. lw, rw, mw: CARDINAL; idx: INTEGER; fok, isL: BOOLEAN;
  928. lt, rt: SymTab.TypeIndex; qw: QbeGen.QVal;
  929. BEGIN
  930. IF AST.Kind(n) = AST.NkDesignator THEN
  931. LowerDesign(n, t, k, q, qn, sfx);
  932. IF NOT asAddr THEN FinalLoad(t, sfx, q) END;
  933. RETURN
  934. END;
  935. k := -1; qn[0] := CHR(0); sfx := FALSE;
  936. IF AST.Kind(n) = AST.NkIntLit THEN
  937. Name(n, qn); QbeGen.NormInt(qn, q); t := SymTab.IntType()
  938. ELSIF AST.Kind(n) = AST.NkCharLit THEN
  939. Name(n, qn); QbeGen.NormLit(qn, q, isCh); t := SymTab.CharType()
  940. ELSIF AST.Kind(n) = AST.NkRealLit THEN
  941. Name(n, qn); QbeGen.NormReal(qn, q); t := SymTab.RealType()
  942. ELSIF AST.Kind(n) = AST.NkStrLit THEN
  943. Name(n, qn);
  944. IF SymTab.StrLen(qn) = 3 THEN
  945. t := SymTab.CharType(); QbeGen.IntStr(QbeGen.CharVal(qn), q)
  946. ELSE
  947. t := SymTab.NewStr(); QbeGen.DeclStr(qn, q); QbeGen.NoteAddr(q, q)
  948. END
  949. ELSIF AST.Kind(n) = AST.NkSetLit THEN
  950. t := SymTab.NewSet(SymTab.NewSubR(0, 255));
  951. QbeGen.NewSetTemp(8, q); QbeGen.SetZero(q, 8);
  952. i := 0;
  953. WHILE i < AST.NChild(n) DO
  954. el := AST.Child(n, i);
  955. IF AST.Kind(el) = AST.NkSubrange THEN
  956. LowerExpr(AST.Child(el, 0), t2, q2);
  957. LowerExpr(AST.Child(el, 1), t2, qt);
  958. QbeGen.SetRange(q, q2, qt, SymTab.SetBaseLo(t), SymTab.SetCount(t))
  959. ELSE
  960. LowerExpr(el, t2, q2);
  961. QbeGen.SetBit(q, q2, SymTab.SetBaseLo(t), SymTab.SetCount(t))
  962. END;
  963. INC(i)
  964. END
  965. ELSIF AST.Kind(n) = AST.NkDesignator THEN
  966. LowerDesign(n, t, k, q, qn, sfx)
  967. ELSIF AST.Kind(n) = AST.NkCall THEN
  968. CalleeName(n, qn);
  969. IF IsBuiltin(qn) THEN LowerBuiltinExpr(n, qn, t, q)
  970. ELSE LowerCall(n, t, q, TRUE)
  971. END
  972. ELSIF AST.Kind(n) = AST.NkUnary THEN
  973. LowerExpr(AST.Child(n, 0), t, q);
  974. IF AST.Op(n) = AST.OpSub THEN
  975. IF QbeGen.IsImm(q) THEN QbeGen.NegFold(q, q)
  976. ELSE QbeGen.NewTemp(qt); QbeGen.NegQ(q, qt, FALSE); QbeGen.CopyOp(qt, q)
  977. END
  978. ELSE
  979. QbeGen.NotQ(q, qt); QbeGen.CopyOp(qt, q); t := SymTab.BoolType()
  980. END
  981. ELSIF AST.Kind(n) = AST.NkBinExpr THEN
  982. op := AST.Op(n);
  983. IF IsRel(op) THEN
  984. LowerExpr(AST.Child(n, 0), t, q);
  985. LowerExpr(AST.Child(n, 1), t2, q2);
  986. rop := SymTab.OpEq; folded := RelSym(op, rop);
  987. IF op = AST.OpIn THEN
  988. QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2), SymTab.SetCount(t2), qt);
  989. t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  990. ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
  991. OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
  992. QbeGen.CmpL(rop, q, q2, qt);
  993. t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  994. ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
  995. OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  996. QbeGen.CmpSet(rop, q, q2, SymTab.SetWords(t), SymTab.SetWords(t2), qt);
  997. t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  998. ELSIF SymTab.StrCompat(t, t2) THEN
  999. QbeGen.StrEq(rop, q, q2, qt);
  1000. t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  1001. ELSIF SymTab.IsLongFamily(t) OR SymTab.IsLongFamily(t2) THEN
  1002. IF SymTab.IsIntFamily(t) THEN QbeGen.WidenLong(q, qf); QbeGen.CopyOp(qf, q) END;
  1003. IF SymTab.IsIntFamily(t2) THEN QbeGen.WidenLong(q2, qf); QbeGen.CopyOp(qf, q2) END;
  1004. QbeGen.CmpLong(rop, q, q2, qt);
  1005. t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  1006. ELSE
  1007. isR := (t # SymTab.InvalidType) AND (SymTab.ClassOf(t) = SymTab.ClReal);
  1008. t := SymTab.BoolType();
  1009. QbeGen.Cmp(rop, q, q2, qt, isR);
  1010. QbeGen.CopyOp(qt, q)
  1011. END
  1012. ELSIF op = AST.OpAnd THEN
  1013. LowerExpr(AST.Child(n, 0), t, q);
  1014. QbeGen.DelayBegin;
  1015. LowerExpr(AST.Child(n, 1), t2, q2);
  1016. QbeGen.DelayEnd;
  1017. QbeGen.Slot4(qs);
  1018. QbeGen.NewLabel(lNext); QbeGen.NewLabel(lFalse); QbeGen.NewLabel(lDone);
  1019. QbeGen.Jnz(q, lNext, lFalse);
  1020. QbeGen.EmitLabel(lNext);
  1021. QbeGen.DelayFlush;
  1022. QbeGen.StoreW(qs, q2);
  1023. QbeGen.Jmp(lDone);
  1024. QbeGen.EmitLabel(lFalse);
  1025. QbeGen.StoreW(qs, "0");
  1026. QbeGen.Jmp(lDone);
  1027. QbeGen.EmitLabel(lDone);
  1028. QbeGen.LoadW(qs, qr);
  1029. QbeGen.CopyOp(qr, q);
  1030. t := SymTab.BoolType()
  1031. ELSIF op = AST.OpOr THEN
  1032. LowerExpr(AST.Child(n, 0), t, q);
  1033. QbeGen.DelayBegin;
  1034. LowerExpr(AST.Child(n, 1), t2, q2);
  1035. QbeGen.DelayEnd;
  1036. QbeGen.Slot4(qs);
  1037. QbeGen.NewLabel(lTrue); QbeGen.NewLabel(lNext); QbeGen.NewLabel(lDone);
  1038. QbeGen.Jnz(q, lTrue, lNext);
  1039. QbeGen.EmitLabel(lTrue);
  1040. QbeGen.StoreW(qs, "1");
  1041. QbeGen.Jmp(lDone);
  1042. QbeGen.EmitLabel(lNext);
  1043. QbeGen.DelayFlush;
  1044. QbeGen.StoreW(qs, q2);
  1045. QbeGen.Jmp(lDone);
  1046. QbeGen.EmitLabel(lDone);
  1047. QbeGen.LoadW(qs, qr);
  1048. QbeGen.CopyOp(qr, q);
  1049. t := SymTab.BoolType()
  1050. ELSE
  1051. LowerExpr(AST.Child(n, 0), t, q);
  1052. LowerExpr(AST.Child(n, 1), t2, q2);
  1053. IF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
  1054. AND (SymTab.ClassOf(t) = SymTab.ClSet)
  1055. AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  1056. (* set union/diff (Add/Sub) or intersection/symdiff (Mul/Div) *)
  1057. lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
  1058. mw := lw; IF rw > mw THEN mw := rw END;
  1059. IF op = AST.OpAdd THEN idx := 0
  1060. ELSIF op = AST.OpSub THEN idx := 2
  1061. ELSIF op = AST.OpMul THEN idx := 1
  1062. ELSE idx := 3
  1063. END;
  1064. QbeGen.SetBinOp(idx, q, q2, lw, rw, qt);
  1065. t := SymTab.NewSet(SymTab.NewSubR(0, VAL(INTEGER, mw) * 32 - 1));
  1066. QbeGen.CopyOp(qt, q)
  1067. ELSIF (op = AST.OpAdd)
  1068. AND (SymTab.StrCompat(t, t2)
  1069. OR (SymTab.IsStrType(t) AND (SymTab.ClassOf(t2) = SymTab.ClChar))
  1070. OR ((SymTab.ClassOf(t) = SymTab.ClChar) AND SymTab.IsStrType(t2))) THEN
  1071. QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2), qt, fok);
  1072. IF NOT fok THEN
  1073. IF SymTab.StrCompat(t, t2) THEN QbeGen.StrCat(q, q2, qt)
  1074. ELSIF SymTab.IsStrType(t) THEN
  1075. QbeGen.DeclCharStr(q2, qs); QbeGen.StrCat(q, qs, qt)
  1076. ELSE
  1077. QbeGen.DeclCharStr(q, qs); QbeGen.StrCat(qs, q2, qt)
  1078. END
  1079. END;
  1080. t := SymTab.NewStr(); QbeGen.CopyOp(qt, q)
  1081. ELSE
  1082. lt := t; rt := t2;
  1083. IF (SymTab.ClassOf(lt) = SymTab.ClReal)
  1084. OR (SymTab.ClassOf(rt) = SymTab.ClReal) THEN
  1085. t := SymTab.RealType()
  1086. ELSIF SymTab.IsLongFamily(lt) OR SymTab.IsLongFamily(rt) THEN
  1087. t := SymTab.LongType()
  1088. ELSE t := SymTab.IntType()
  1089. END;
  1090. isL := SymTab.IsLongFamily(t);
  1091. isR := SymTab.ClassOf(t) = SymTab.ClReal;
  1092. kind := 0;
  1093. IF op = AST.OpSub THEN kind := 1
  1094. ELSIF op = AST.OpMul THEN kind := 2
  1095. ELSIF op = AST.OpDiv THEN kind := 3
  1096. ELSIF op = AST.OpMod THEN kind := 4
  1097. END;
  1098. folded := FALSE;
  1099. IF (NOT isL) AND (NOT isR) AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
  1100. folded := QbeGen.Fold2(kind, q, q2, qf)
  1101. END;
  1102. IF folded THEN QbeGen.CopyOp(qf, q)
  1103. ELSE
  1104. IF isL THEN
  1105. IF SymTab.IsIntFamily(lt) THEN
  1106. QbeGen.WidenLong(q, qw); QbeGen.CopyOp(qw, q)
  1107. END;
  1108. IF SymTab.IsIntFamily(rt) THEN
  1109. QbeGen.WidenLong(q2, qw); QbeGen.CopyOp(qw, q2)
  1110. END;
  1111. QbeGen.NewTemp(qt);
  1112. IF op = AST.OpAdd THEN QbeGen.Op3L("add", qt, q, q2)
  1113. ELSIF op = AST.OpSub THEN QbeGen.Op3L("sub", qt, q, q2)
  1114. ELSIF op = AST.OpMul THEN QbeGen.Op3L("mul", qt, q, q2)
  1115. ELSE QbeGen.Op3L("div", qt, q, q2)
  1116. END
  1117. ELSE
  1118. QbeGen.NewTemp(qt);
  1119. IF op = AST.OpAdd THEN QbeGen.Op3("add", qt, q, q2, isR)
  1120. ELSIF op = AST.OpSub THEN QbeGen.Op3("sub", qt, q, q2, isR)
  1121. ELSIF op = AST.OpMul THEN QbeGen.Op3("mul", qt, q, q2, isR)
  1122. ELSIF op = AST.OpDiv THEN QbeGen.Op3("div", qt, q, q2, isR)
  1123. ELSE QbeGen.Op3("rem", qt, q, q2, isR)
  1124. END
  1125. END;
  1126. QbeGen.CopyOp(qt, q)
  1127. END
  1128. END
  1129. END
  1130. END
  1131. END LowerExprFull;
  1132. PROCEDURE LowerExpr (n: AST.Node; VAR t: SymTab.TypeIndex;
  1133. VAR q: QbeGen.QVal);
  1134. VAR k: INTEGER; qn: SymTab.Name; sfx: BOOLEAN;
  1135. BEGIN
  1136. LowerExprFull(n, t, q, k, qn, sfx, FALSE)
  1137. END LowerExpr;
  1138. PROCEDURE LowerStmt (seq: AST.Node);
  1139. VAR i: CARDINAL; c, els, by: AST.Node; k: INTEGER;
  1140. t, t2, dt, et: SymTab.TypeIndex;
  1141. q, q2, qt, qf, qd, qe: QbeGen.QVal;
  1142. qlo, qhi, qk, qb, ql: QbeGen.QVal;
  1143. lTop, lBody, lEnd, lThen, lElse, lNext, lFalse, lDone, lx: QbeGen.QVal;
  1144. qn, lv: SymTab.Name;
  1145. kind, op, rop, cls: INTEGER;
  1146. sfx, folded, isR, conv, wconv, hasElse: BOOLEAN;
  1147. BEGIN
  1148. IF seq = AST.NoNode THEN RETURN END;
  1149. k := AST.Kind(seq);
  1150. IF k = AST.NkBlock THEN
  1151. i := 0;
  1152. WHILE i < AST.NChild(seq) DO
  1153. LowerStmt(AST.Child(seq, i)); INC(i)
  1154. END
  1155. ELSIF k = AST.NkAssign THEN
  1156. LowerDesign(AST.Child(seq, 0), dt, cls, qd, qn, sfx);
  1157. LowerExpr(AST.Child(seq, 1), et, qe);
  1158. isR := (dt # SymTab.InvalidType) AND (SymTab.ClassOf(dt) = SymTab.ClReal);
  1159. conv := isR AND SymTab.IsIntFamily(et);
  1160. wconv := (dt # SymTab.InvalidType) AND SymTab.IsLongFamily(dt)
  1161. AND SymTab.IsIntFamily(et);
  1162. IF sfx OR (cls = SymTab.KindField) THEN
  1163. IF SymTab.ClassOf(dt) = SymTab.ClArray THEN
  1164. IF (et # SymTab.InvalidType) AND (SymTab.ClassOf(et) = SymTab.ClUStr)
  1165. AND SymTab.IsUCharArray(dt) THEN QbeGen.UAssign(qd, qe)
  1166. ELSIF SymTab.StrCompat(dt, et) THEN QbeGen.StrAssign(qd, qe)
  1167. ELSE QbeGen.CopyArray(qd, qe, dt)
  1168. END
  1169. ELSIF SymTab.ClassOf(dt) = SymTab.ClSet THEN
  1170. QbeGen.CopySet(qd, qe, SymTab.SetWords(dt), SymTab.SetWords(et))
  1171. ELSIF SymTab.ClassOf(dt) = SymTab.ClRecord THEN
  1172. QbeGen.CopyRecord(qd, qe, dt)
  1173. ELSIF SymTab.IsLongFamily(dt) THEN
  1174. IF wconv THEN QbeGen.WidenLong(qe, ql); QbeGen.ElemStore(qd, ql, dt)
  1175. ELSE QbeGen.ElemStore(qd, qe, dt)
  1176. END
  1177. ELSIF conv THEN QbeGen.ConvIR(qe, qt); QbeGen.ElemStore(qd, qt, dt)
  1178. ELSE QbeGen.ElemStore(qd, qe, dt)
  1179. END
  1180. ELSE
  1181. IF SymTab.ClassOf(dt) = SymTab.ClArray THEN
  1182. IF (et # SymTab.InvalidType) AND (SymTab.ClassOf(et) = SymTab.ClUStr)
  1183. AND SymTab.IsUCharArray(dt) THEN QbeGen.UAssign(qd, qe)
  1184. ELSIF SymTab.StrCompat(dt, et) THEN QbeGen.StrAssign(qd, qe)
  1185. ELSE QbeGen.CopyArray(qd, qe, dt)
  1186. END
  1187. ELSIF SymTab.ClassOf(dt) = SymTab.ClSet THEN
  1188. QbeGen.CopySet(qd, qe, SymTab.SetWords(dt), SymTab.SetWords(et))
  1189. ELSIF SymTab.ClassOf(dt) = SymTab.ClRecord THEN
  1190. QbeGen.CopyRecord(qd, qe, dt)
  1191. ELSIF (SymTab.ClassOf(dt) = SymTab.ClPtr)
  1192. OR (SymTab.ClassOf(dt) = SymTab.ClProc) THEN
  1193. QbeGen.StorePtr(qn, qe)
  1194. ELSIF SymTab.IsLongFamily(dt) THEN
  1195. IF wconv THEN QbeGen.WidenLong(qe, ql); QbeGen.StoreLong(qn, ql)
  1196. ELSE QbeGen.StoreLong(qn, qe)
  1197. END
  1198. ELSIF conv THEN QbeGen.ConvIR(qe, qt); QbeGen.StoreVar(qn, qt, TRUE)
  1199. ELSE QbeGen.StoreVar(qn, qe, isR)
  1200. END
  1201. END
  1202. ELSIF k = AST.NkIf THEN
  1203. LowerExpr(AST.Child(seq, 0), t, q);
  1204. QbeGen.NewLabel(lThen); QbeGen.NewLabel(lElse); QbeGen.NewLabel(lEnd);
  1205. QbeGen.Jnz(q, lThen, lElse); QbeGen.EmitLabel(lThen);
  1206. LowerStmt(AST.Child(seq, 1));
  1207. QbeGen.Jmp(lEnd);
  1208. els := AST.Child(seq, 2); hasElse := FALSE;
  1209. WHILE (els # AST.NoNode) AND (AST.Kind(els) = AST.NkIf) DO
  1210. QbeGen.EmitLabel(lElse); QbeGen.NewLabel(lElse);
  1211. LowerExpr(AST.Child(els, 0), t, q);
  1212. QbeGen.NewLabel(lThen); QbeGen.Jnz(q, lThen, lElse);
  1213. QbeGen.EmitLabel(lThen);
  1214. LowerStmt(AST.Child(els, 1));
  1215. QbeGen.Jmp(lEnd);
  1216. els := AST.Child(els, 2)
  1217. END;
  1218. IF els # AST.NoNode THEN
  1219. QbeGen.EmitLabel(lElse); hasElse := TRUE; LowerStmt(els)
  1220. END;
  1221. IF hasElse THEN QbeGen.EmitLabel(lEnd)
  1222. ELSE QbeGen.EmitLabel(lElse); QbeGen.EmitLabel(lEnd)
  1223. END
  1224. ELSIF k = AST.NkWhile THEN
  1225. QbeGen.NewLabel(lTop); QbeGen.NewLabel(lBody); QbeGen.NewLabel(lEnd);
  1226. QbeGen.EmitLabel(lTop);
  1227. LowerExpr(AST.Child(seq, 0), t, q);
  1228. QbeGen.Jnz(q, lBody, lEnd); QbeGen.EmitLabel(lBody);
  1229. LowerStmt(AST.Child(seq, 1));
  1230. QbeGen.Jmp(lTop); QbeGen.EmitLabel(lEnd)
  1231. ELSIF k = AST.NkRepeat THEN
  1232. QbeGen.NewLabel(lTop); QbeGen.NewLabel(lEnd); QbeGen.EmitLabel(lTop);
  1233. LowerStmt(AST.Child(seq, 0));
  1234. LowerExpr(AST.Child(seq, 1), t, q);
  1235. QbeGen.Jnz(q, lEnd, lTop); QbeGen.EmitLabel(lEnd)
  1236. ELSIF k = AST.NkLoop THEN
  1237. QbeGen.NewLabel(lTop); QbeGen.NewLabel(lEnd);
  1238. QbeGen.PushLoop(lEnd); QbeGen.EmitLabel(lTop);
  1239. LowerStmt(AST.Child(seq, 0));
  1240. QbeGen.Jmp(lTop); QbeGen.PopLoop; QbeGen.EmitLabel(lEnd)
  1241. ELSIF k = AST.NkExit THEN
  1242. IF QbeGen.TopLoop(lx) THEN QbeGen.Jmp(lx) END
  1243. ELSIF k = AST.NkFor THEN
  1244. Name(AST.Child(seq, 0), lv);
  1245. LowerExpr(AST.Child(seq, 1), t, qlo);
  1246. LowerExpr(AST.Child(seq, 2), t2, qhi);
  1247. QbeGen.StoreVar(lv, qlo, FALSE);
  1248. QbeGen.NewLabel(lTop); QbeGen.NewLabel(lBody); QbeGen.NewLabel(lEnd);
  1249. QbeGen.EmitLabel(lTop);
  1250. QbeGen.LoadVar(lv, FALSE, qt);
  1251. QbeGen.NewTemp(qk);
  1252. QbeGen.Op3("cslew", qk, qt, qhi, FALSE);
  1253. QbeGen.Jnz(qk, lBody, lEnd);
  1254. QbeGen.EmitLabel(lBody);
  1255. LowerStmt(AST.Child(seq, 4));
  1256. QbeGen.LoadVar(lv, FALSE, qt);
  1257. QbeGen.IntStr(1, qb);
  1258. QbeGen.NewTemp(qk);
  1259. QbeGen.Op3("add", qk, qt, qb, FALSE);
  1260. QbeGen.StoreVar(lv, qk, FALSE);
  1261. QbeGen.Jmp(lTop); QbeGen.EmitLabel(lEnd)
  1262. ELSIF k = AST.NkHalt THEN
  1263. IF AST.Child(seq, 0) # AST.NoNode THEN
  1264. LowerExpr(AST.Child(seq, 0), t, q) END;
  1265. QbeGen.HaltQ
  1266. ELSIF k = AST.NkReturn THEN
  1267. IF AST.Child(seq, 0) = AST.NoNode THEN
  1268. QbeGen.EmitRet(q, FALSE)
  1269. ELSE
  1270. LowerExpr(AST.Child(seq, 0), t, q);
  1271. conv := (SymTab.ClassOf(SymTab.CurRes()) = SymTab.ClReal)
  1272. AND SymTab.IsIntFamily(t);
  1273. IF conv THEN QbeGen.ConvIR(q, qt); QbeGen.EmitRet(qt, TRUE)
  1274. ELSE QbeGen.EmitRet(q, TRUE)
  1275. END
  1276. END
  1277. ELSIF k = AST.NkCase THEN LowerCase(seq)
  1278. ELSIF k = AST.NkWith THEN LowerWith(seq)
  1279. ELSIF k = AST.NkCall THEN
  1280. CalleeName(seq, qn);
  1281. IF IsBuiltin(qn) THEN LowerBuiltinStmt(seq, qn)
  1282. ELSE LowerCall(seq, t, q, FALSE)
  1283. END
  1284. END
  1285. END LowerStmt;
  1286. PROCEDURE LowerDecls (seq: AST.Node);
  1287. VAR i, j: CARDINAL; c: AST.Node; nm, txt: SymTab.Name; qv: QbeGen.QVal;
  1288. mg: QbeGen.QVal; uid, depth, np: CARDINAL; res, pt: SymTab.TypeIndex;
  1289. ext, pv: BOOLEAN;
  1290. BEGIN
  1291. IF seq = AST.NoNode THEN RETURN END;
  1292. i := 0;
  1293. WHILE i < AST.NChild(seq) DO
  1294. c := AST.Child(seq, i);
  1295. IF i = AST.MaxChild - 1 THEN LowerDecls(c)
  1296. ELSIF AST.Kind(c) = AST.NkDeclSeq THEN LowerDecls(c)
  1297. ELSIF AST.Kind(c) = AST.NkVarDecl THEN
  1298. j := 0;
  1299. WHILE j < AST.NChild(c) DO
  1300. Name(AST.Child(c, j), nm);
  1301. QbeGen.DeclVar(nm, AST.Ty(c));
  1302. INC(j)
  1303. END
  1304. ELSIF AST.Kind(c) = AST.NkConstDecl THEN
  1305. Name(AST.Child(c, 0), nm);
  1306. Name(AST.Child(c, 1), txt);
  1307. QbeGen.NormInt(txt, qv);
  1308. QbeGen.DeclConst(nm, qv, AST.Ty(c))
  1309. ELSIF AST.Kind(c) = AST.NkProcDecl THEN
  1310. Name(AST.Child(c, 0), nm);
  1311. IF NOT ProcInfo(nm, uid, res, depth, ext, np) THEN END;
  1312. QbeGen.Mangled(nm, uid, mg);
  1313. QbeGen.BeginFunc(mg);
  1314. j := 0;
  1315. WHILE j < np DO
  1316. IF NOT ParamInfo(nm, j, pt, pv, txt) THEN END;
  1317. IF NOT QbeGen.FuncParam(txt, pv, pt) THEN END;
  1318. INC(j)
  1319. END;
  1320. QbeGen.SetFuncRes(res);
  1321. QbeGen.EndFuncHeader;
  1322. LowerDecls(AST.Child(c, 2));
  1323. LowerStmt(AST.Child(c, 1));
  1324. QbeGen.EndFunc(res)
  1325. END;
  1326. INC(i)
  1327. END
  1328. END LowerDecls;
  1329. PROCEDURE LowerUnit (unit: AST.Node);
  1330. VAR nm: SymTab.Name; out: ARRAY [0 .. 255] OF CHAR; i: CARDINAL;
  1331. BEGIN
  1332. withTop := 0;
  1333. Name(AST.Child(unit, 0), nm);
  1334. i := 0;
  1335. WHILE (i <= 254) AND (i <= HIGH(nm)) AND (nm[i] # CHR(0)) DO
  1336. out[i] := nm[i]; INC(i)
  1337. END;
  1338. out[i] := "L"; INC(i); out[i] := CHR(0);
  1339. QbeGen.OpenModule(nm);
  1340. QbeGen.SetOutName(out);
  1341. QbeGen.SetModule(nm);
  1342. LowerDecls(AST.Child(unit, 1));
  1343. QbeGen.BeginBody;
  1344. LowerStmt(AST.Child(unit, 2));
  1345. QbeGen.EndModule(nm)
  1346. END LowerUnit;
  1347. BEGIN
  1348. END Lower.