<> <> <> <> <> <> DIRECTORY Alloc, Code, CodeDefs, ComData, FOpCodes, IntCodeDefs, P5, P5S, P5U, SymbolOps, Symbols, Tree; Address: PROGRAM IMPORTS MPtr: ComData, CPtr: Code, CodeDefs, P5U, P5, SymbolOps EXPORTS CodeDefs, P5S = BEGIN OPEN IntCodeDefs, CodeDefs; <> BitCount: TYPE = INT; -- should it be Symbols.BitCount; PackedBitCount: TYPE = Symbols.PackedBitCount; WordCount: TYPE = Symbols.WordCount; wordLength: CARDINAL = Symbols.WordLength; CSEIndex: TYPE = Symbols.CSEIndex; ISEIndex: TYPE = Symbols.ISEIndex; tb: Tree.Base; -- tree base (local copy) seb: Symbols.Base; -- semantic entry base (local copy) cb: CodeDefs.Base; -- code base (local copy) AddressNotify: PUBLIC Alloc.Notifier = BEGIN -- called by Code whenever table area is repacked seb _ base[Symbols.seType]; tb _ base[Tree.treeType]; cb _ base[codeType]; END; <> Index: PUBLIC PROC [node: Tree.Index] RETURNS [v: Var] = BEGIN -- generates code for array indexing arrayType: CSEIndex = P5U.OperandType[tb[node].son[1]]; grain, tBits: BitCount; packed: BOOL; indexRange: INT; ind: IndexedLocation; an: Node _ P5.Exp[tb[node].son[1]]; WITH a: seb[arrayType] SELECT FROM array => BEGIN grain _ SymbolOps.BitsPerElement[a.componentType, a.packed]; packed _ grain < wordLength; indexRange _ SymbolOps.Cardinality[a.indexType]; END; ENDCASE => ERROR; IF packed AND (tBits _ indexRange*grain) IN (0..wordLength) AND tBits < an.bits THEN an _ P5U.TakeField[n: an, vl: [disp: an.bits-tBits, size: tBits]]; ind _ z.NEW[indexed LocationRep _ [indexed[base: an, index: P5.Exp[tb[node].son[2]]]]]; v _ P5U.MakeVar[bits: grain, id: NullVariableId, loc: ind]; END; boundCheckOp: Node _ NIL; -- *** must NIL if z goes away descSize: CARDINAL = PtrSize + WordSize; DIndex: PUBLIC PROC [node: Tree.Index] RETURNS [l: Node] = BEGIN -- generates code for indexing from an array descriptor arrayDType: CSEIndex = SymbolOps.NormalType[P5U.OperandType[tb[node].son[1]]]; arrayType: CSEIndex = WITH seb[arrayDType] SELECT FROM arraydesc => SymbolOps.UnderType[describedType], ENDCASE => ERROR; grain: BitCount; nilck: BOOL = tb[node].attr1; bndck: BOOL = tb[node].attr3; t1: Tree.Link _ tb[node].son[1]; t2: Tree.Link _ tb[node].son[2]; desc, base, bound, index: Node; ind: Location; cl: CodeList _ P5U.NewCodeList[]; t1 _ P5U.ProcessSafens[cl, t1]; WITH a:seb[arrayType] SELECT FROM array => grain _ SymbolOps.BitsPerElement[a.componentType, a.packed]; ENDCASE => ERROR; desc _ P5.Exp[t1]; base _ P5U.TakeField[n: desc, vl: [disp: 0, size: PtrSize]]; IF nilck THEN base _ P5U.ApplyOp[oper: P5U.MesaOpNode[nilck], args: P5U.MakeNodeList[base], bits: PtrSize]; index _ P5.Exp[t2]; IF bndck THEN BEGIN bound _ P5U.TakeField[n: desc, vl: [disp: PtrSize, size: WordSize]]; index _ P5U.BoundsCheck[index, bound]; END; ind _ z.NEW[indexed LocationRep _ [indexed[base: P5U.Deref[base, 0], index: index]]]; l _ P5U.MakeVar[bits: grain, id: NullVariableId, loc: ind]; RETURN[P5U.MaybeBlock[cl, l]]; END; StringBoundSize: CARDINAL = 16; WordOffset: PROC [sei: ISEIndex] RETURNS [INT] = BEGIN bits: CARDINAL = seb[sei].idValue; RETURN [P5U.WordsForBits[bits]] END; SeqIndex: PUBLIC PROC [node: Tree.Index] RETURNS [l: Node] = BEGIN seqType: CSEIndex = P5U.OperandType[tb[node].son[1]]; t1: Tree.Link _ tb[node].son[1]; t2: Tree.Link _ tb[node].son[2]; isString: BOOL _ FALSE; grain: BitCount; bndck: BOOL = tb[node].attr3; index, elements, tag: Node; ind: Location; cl: CodeList _ P5U.NewCodeList[]; t1 _ P5U.ProcessSafens[cl, t1]; WITH ss: seb[seqType] SELECT FROM array => {isString _ TRUE; grain _ Symbols.ByteLength}; sequence => BEGIN grain _ SymbolOps.BitsPerElement[ss.componentType, ss.packed]; IF bndck THEN P5.AdjustNilCheck[tb[node].son[1], WordOffset[ss.tagSei]]; END; ENDCASE => ERROR; IF isString THEN { elements _ P5.Exp[tb[node].son[1]]; tag _ P5U.TakeField[n: elements, vl: [disp: -StringBoundSize, size: StringBoundSize]]} ELSE { tag _ P5.Exp[tb[node].son[1]]; -- The symbol table entry for the sequence part points to the tag (if any). If there is not tag (i.e., a COMPUTED sequence), it still points ahead of the sequence part. If one adds the size of this node to its location, one gets a node pointing to the beginning of the sequence part elements _ P5U.TakeField[n: tag, vl: [disp: tag.bits, size: 0]]}; index _ P5.Exp[t2]; IF bndck THEN index _ P5U.BoundsCheck[index, tag]; ind _ z.NEW[indexed LocationRep _ [indexed[base: elements, index: index]]]; l _ P5U.MakeVar[bits: grain, id: NullVariableId, loc: ind]; RETURN[P5U.MaybeBlock[cl, l]]; END; END.