DIRECTORY Atoms, CCTypes, CedarCode, CedarOtherPureTypes, CirioMemory, CirioNubAccess, CirioTargets, CirioTypes, DeferringTypes, IO, LoadStateAccess, MobAccess, MobObjectFiles, NewRMTW, ObjectFiles, PFS, PointerTypes, Procedures, RefTypes, RMTWPrivate, Rope, Symbols, SystemInterface; RMTWPointers: CEDAR PROGRAM IMPORTS Atoms, CCTypes, CedarCode, CedarOtherPureTypes, CirioMemory, CirioNubAccess, CirioTypes, DeferringTypes, IO, LoadStateAccess, MobAccess, MobObjectFiles, NewRMTW, ObjectFiles, PFS, PointerTypes, Procedures, RefTypes, RMTWPrivate, Rope, SystemInterface EXPORTS NewRMTW, RMTWPrivate SHARES Rope = BEGIN OPEN LSA:LoadStateAccess, ObjF:ObjectFiles, MA:MobAccess, MOF:MobObjectFiles, RMTWPrivate; Operator: TYPE = CedarCode.Operator; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE ฌ NIL] ฌ CCTypes.CCError; RemoteMimosaTargetWorld: TYPE = REF RemoteMimosaTargetWorldBody; RemoteMimosaTargetWorldBody: PUBLIC TYPE = RMTWPrivate.RemoteMimosaTargetWorldBody; TargetBitsPerWord: CARD = 32; AnalyzedRefSEH: TYPE = REF AnalyzedRefSEHBody; AnalyzedRefSEHBody: TYPE = RECORD[ rmtw: RemoteMimosaTargetWorld, directRefType: Type, size: CARD, clientTargetType: Type, isRA: BOOL ]; AnalyzeRefSEH: PUBLIC PROC[dft: Type, seh: SEH, ser: SER, cons: REF cons MA.BodySE, ti: REF ref MA.TypeInfoConsSE, rmtw: RemoteMimosaTargetWorld, sk: SehKnowledge] RETURNS[Type] = { sei: Symbols.SEIndex ~ MA.GetSeiForSEH[seh]; clientTargetType, refType, ropeType: Type; private: AnalyzedRefSEH ฌ NIL; ropeBti: BasicTypeInfo ฌ NIL; bti: BasicTypeInfo ฌ NEW[BasicTypeInfoPrivate ฌ [CreateIndirectRefNode, RefBitSize, NIL]]; isRA: BOOL ฌ FALSE; IF MA.GetSeiForSEH[ti.refType] = LOOPHOLE[stopSei] THEN skAtStopSei ฌ sk; IF sk=none AND rmtw.atomSei#Symbols.SENull AND sei=rmtw.atomSei THEN sk ฌ ATOM; IF ti.ordered AND ti.basing THEN { refType ฌ AnalyzedUnknownSEH[seh, rmtw, "ORDERED BASE POINTER (you don't want to look closely)", bitsPerPtr]; DeferringTypes.SetUndertype[dft, refType]; RETURN [refType]}; IF sk=ROPE THEN { ropeBti ฌ NEW [BasicTypeInfoPrivate ฌ [RopeCreateIndirect, RefBitSize, NIL]]; DeferringTypes.SetUndertype[dft, ropeType ฌ CedarOtherPureTypes.CreateRopeType[rmtw.cc, ropeBti]]}; IF sk=ATOM THEN { DeferringTypes.SetUndertype[dft, refType ฌ Atoms.CreateAtomType[rmtw.cc, bti]]; IF rmtw.atomSei=Symbols.SENull THEN rmtw.atomSei ฌ sei; IF rmtw.atomRecRT=NIL THEN rmtw.atomRecRT ฌ AnalyzeSEH[rmtw.atomRecSeh, rmtw, notSpecial]; clientTargetType ฌ rmtw.atomRecRT} ELSE { underTargetSeh: SEH ฌ UnderTypeSEH[ti.refType, rmtw]; targetSer: SER ฌ MA.FetchSER[underTargetSeh]; WITH targetSer.body SELECT FROM x: REF cons MA.BodySE => isRA ฌ x.typeInfo.typeTag=any; x: REF id MA.BodySE => CCE[cirioError, "UnderTypeSEH returned an id seh"]; ENDCASE => ERROR; IF isRA THEN refType ฌ RefTypes.CreateRefAnyType[rmtw.cc, bti] ELSE refType ฌ RefTypes.CreateRefType[rmtw.cc, bti]; IF sk#ROPE THEN DeferringTypes.SetUndertype[dft, refType]; IF NOT isRA THEN clientTargetType ฌ AnalyzeSEH[ ti.refType, rmtw, SELECT sk FROM none, notSpecial => none, ROPE => RopeRep, ATOM => notSpecial, RopeRep => CCE[cirioError, IO.PutFR1["Implausible SehKnowledge for REF SEH %g", [rope[FmtSeh[seh, ""]]] ]], ENDCASE => ERROR ]; }; private ฌ NEW[AnalyzedRefSEHBodyฌ[ rmtw: rmtw, directRefType: refType, size: ti.length, clientTargetType: clientTargetType, isRA: isRA]]; bti.btiData ฌ private; IF sk=ATOM THEN Atoms.SetAtomRecType[refType, clientTargetType, rmtw.cc] ELSE IF NOT isRA THEN RefTypes.SetReferent[refType, clientTargetType, 0, rmtw.cc]; IF sk = ROPE THEN {ropeBti.btiData ฌ private; RETURN[ropeType]} ELSE RETURN[private.directRefType]; }; stopSei: CARD ฌ 1; skAtStopSei: SehKnowledge ฌ notSpecial; RefBitSize: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type] RETURNS[CARD] = { private: AnalyzedRefSEH ฌ NARROW[bti.btiData]; RETURN[private.size]}; CreateIndirectRefNode: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type, mem: Mem] RETURNS[Node] = { private: AnalyzedRefSEH ฌ NARROW[bti.btiData]; nodeData: REF RefNodeData ฌ NEW[RefNodeData ฌ [private, mem]]; RETURN[CedarCode.CreateCedarNode[RefOps, indirectType, nodeData]]}; RefNodeData: TYPE = RECORD[private: AnalyzedRefSEH, mem: Mem]; RefOps: REF CedarCode.OperationsBody ฌ NEW[CedarCode.OperationsBodyฌ[ unaryOp: RefUnaryOp, store: RefStore, load: RefLoad]]; RefUnaryOp: PROC[op: Operator, type: Type, node: Node, cc: CC] RETURNS[Node] = { IF op # $address THEN CCE[cirioError, "address is the only supported unary operation on REFs"] ELSE { nodeData: REF RefNodeData ฌ NARROW[CedarCode.GetDataFromNode[node]]; RETURN[ConvertFromIndirectToPointer[node, nodeData.mem, nodeData.private.rmtw]]; }; }; RefStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = { nodeData: REF RefNodeData ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; rmtw: RemoteMimosaTargetWorld ~ nodeData.private.rmtw; mem: Mem ~ nodeData.mem; refSize: CARD ~ nodeData.private.size; via: REF ANY ~ CedarCode.GetNodeRepresentation[valNode, cc]; rc: REF CARD ~ IF via=NIL THEN NIL ELSE WITH via SELECT FROM ani: Atoms.AtomNodeInfo => WITH ani.data SELECT FROM x: REF CARD => x, ENDCASE => CCE[cirioError, "storing atom with useless AtomNodeInfo.data"], rni: RefTypes.RefNodeInfo => WITH rni.data SELECT FROM x: REF CARD => x, ENDCASE => CCE[cirioError, "storing REF with useless RefNodeInfo.data"], ENDCASE => CCE[cirioError, "storing REF with unexpected node rep"]; IF rc=NIL THEN mem.MemWrite[0, bitsPerPtr, zeroBA] ELSE { mem.MemWrite[rcญ, bitsPerPtr, zeroBA]}; RETURN}; RefLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = { nodeData: REF RefNodeData ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; rmtw: RemoteMimosaTargetWorld ~ nodeData.private.rmtw; mem: Mem ~ nodeData.mem; refSize: CARD ~ nodeData.private.size; errMsg: Rope.ROPE ฌ NIL; isRA: BOOL ~ nodeData.private.isRA; isAtom: BOOL ฌ CCTypes.GetTypeClass[indirectType] = $atom; addrBits: CARD; referentSize: BitAddr ฌ unspecdBA; referentOffset: BitAddr ฌ zeroBA; targetDirectType: Type ฌ nodeData.private.clientTargetType; targetIndirectType: Type ฌ NIL; { ENABLE { CirioNubAccess.RemoteAddrFault => {errMsg ฌ IO.PutFR["CirioNubAccess.RemoteAddrFault[byteAddress: %x, valid: %g]", [integer[addr.byteAddress]], [boolean[addr.valid]] ]; GOTO unknownAddress}; CCE => {errMsg ฌ msg; GOTO unknownAddress}; }; IF NOT isRA THEN targetIndirectType ฌ CCTypes.GetIndirectType[targetDirectType]; addrBits ฌ mem.MemRead[bitsPerPtr, zeroBA]; IF addrBits IN [0..8) THEN RETURN[IF isAtom THEN Atoms.CreateNilAtomNode[nodeData.private.clientTargetType, cc] ELSE RefTypes.CreateNilRefNode[cc]] ELSE { referentOffset ฌ CirioTypes.PtrToBa[addrBits]; IF isRA THEN { typeAddr: CirioNubAccess.RemoteAddress ฌ NewRMTW.BaToCnra[rmtw.nub, CirioMemory.PtrToBa[addrBits-4]]; typeCode: CARD ฌ CirioNubAccess.Read32BitsAsCard[typeAddr]; targetDirectType ฌ AnalyzeTc[rmtw, typeCode]; isAtom ฌ targetDirectType = rmtw.atomRecRT; targetIndirectType ฌ CCTypes.GetIndirectType[targetDirectType]}; --Compute target size-- { ENABLE CCE => CONTINUE; --MJS August 21, 1990: have to allow for REF RECORD [..SEQUENCE..], which refuses to compute a bitSize (which obviously should take some more parameters) bareReferentSize: CARD ~ CCTypes.GetBitSize[targetIndirectType, cc]; IF bareReferentSize RETURN[UnimplementedTypeNode[indirectType, rmtw, errMsg]]; }}; bitsPerTargetWord: NAT = 32; GetAtomPointer: PROC [data: REF ANY, cc: CC] RETURNS[CirioTypes.Node] ~ {CCE[unimplemented, "RMTWPointers.GetAtomPointer was thought (by MJS on 13-Dec-90) to be unneeded"]}; AnalyzedProcSEH: TYPE ~ REF AnalyzedProcSEHBody; AnalyzedProcSEHBody: TYPE ~ RECORD [ rmtw: RemoteMimosaTargetWorld, type: Type ฌ NIL, typeIn, typeOut: Type]; AnalyzeProcedureSEH: PUBLIC PROC[ti: REF transfer MA.TypeInfoConsSE, cons: REF cons MA.BodySE, ser: SER, seh: SEH, rmtw: RemoteMimosaTargetWorld] RETURNS[Type] = { private: AnalyzedProcSEH ~ NEW [AnalyzedProcSEHBody ฌ [ rmtw: rmtw, typeIn: IF ti.typeIn#NIL THEN AnalyzeSEH[ti.typeIn, rmtw, none] ELSE NIL, typeOut: IF ti.typeOut#NIL THEN AnalyzeSEH[ti.typeOut, rmtw, none] ELSE NIL]]; bti: BasicTypeInfo ~ NEW[BasicTypeInfoPrivate ฌ [ProcCreateIndirect, ProcBitSize, private]]; IF ti.typeIn=NIL OR ti.typeOut=NIL THEN { empty: Type ~ AnalyzeRecordSEH[seh: NIL, ser: NIL, cons: NIL, ti: NIL, rmtw: rmtw, isRopeRep: FALSE]; IF ti.typeIn=NIL THEN private.typeIn ฌ empty; IF ti.typeOut=NIL THEN private.typeOut ฌ empty}; private.type ฌ Procedures.CreateProcedureType[private.typeIn, private.typeOut, rmtw.cc, bti]; RETURN[private.type]}; AnalProcTs: PUBLIC PROC [rmtw: RemoteMimosaTargetWorld, tsd: TsDict, i: INT, opts: TsOptions] RETURNS [Type, INT] ~ { i2, i3: INT; argType, retType: Type; [argType, i2] ฌ AnalyzeTs[rmtw, tsd, i]; [retType, i3] ฌ AnalyzeTs[rmtw, tsd, i2]; {private: AnalyzedProcSEH ~ NEW [AnalyzedProcSEHBody ฌ [ rmtw, NIL, argType, retType]]; bti: BasicTypeInfo ~ NEW[BasicTypeInfoPrivate ฌ [ProcCreateIndirect, ProcBitSize, private]]; private.type ฌ Procedures.CreateProcedureType[private.typeIn, private.typeOut, rmtw.cc, bti]; RETURN[private.type, i3]}}; ProcBitSize: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type] RETURNS[CARD] ~ { private: AnalyzedProcSEH ~ NARROW[bti.btiData]; RETURN [TargetBitsPerWord]}; ProcCreateIndirect: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type, mem: Mem] RETURNS[Node] ~ { private: AnalyzedProcSEH ~ NARROW[bti.btiData]; procIndirect: ProcIndirect ~ NEW [ProcIndirectBody ฌ [private, mem]]; RETURN CedarCode.CreateCedarNode[ProcOps, indirectType, procIndirect]}; ProcIndirect: TYPE ~ REF ProcIndirectBody; ProcIndirectBody: TYPE ~ RECORD [private: AnalyzedProcSEH, mem: Mem]; ProcOps: REF CedarCode.OperationsBody ฌ NEW[CedarCode.OperationsBodyฌ[ unaryOp: ProcUnaryOp, store: ProcStore, load: ProcLoad]]; ProcUnaryOp: PROC[op: Operator, type: Type, node: Node, cc: CC] RETURNS[Node] ~ { IF op # $address THEN CCE[cirioError, "Procedure indirects only implement $address"]; {procIndirect: ProcIndirect ~ NARROW[CedarCode.GetDataFromNode[node]]; RETURN ConvertFromIndirectToPointer[node, procIndirect.mem, procIndirect.private.rmtw]}}; ProcStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] ~ { procIndirect: ProcIndirect ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; rmtw: RemoteMimosaTargetWorld ~ procIndirect.private.rmtw; procInfo: Procedures.ProcedureNodeInfo ~ NARROW[CedarCode.GetNodeRepresentation[valNode, cc]]; procDirect: ProcDirect ~ NARROW[procInfo.data]; procIndirect.mem.MemWrite[bits: LOOPHOLE[procDirect.repAddr.byteAddress], bitSize: bitsPerPtr, offset: zeroBA]; RETURN}; ProcLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] ~ { procIndirect: ProcIndirect ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; rmtw: RemoteMimosaTargetWorld ~ procIndirect.private.rmtw; mem: Mem ~ procIndirect.mem; {ENABLE CirioNubAccess.RemoteAddrFault, CCE => GOTO unknownAddress; repBits: CARD ~ procIndirect.mem.MemRead[bitsPerPtr, zeroBA]; repAddr: CirioNubAccess.RemoteAddress ~ NewRMTW.BaToCnra[rmtw.nub, [aus: repBits, bits: 0]]; analProcSEH: AnalyzedProcSEH ฌ procIndirect.private; procDirect: ProcDirect ~ NEW [ProcDirectBody ฌ [rmtw, analProcSEH, repAddr, [h: NIL, byteAddress: 0, bitOffset: 0, nil: FALSE, valid: FALSE], 0]]; procInfo: Procedures.ProcedureNodeInfo ~ NEW [Procedures.ProcedureNodeInfoBody ฌ [CallProc, DescribeProc, procDirect]]; IF repAddr.valid AND NOT repAddr.nil THEN { ENABLE CirioNubAccess.RemoteNilFault, CirioNubAccess.RemoteAddrFault => CONTINUE; procDirect.pc ฌ [h: repAddr.h, byteAddress: CirioNubAccess.Read32BitsAsCard[repAddr], bitOffset: 0, nil: FALSE, valid: TRUE]; procDirect.pcCard ฌ LOOPHOLE[procDirect.pc.byteAddress]; procDirect.pc.nil ฌ procDirect.pc.byteAddress = 0; }; RETURN Procedures.CreateProcedureNode[procIndirect.private.type, procInfo]; EXITS unknownAddress => RETURN[UnimplementedTypeNode[indirectType, rmtw, "proc at bad address"]]; }}; ProcDirect: TYPE ~ REF ProcDirectBody; ProcDirectBody: TYPE ~ RECORD [ rmtw: RemoteMimosaTargetWorld, analProcSEH: AnalyzedProcSEH, repAddr, pc: CirioNubAccess.RemoteAddress, pcCard: CARD]; CreateProcConstant: PUBLIC PROC [rmtw: RemoteMimosaTargetWorld, jmpi: MobObjectFiles.JointMobParsedInfo, searchMem: Mem, textBase: CARD, bth: MobAccess.BTH] RETURNS [ans: Node] ~ { MakeBroken: PROC [explanation: Rope.ROPE] RETURNS [Node] ~ { ukt: Type ~ CedarOtherPureTypes.CreateUnknownType[rmtw.cc, explanation]; RETURN CedarOtherPureTypes.CreateUnknownTypeNode[ukt, explanation, rmtw.cc]}; IF bth = NIL THEN -- can happen for MACHINE CODE procedures ans ฌ MakeBroken["broken procedure constant (because of NIL BTH --- MACHINE CODE?)"] ELSE BEGIN ENABLE CCE => { ans ฌ MakeBroken[IO.PutFR["broken procedure constant (for %g, reason=%g)", [rope[DescribeBth[bth]]], [rope[msg]] ]]; CONTINUE}; relPC: CARD ~ MOF.GetEntryPCofCallableBTH[bth, jmpi]; absPC: CARD ~ relPC + textBase; frameStart: BitAddr ~ searchMem.MemGetStart[]; frameLen: BitAddr ~ searchMem.MemGetSize[]; btr: MA.BTR ~ MA.FetchBTR[bth]; flag: CARD ~ SELECT btr.level FROM >Symbols.lL => 1, =Symbols.lL => 0, ERROR, ENDCASE => ERROR; repAddr: CirioNubAccess.RemoteAddress ~ SeekDescr[absPC, flag, frameStart.aus, frameLen.aus, rmtw.nub]; IF NOT repAddr.valid THEN RETURN [MakeBroken[IO.PutFR["broken procedure constant (unable to find cell describing pc=%xH, flg=%g for %g)", [cardinal[absPC]], [cardinal[flag]], [rope[DescribeBth[bth]]] ]]]; {procType: Type ~ WITH btr.extension SELECT FROM x: REF Callable MA.BTRExtension => AnalyzeSEH[x.ioType, rmtw, none], ENDCASE => CCE[cirioError, "body not callable"]; procPrivate: REF ANY ~ CCTypes.GetTypeRepresentation[procType, rmtw.cc]; analProcSEH: AnalyzedProcSEH ~ WITH procPrivate SELECT FROM procBTI: BasicTypeInfo => WITH procBTI.btiData SELECT FROM x: AnalyzedProcSEH => x, ENDCASE => CCE[cirioError, "analysis of callable body's IO type fails (way 1)"], ENDCASE => CCE[cirioError, "analysis of callable body's IO type fails (way 2)"]; procDirect: ProcDirect ~ NEW [ProcDirectBody ฌ [rmtw, analProcSEH, repAddr, [rmtw.nub, LOOPHOLE[absPC], 0, FALSE, TRUE], absPC]]; procInfo: Procedures.ProcedureNodeInfo ~ NEW [Procedures.ProcedureNodeInfoBody ฌ [CallProc, DescribeProc, procDirect]]; RETURN Procedures.CreateProcedureNode[procType, procInfo]} END; RETURN}; DescribeBth: PROC [bth: MobAccess.BTH] RETURNS [Rope.ROPE] ~ { mob: MobAccess.MobCookie; bti: Symbols.BTIndex; [mob, bti] ฌ MobAccess.BTHDetails[bth]; RETURN IO.PutFR["", [rope[PFS.RopeFromPath[SystemInterface.GetNameOfFile[MobAccess.GetFileForMobCookie[mob]]]]], [cardinal[LOOPHOLE[bti]]] ]}; SeekDescr: PROC [pc, link: CARD, base, bytes: CARD, nub: CirioNubAccess.Handle] RETURNS [da: CirioNubAccess.RemoteAddress ฌ [NIL, 0, 0, FALSE, FALSE]] ~ { ENABLE CirioNubAccess.RemoteNilFault, CirioNubAccess.RemoteAddrFault => CONTINUE; limit: CARD ~ base+bytes; target: CirioTargets.Target ~ NARROW[nub.target]; pcBA: CirioMemory.BitAddr ฌ CirioMemory.PtrToBa[pc]; fDescrBA: CirioMemory.BitAddr ~ target.DescriptorFromPC[target, pcBA]; fDescr: CARD ~ CirioMemory.BaToPtr[fDescrBA]; ans: CARD ฌ 0; found: BOOL ฌ FALSE; da ฌ [nub, base, 0, FALSE, TRUE]; WHILE da.byteAddress < limit DO fDescrCand: CARD ~ CirioNubAccess.Read32BitsAsCard[da]; da.byteAddress ฌ da.byteAddress + 4; IF fDescrCand=fDescr THEN { linkCand: CARD ~ CirioNubAccess.Read32BitsAsCard[da]; IF linkCand=link THEN { ans ฌ da.byteAddress - 4; IF found THEN RETURN [[NIL, 0, 0, FALSE, FALSE]]; found ฌ TRUE}; }; ENDLOOP; IF found THEN da.byteAddress ฌ ans ELSE da.valid ฌ FALSE; RETURN}; CallProc: PROC[args: Node, cc: CC, data: REF ANY] RETURNS[Node] ~ { procDirect: ProcDirect ฌ NARROW[data]; nub: CirioNubAccess.Handle ฌ procDirect.rmtw.nub; analProcSEH: AnalyzedProcSEH ฌ procDirect.analProcSEH; argType: Type ฌ analProcSEH.typeIn; argIndirectType: Type ฌ CCTypes.GetIndirectType[analProcSEH.typeIn]; argBitSize: CARD ฌ CCTypes.GetBitSize[argIndirectType, cc]; argByteSize: CARD ฌ (argBitSize+7)/8; argArea: CirioNubAccess.AllocatedBytes ฌ CirioNubAccess.AllocateBytes[nub, argByteSize]; argMem: Mem ฌ CreateSimpleMem[addr: argArea.bytes, size: [aus: argByteSize, bits: 0]]; argAreaNode: Node ฌ CCTypes.CreateIndirectNode[argIndirectType, argMem, cc]; resultType: Type ฌ analProcSEH.typeOut; resultIndirectType: Type ฌ CCTypes.GetIndirectType[resultType]; resultBitSize: CARD ฌ CCTypes.GetBitSize[resultIndirectType, cc]; resultByteSize: CARD ฌ (resultBitSize+7)/8; resultArea: CirioNubAccess.AllocatedBytes ฌ CirioNubAccess.AllocateBytes[nub, resultByteSize]; resultMem: Mem ฌ CreateSimpleMem[addr: resultArea.bytes, size: [aus: resultByteSize, bits: 0]]; resultAreaNode: Node ฌ CCTypes.CreateIndirectNode[resultIndirectType, resultMem, cc]; formalArgSizes, formalRetSizes: CirioNubAccess.SizeList; actualArgs, actualRets: CirioNubAccess.Fields; [formalArgSizes, actualArgs] ฌ AnalyzeArgRet[argType, cc, argArea]; [formalRetSizes, actualRets] ฌ AnalyzeArgRet[resultType, cc, resultArea]; CedarCode.StoreThroughIndirectNode[CedarCode.GetTypeOfNode[args], args, CedarCode.GetTypeOfNode[argAreaNode], argAreaNode, cc]; TRUSTED {CirioNubAccess.Call[nub, LOOPHOLE[procDirect.repAddr.byteAddress], formalArgSizes, formalRetSizes, actualArgs, actualRets]}; IF TRUE THEN BEGIN resultDeferedLoad: Node ฌ CedarCode.LoadThroughIndirectNode[CedarCode.GetTypeOfNode[resultAreaNode], resultAreaNode, cc]; result: Node ฌ CedarCode.ForceNodeIn[CedarCode.GetTypeOfNode[resultDeferedLoad], resultDeferedLoad, cc]; CirioNubAccess.ReleaseAllocatedBytes[argArea.allocHandle]; CirioNubAccess.ReleaseAllocatedBytes[resultArea.allocHandle]; RETURN[result]; END; CCTypes.CCError[unimplemented, "Can't call procedures yet"]; }; AnalyzeArgRet: PROC [recType: Type, cc: CC, area: CirioNubAccess.AllocatedBytes] RETURNS [formalSizes: CirioNubAccess.SizeList, actuals: CirioNubAccess.Fields] ~ { formalTail: CirioNubAccess.SizeList ฌ formalSizes ฌ LIST[0]; TakeN: PROC [length: CARD] ~ {actuals ฌ NEW [CirioNubAccess.FieldSeq[length]]}; TakeField: PROC [index: CARD, byteOffset: INT, bitOffset: INT, bitSize: CARD] ~ { addr: INT ~ area.bytes.byteAddress + byteOffset; f: CirioNubAccess.SizeList ~ LIST[bitSize]; actuals[index] ฌ [LOOPHOLE[addr], bitOffset, bitSize]; formalTail.rest ฌ f; formalTail ฌ f; RETURN}; GenRecordFields[recType, cc, TakeN, TakeField]; formalSizes ฌ formalSizes.rest; RETURN}; DescribeProc: PROC[to: IO.STREAM, data: REF ANY, depth, width: INT] ~ { procDirect: ProcDirect ~ NARROW[data]; rmtw: RemoteMimosaTargetWorld ~ procDirect.rmtw; sourceIndex: CARD ฌ 0; descr: ROPE ฌ ""; Basic: PROC RETURNS [d: Rope.ROPE] ~ { d ฌ IO.PutFR["pc=%g, descr at %g", [rope[FmtRemoteAddr[procDirect.pc]]], [rope[FmtRemoteAddr[procDirect.repAddr]]] ]; IF sourceIndex#0 THEN d ฌ d.Concat[IO.PutFR1[", src=%g", [cardinal[sourceIndex]] ]]; RETURN}; IF NOT procDirect.repAddr.valid THEN {to.PutRope["(invalid proc descriptor address)"]; RETURN}; IF procDirect.repAddr.nil THEN {to.PutRope["NIL"]; RETURN}; {ENABLE CCE => { descr ฌ Rope.Cat["(Proc, ", Basic[], ")"]; CONTINUE}; ledo: REF LSA.LoadedModuleInfo ~ IF procDirect.pc.valid THEN LSA.GetLoadedModuleInfoFromAbsPC[rmtw.lsh, procDirect.pcCard] ELSE CCE[cirioError]; relPC: CARD ~ IF ledo = NIL THEN 0 ELSE IF procDirect.pcCard >= ledo.lsi[text].base THEN procDirect.pcCard-ledo.lsi[text].base ELSE CCE[cirioError]; vs: REF ObjF.VersionStampInfo ~ IF ledo = NIL THEN NIL ELSE ObjF.FindVersionStamp[ledo.module]; IF ledo=NIL OR vs=NIL THEN { pci: CirioNubAccess.PCInfo ~ CirioNubAccess.PCtoInfo[rmtw.nub, procDirect.pcCard]; IF pci#NIL THEN { descr ฌ Rope.Cat[ IF pci.guessedEmbeddedFileName#NIL THEN PFS.RopeFromPath[pci.guessedEmbeddedFileName] ELSE "??", ".", pci.procName ]; IF depth>2 THEN descr ฌ Rope.Cat[ IF pci.fileName#NIL THEN PFS.RopeFromPath[pci.fileName] ELSE "??", ".", descr]; to.PutRope[descr]; RETURN}; }; IF ledo = NIL THEN { to.PutF1["(Proc at absPC=%xh without symbols)", [cardinal[procDirect.pcCard]] ]; RETURN}; IF vs=NIL THEN { to.PutF["(Proc at relPC=%xh in symbolless %g)", [cardinal[relPC]], [rope[PFS.RopeFromPath[ledo.loadedFile.GetNameOfFile]]] ]; RETURN}; {lmi: REF NewRMTW.LoadedModuleInfo ~ NewRMTW.GetLoadedModuleInfo[rmtw.cedarModules, ledo]; jmpi: MOF.JointMobParsedInfo ~ lmi.jmpi; bthList: LIST OF MA.BTH ฌ MOF.FindNearBTHAncestorsForPC[relPC, jmpi]; FOR bthList ฌ bthList, bthList.rest WHILE bthList#NIL DO btr: MA.BTR ~ MA.FetchBTR[bthList.first]; WITH btr.extension SELECT FROM x: REF Callable MA.BTRExtension => { ToName: PROC [btr: MA.BTR] RETURNS [Rope.ROPE] ~ { WITH btr.extension SELECT FROM y: REF Callable MA.BTRExtension => IF y.id#NIL THEN { id: REF id MA.BodySE ~ NARROW[MA.FetchSER[y.id].body]; RETURN [id.hash]}; ENDCASE => btr ฌ btr; RETURN[NIL]}; lastName: Rope.ROPE ~ ToName[btr]; sourceIndex ฌ btr.sourceIndex; descr ฌ IF lastName#NIL THEN lastName ELSE "(no name)"; IF depth>2 THEN descr ฌ descr.Cat["(", Basic[], ")"]; FOR parent: MA.BTR ฌ BTParent[btr], BTParent[parent] UNTIL parent=NIL DO thisName: Rope.ROPE ~ ToName[parent]; IF thisName#NIL THEN descr ฌ thisName.Cat[".", descr]; ENDLOOP; to.PutRope[descr]; RETURN}; ENDCASE => data ฌ data; ENDLOOP; }}; to.PutRope[descr]; RETURN}; BTParent: PROC [btr: MA.BTR] RETURNS [MA.BTR] ~ { btr ฌ btr; DO next: MA.BTR ~ MA.FetchBTR[btr.link.index]; SELECT btr.link.which FROM sibling => btr ฌ next; parent => RETURN [next]; ENDCASE => ERROR; ENDLOOP}; FmtRemoteAddr: PROC [ra: CirioNubAccess.RemoteAddress] RETURNS [Rope.ROPE] ~ { SELECT TRUE FROM ~ra.valid => RETURN ["(invalid address)"]; ra.nil => RETURN ["NIL"]; ra.bitOffset=0 => RETURN IO.PutFR1["%xh", [cardinal[ra.byteAddress]]]; ENDCASE => RETURN IO.PutFR["%xh[%xh]", [cardinal[ra.byteAddress]], [cardinal[ra.bitOffset]]]}; RopeNodeData: TYPE = RECORD[ style: RopeStyle, analyzedRefSeh: AnalyzedRefSEH, mem: Mem]; RopeStyle: TYPE ~ {pcedar2, cedar10}; RopeCreateIndirect: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type, mem: Mem] RETURNS[Node] = { analyzedRefSeh: AnalyzedRefSEH ฌ NARROW[bti.btiData]; directRepType: Type ฌ analyzedRefSeh.clientTargetType; indirectRepType: Type ฌ CCTypes.GetIndirectType[directRepType]; nodeData: REF RopeNodeData ฌ NEW[RopeNodeData ฌ [pcedar2, analyzedRefSeh, mem]]; {ENABLE CCE => GOTO Not; [] ฌ CCTypes.SelectIdField["v", indirectRepType, cc]; nodeData.style ฌ cedar10; EXITS Not => nodeData.style ฌ pcedar2}; RETURN[CedarCode.CreateCedarNode[RopeOps, indirectType, nodeData]]}; RopeOps: REF CedarCode.OperationsBody ฌ NEW[CedarCode.OperationsBodyฌ[ unaryOp: RopeUnaryOp, store: RopeStore, load: RopeLoad]]; RopeUnaryOp: PROC[op: Operator, type: Type, node: Node, cc: CC] RETURNS[Node] = { IF op # $address THEN CCE[cirioError, "address is the only supported unary operation on ROPEs"] ELSE { nodeData: REF RopeNodeData ฌ NARROW[CedarCode.GetDataFromNode[node]]; mem: Mem ฌ nodeData.mem; rmtw: RemoteMimosaTargetWorld ฌ nodeData.analyzedRefSeh.rmtw; RETURN[ConvertFromIndirectToPointer[node, mem, rmtw]]; }; }; RopeStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = { nodeData: REF RopeNodeData ฌ NARROW[CedarCode.GetDataFromNode[indirectNode]]; mem: Mem ฌ nodeData.mem; rmtw: RemoteMimosaTargetWorld ฌ nodeData.analyzedRefSeh.rmtw; info: REF CedarOtherPureTypes.RopeInfo ฌ NARROW[CedarCode.GetNodeRepresentation[valNode, cc]]; ra: REF CARD ~ WITH info.addr SELECT FROM x: REF CARD => x, ENDCASE => NIL; IF ra=NIL THEN CCE[cirioError, "source ROPE not in target world (and creation there not yet implemented)."]; mem.MemWrite[raญ, bitsPerPtr, zeroBA]; RETURN}; RopeLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN nodeData: REF RopeNodeData ฌ NARROW[CedarCode.GetDataFromNode[indirectNode]]; mem: Mem ฌ nodeData.mem; rmtw: RemoteMimosaTargetWorld ฌ nodeData.analyzedRefSeh.rmtw; ropeAddr: CirioTypes.CirioAddress ฌ MakeCirioAddress[mem, rmtw]; ropeRepAddr: CirioTypes.CirioAddress ฌ ropeAddr.followPointer[0, ropeAddr]; IF ropeRepAddr.isNil[ropeRepAddr] THEN RETURN[CedarOtherPureTypes.CreateRopeNode[NIL, cc, NEW [CARD ฌ 0]]]; {rraCard: CARD ~ mem.MemRead[bitsPerPtr, zeroBA]; repMem: Mem ~ mem.MemIndirect[]; rope: ROPE ~ ReadRope[repMem, nodeData.style, rmtw.nub]; RETURN[CedarOtherPureTypes.CreateRopeNode[rope, cc, NEW [CARD ฌ rraCard]]]; }END; rfo: ARRAY RopeStyle OF RECORD [size, case: INT] ~ [pcedar2: [ 01, 62 ], cedar10: [ 32, 30 ] ]; ReadRope: PROC [repMem: Mem, style: RopeStyle, nub: CirioNubAccess.Handle, start: INT ฌ 0, len: INT ฌ INT.LAST] RETURNS [ROPE] ~ { tag: CARD ฌ repMem.MemRead[1, zeroBA]; case: CARD; size: INT; IF len<=0 THEN RETURN [""]; IF style=cedar10 THEN { IF tag#0 THEN RETURN ["!!a wide rope!!"]; tag ฌ repMem.MemRead[1, CirioMemory.BitsToBa[16]]}; IF tag=0 THEN { length: INT ~ repMem.MemRead[15, CirioMemory.BitsToBa[1]]; limitedLen: INT ~ MIN[len, MIN[length-start, 500]]; charsBS: BitAddr; charsRA: CirioNubAccess.RemoteAddress; chars: REF TEXT; IF limitedLen<=0 THEN RETURN [""]; charsBS ฌ repMem.MemGetStart[].BaAdd[CirioMemory.BaCons[start, 32]]; charsRA ฌ [nub, charsBS.aus, charsBS.bits, FALSE, TRUE]; chars ฌ CirioNubAccess.ReadBytes[charsRA, limitedLen]; RETURN Rope.FromRefText[chars]}; case ฌ repMem.MemRead[2, CirioMemory.BitsToBa[rfo[style].case]]; size ฌ repMem.MemRead[IF style=cedar10 THEN 32 ELSE 31, CirioMemory.BitsToBa[rfo[style].size]]; IF start >= size THEN RETURN [""]; len ฌ MIN[size-start, len]; SELECT case FROM 0 => {--substr baseMem: Mem ~ repMem.MemSubfield[[CirioMemory.BitsToBa[64], CirioMemory.BitsToBa[32]]].MemIndirect[]; istart: INT ~ repMem.MemRead[32, CirioMemory.BitsToBa[96]]; RETURN ReadRope[baseMem, style, nub, start+istart, len]}; 1 => {--concat baseMem: Mem ~ repMem.MemSubfield[[CirioMemory.BitsToBa[64], CirioMemory.BitsToBa[32]]].MemIndirect[]; restMem: Mem ~ repMem.MemSubfield[[CirioMemory.BitsToBa[96], CirioMemory.BitsToBa[32]]].MemIndirect[]; pos: INT ~ repMem.MemRead[32, CirioMemory.BitsToBa[128]]; base, rest: ROPE; IF start>=pos THEN RETURN ReadRope[restMem, style, nub, start-pos, len]; IF start+len <= pos THEN RETURN ReadRope[baseMem, style, nub, start, len]; base ฌ ReadRope[baseMem, style, nub, start, pos-start]; rest ฌ ReadRope[restMem, style, nub, 0, start+len-pos]; RETURN base.Concat[rest]}; 2 => {--replace baseMem: Mem ~ repMem.MemSubfield[[CirioMemory.BitsToBa[64], CirioMemory.BitsToBa[32]]].MemIndirect[]; replaceMem: Mem ~ repMem.MemSubfield[[CirioMemory.BitsToBa[96], CirioMemory.BitsToBa[32]]].MemIndirect[]; istart: INT ~ repMem.MemRead[32, CirioMemory.BitsToBa[128]]; oldPos: INT ~ repMem.MemRead[32, CirioMemory.BitsToBa[160]]; newPos: INT ~ repMem.MemRead[32, CirioMemory.BitsToBa[192]]; b1, rr, b2: ROPE ฌ NIL; IF start0 THEN {n: INT ~ MIN[len, newPos-start]; rr ฌ ReadRope[replaceMem, style, nub, start-istart, n]; len ฌ len - n; start ฌ newPos}; IF len>0 THEN {n: INT ~ MIN[len, size-newPos]; b2 ฌ ReadRope[baseMem, style, nub, start-newPos+oldPos, len]}; RETURN b1.Cat[rr, b2]}; 3 => RETURN ["!!object-oriented ROPE!!"]; ENDCASE => ERROR}; TransparentTypeInfo: TYPE ~ CedarOtherPureTypes.TransparentTypeInfo; AnalyzedUnknownSEH: PUBLIC PROC[seh: SEH, rmtw: RemoteMimosaTargetWorld, explanation: Rope.ROPE, bits: INT] RETURNS[Type] = {RETURN MakeBrokenType[rmtw, explanation, bits]}; MakeBrokenType: PUBLIC PROC[rmtw: RemoteMimosaTargetWorld, explanation: Rope.ROPE, bits: INT] RETURNS[Type] = { IF bits<0 THEN { targetType: Type ฌ CedarOtherPureTypes.CreateUnknownType[rmtw.cc, explanation]; RETURN[targetType]} ELSE { tti: TransparentTypeInfo ~ NEW [CedarOtherPureTypes.TransparentTypeInfoBody ฌ [TransparentCreateIndirect, explanation, bits, rmtw]]; targetType: Type ฌ CedarOtherPureTypes.CreateTransparentType[rmtw.cc, tti]; RETURN[targetType]}; }; UnimplementedTypeNode: PUBLIC PROC[targetType: Type, rmtw: RemoteMimosaTargetWorld, explanation: Rope.ROPE] RETURNS[CirioTypes.Node] = { unknownType: Type ฌ CedarOtherPureTypes.CreateUnknownType[rmtw.cc, explanation]; RETURN[CedarOtherPureTypes.CreateIndirectToAnUnknownType[unknownType, explanation, rmtw.cc]]; }; TransparentCreateIndirect: PROC[tti: TransparentTypeInfo, cc: CC, indirectType, targetType: Type, mem: Mem] RETURNS[Node] = { tnd: REF TransparentNodeData ~ NEW [TransparentNodeData ฌ [targetType, indirectType, mem, tti]]; RETURN[CedarCode.CreateCedarNode[TransparentOps, indirectType, tnd]]}; TransparentNodeData: TYPE ~ RECORD [ targetType, indirectType: Type, mem: Mem, tti: TransparentTypeInfo]; TransparentOps: REF CedarCode.OperationsBody ฌ NEW[CedarCode.OperationsBodyฌ[ unaryOp: TransparentUnaryOp, store: TransparentStore, load: TransparentLoad]]; TransparentUnaryOp: PROC[op: Operator, type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN IF op # $address THEN CCE[cirioError, "address is the only supported unary operation on Transparents"] ELSE BEGIN nodeData: REF TransparentNodeData ฌ NARROW[CedarCode.GetDataFromNode[node]]; rmtw: RemoteMimosaTargetWorld ฌ NARROW[nodeData.tti.data]; mem: Mem ฌ nodeData.mem; RETURN[ConvertFromIndirectToPointer[node, mem, rmtw]]; END; END; TransparentStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = { tnd: REF TransparentNodeData ฌ NARROW[CedarCode.GetDataFromNode[indirectNode]]; tni: CedarOtherPureTypes.TransparentNodeInfo ~ NARROW[CedarCode.GetNodeRepresentation[valNode, cc]]; mem: Mem ฌ tnd.mem; rmtw: RemoteMimosaTargetWorld ฌ NARROW[tnd.tti.data]; tti: TransparentTypeInfo ฌ tnd.tti; bytes: INT ~ (tti.bits+7)/8; rpad: INT ~ bytes*8 - tti.bits; srcBits: INT ~ tni.val.Length*8-(tni.lpad+tni.rpad); GetBits: PROC [i: INT] RETURNS [bits: BYTE] ~ { bits ฌ tni.val.Fetch[i].ORD; IF tni.lpad#0 THEN { bits ฌ (bits * (2**tni.lpad)) MOD 256; bits ฌ bits + (CARDINAL[tni.val.Fetch[i.SUCC].ORD] * (2**tni.lpad))/256; bits ฌ bits+0}; IF i.SUCC=bytes AND tni.rpad#0 THEN bits ฌ bits/(2**tni.rpad); RETURN}; IF tti.bits # srcBits THEN CCE[operation, IO.PutFR["Trying to store %g transparent bits into %g-bit container", [integer[srcBits]], [integer[tti.bits]] ]]; FOR i: INT IN [0..bytes) DO mem.MemWrite[bits: GetBits[i], bitSize: 8-(IF i=bytes THEN rpad ELSE 0), offset: [aus: i, bits: 0]]; ENDLOOP; RETURN}; TransparentLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = { tnd: REF TransparentNodeData ฌ NARROW[CedarCode.GetDataFromNode[indirectNode]]; mem: Mem ฌ tnd.mem; rmtw: RemoteMimosaTargetWorld ฌ NARROW[tnd.tti.data]; tti: TransparentTypeInfo ฌ tnd.tti; bytes: INT ~ (tti.bits+7)/8; rpad: INT ~ bytes*8 - tti.bits; i: INT ฌ 0; val: Rope.ROPE; NextByte: PROC RETURNS [CHAR] ~ { byte: BYTE ฌ mem.MemRead[bitSize: 8-(IF i=bytes THEN rpad ELSE 0), offset: [aus: i, bits: 0]]; IF (i ฌ i.SUCC)=bytes THEN byte ฌ byte*(2**rpad); RETURN [VAL[byte]]}; val ฌ Rope.FromProc[bytes, NextByte]; RETURN CedarOtherPureTypes.CreateTransparentTypeNode [CCTypes.GetTargetTypeOfIndirect [indirectType], NEW [CedarOtherPureTypes.TransparentNodeInfoBody ฌ [val, 0, rpad]], cc]}; DummyGetPointer: PUBLIC PROC[data: REF ANY, cc: CC] RETURNS[CirioTypes.Node] = BEGIN CCE[unimplemented]; END; PointerCreateIndirect: PROC [bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { rmtw: RemoteMimosaTargetWorld ~ NARROW[bti.btiData]; referentIndirectType: Type ~ PointerTypes.GetReferentType[targetType]; pi: PointerIndirect ~ NEW [PointerIndirectPrivate ฌ [rmtw, indirectType, targetType, referentIndirectType, mem]]; RETURN CedarCode.CreateCedarNode[PointerOps, indirectType, pi]}; PointerBitSize: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type] RETURNS[CARD] ~ { rmtw: RemoteMimosaTargetWorld ~ NARROW[bti.btiData]; RETURN[bitsPerPtr]}; PointerOps: REF CedarCode.OperationsBody ฌ NEW[CedarCode.OperationsBodyฌ[ unaryOp: PointerUnaryOp, store: PointerStore, load: PointerLoad]]; PointerIndirect: TYPE ~ REF PointerIndirectPrivate; PointerIndirectPrivate: TYPE = RECORD[ rmtw: RemoteMimosaTargetWorld, ptrIndirectType, ptrDirectType, referentIndirectType: Type, mem: Mem]; PointerUnaryOp: PROC[op: Operator, type: Type, node: Node, cc: CC] RETURNS[Node] = { IF op # $address THEN CCE[cirioError, "address is the only supported unary operation on POINTERs"] ELSE { nodeData: PointerIndirect ฌ NARROW[CedarCode.GetDataFromNode[node]]; RETURN[ConvertFromIndirectToPointer[node, nodeData.mem, nodeData.rmtw]]; }; }; PointerStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = { nodeData: REF RefNodeData ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; rmtw: RemoteMimosaTargetWorld ~ nodeData.private.rmtw; mem: Mem ~ nodeData.mem; refSize: CARD ~ nodeData.private.size; valInfo: PointerTypes.PointerNodeInfo ~ NARROW[CedarCode.GetNodeRepresentation[valNode, cc]]; IF valInfo=NIL THEN mem.MemWrite[0, bitsPerPtr, zeroBA] ELSE { pointerData: PointerDirect ~ NARROW[valInfo.data]; mem.MemWrite[pointerData.ptrVal, bitsPerPtr, zeroBA]}; RETURN}; PointerLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = { nodeData: PointerIndirect ฌ NARROW[CedarCode.GetDataFromNode[indirectNode]]; rmtw: RemoteMimosaTargetWorld ฌ nodeData.rmtw; mem: Mem ฌ nodeData.mem; errMsg: Rope.ROPE ฌ NIL; referentIndirectType: Type ฌ nodeData.referentIndirectType; referentDirectType: Type ฌ CCTypes.GetTargetTypeOfIndirect[referentIndirectType]; BEGIN ENABLE { CirioNubAccess.RemoteAddrFault => {errMsg ฌ IO.PutFR["CirioNubAccess.RemoteAddrFault[byteAddress: %x, valid: %g]", [integer[addr.byteAddress]], [boolean[addr.valid]] ]; GOTO unknownAddress}; CCE => {errMsg ฌ msg; GOTO unknownAddress}; }; addrBits: CARD ~ mem.MemRead[bitsPerPtr, CirioTypes.zeroBA]; IF addrBits IN [0..8) THEN RETURN[PointerTypes.CreateNilPointerNode[cc]] ELSE BEGIN referentSize: BitAddr ฌ unspecdBA; {ENABLE CCE => CONTINUE; --MJS August 21, 1990: have to allow for REF RECORD [..SEQUENCE..], which refuses to compute a bitSize (which obviously should take some more parameters) bareReferentSize: CARD ~ CCTypes.GetBitSize[referentIndirectType, cc]; rounded: CARD ~ ((bareReferentSize+(bitsPerTargetWord-1))/bitsPerTargetWord) * bitsPerTargetWord; referentSize ฌ [aus: rounded/bitsPerAu, bits: rounded MOD bitsPerAu]; }; { targetMem: Mem ~ CreateSimpleMem[addr: NewRMTW.BaToCnra[rmtw.nub, [aus: addrBits, bits: 0]], size: referentSize]; --numeric load cares about the size referentIndirect: Node ~ CCTypes.CreateIndirectNode[referentIndirectType, targetMem, cc]; RETURN ConvertFromIndirectToPointer[referentIndirect, targetMem, rmtw]; }END; EXITS unknownAddress => RETURN[UnimplementedTypeNode[indirectType, rmtw, errMsg]]; END; }; PointerDirect: TYPE ~ REF PointerData; PointerData: TYPE = RECORD[ rmtw: RemoteMimosaTargetWorld, clientTargetType: Type, mem: Mem, ptrVal: CARD]; ConvertFromIndirectToPointer: PUBLIC PROC[indirect: CirioTypes.Node, mem: Mem, rmtw: RemoteMimosaTargetWorld] RETURNS[CirioTypes.Node] = { indirectType: Type ฌ CedarCode.GetTypeOfNode[indirect]; clientTargetType: Type ฌ CCTypes.GetTargetTypeOfIndirect[indirectType]; pointerBTI: BasicTypeInfo ฌ NEW[BasicTypeInfoPrivate ฌ [PointerCreateIndirect, PointerBitSize, rmtw]]; pointerType: Type ฌ PointerTypes.CreatePointerType[clientTargetType, rmtw.cc, pointerBTI]; referentStart: BitAddr ฌ mem.MemGetStart[]; pointerData: PointerDirect ฌ NEW[PointerDataฌ[ rmtw: rmtw, clientTargetType: clientTargetType, mem: mem, ptrVal: LOOPHOLE[referentStart.aus] ]]; info: PointerTypes.PointerNodeInfo ฌ NEW[PointerTypes.PointerNodeInfoBodyฌ[ clientTargetType: clientTargetType, indirectToClientTarget: indirect, getAddress: PointerGetAddress, pointerAdd: PointerAdd, pointerCardValue: PointerCardValue, data: pointerData]]; IF referentStart.bits#0 THEN CCE[cirioError, "trying to make a pointer to a non-AU-aligned address"]; RETURN PointerTypes.CreatePointerNode[pointerType, info, rmtw.cc]}; PointerGetAddress: PROC[data: REF ANY, cc: CC] RETURNS[CirioTypes.CirioAddress] = { pointerData: PointerDirect ฌ NARROW[data]; RETURN[MakeCirioAddress[pointerData.mem, pointerData.rmtw]]}; PointerAdd: PROC[offset: INT, data: REF ANY, cc: CC] RETURNS [CirioTypes.Node] = { oldPointerData: PointerDirect ฌ NARROW[data]; translatedMem: Mem ฌ oldPointerData.mem.MemShift[[aus: offset, bits: 0]]; indirectTargetType: Type ฌ CCTypes.GetIndirectType[oldPointerData.clientTargetType]; in: Node ฌ CCTypes.CreateIndirectNode[indirectTargetType, translatedMem, cc]; n: Node ฌ ConvertFromIndirectToPointer[in, translatedMem, oldPointerData.rmtw]; RETURN [n]}; PointerCardValue: PROC[data: REF ANY] RETURNS [CARD] = { pointerData: PointerDirect ฌ NARROW[data]; ba: BitAddr ฌ pointerData.mem.MemGetStart[]; IF ba.bits#0 THEN CCE[cirioError, "pointer not byte-aligned!"]; RETURN[LOOPHOLE[ba.aus]]}; MakeCirioAddress: PROC[mem: Mem, rmtw: RemoteMimosaTargetWorld] RETURNS[CirioTypes.CirioAddress] = BEGIN addressData: REF AddressData ฌ NEW[AddressDataฌ[rmtw, mem, FALSE]]; RETURN[NEW [CirioTypes.CirioAddressBody ฌ [CirioAddressIsNil, ReadBitsForCirioAddress, WriteBitsForCirioAddress, FollowPointerForCirioAddress, AsCardForCirioAddress, addressData]]]; END; AddressData: TYPE = RECORD[ rmtw: RemoteMimosaTargetWorld, mem: Mem, nil: BOOL]; CirioAddressIsNil: PROC [data: CirioTypes.CirioAddress] RETURNS [BOOL] ~ { addressData: REF AddressData ฌ NARROW[data.data]; RETURN [addressData.nil]}; ReadBitsForCirioAddress: PROC [byteOffset: INT ฌ 0, bitOffset: INT ฌ 0, bitSize: CARD, data: CirioTypes.CirioAddress] RETURNS [CARD] = { addressData: REF AddressData ฌ NARROW[data.data]; IF addressData.nil THEN CCE[operation, "Dereferencing NIL in debuggee (CirioAddress)"]; {fullOffset: INT ฌ byteOffset + bitOffset/8; remainingBitOffset: INT ฌ bitOffset MOD 8; RETURN addressData.mem.MemRead[bitSize: bitSize, offset: [aus: fullOffset, bits: remainingBitOffset]]}}; WriteBitsForCirioAddress: PROC [byteOffset: INT ฌ 0, bitOffset: INT ฌ 0, bitSize: CARD, data: CirioTypes.CirioAddress, bits: CARD] = { addressData: REF AddressData ฌ NARROW[data.data]; CCE[unimplemented, "write bits through a CirioTypes.CirioAddress impl'd in RMTWPointers"]}; FollowPointerForCirioAddress: PROC[byteOffset: INT ฌ 0, data: CirioTypes.CirioAddress] RETURNS[CirioTypes.CirioAddress] = BEGIN addressData: REF AddressData ~ NARROW[data.data]; IF addressData.nil THEN CCE[operation, "Dereferencing NIL in debuggee (CirioAddress)"]; {mem: Mem ~ addressData.mem; newPointerVal: CARD ฌ ReadBitsForCirioAddress[byteOffset, 0, 32, data]; newAddr: CirioNubAccess.RemoteAddress ฌ [ addressData.rmtw.nub, newPointerVal, 0, newPointerVal = 0, TRUE]; newAddressData: REF AddressData ฌ NEW[AddressDataฌ[ rmtw: addressData.rmtw, mem: noMem, nil: newAddr.nil ]]; IF NOT newAddr.nil THEN { newAddressData.mem ฌ CreateSimpleMem[newAddr, unspecdBA]}; RETURN[NEW [CirioTypes.CirioAddressBody ฌ [CirioAddressIsNil, ReadBitsForCirioAddress, WriteBitsForCirioAddress, FollowPointerForCirioAddress, AsCardForCirioAddress, newAddressData]]]; }END; AsCardForCirioAddress: PROC[data: CirioTypes.CirioAddress] RETURNS[CARD] = { addressData: REF AddressData ฌ NARROW[data.data]; mem: Mem ฌ addressData.mem; start: BitAddr ฌ mem.MemGetStart[]; IF start.bits#0 THEN CCE[cirioError, "asking for non-AU-aligned address as CARD"]; RETURN[LOOPHOLE[start.aus]]}; BaToCnra: PUBLIC PROC [nub: CirioNubAccess.Handle, ba: CirioTypes.BitAddr] RETURNS [CirioNubAccess.RemoteAddress] ~ { RETURN [[nub, ba.aus, ba.bits, ba.aus=0, ba.aus#INT.LAST]]}; END. ๐ RMTWPointers.mesa Copyright ำ 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Last tweaked by Mike Spreitzer on August 17, 1992 3:21 pm PDT Philip James, February 24, 1992 10:28 am PST Laurie Horton, September 19, 1991 4:38 pm PDT Katsuyuki Komatsu March 31, 1992 5:35 pm PST Willie-s, September 17, 1992 10:24 am PDT Intro Ref Types For the moment we can not handle ref any. This will require help from the nub to find text strings. Moreover, we can not deliver the code at type time until we get help from the nub. So, I deliver 0. we nest a block to handle unknown address, allowing nodeData to be visible Procedures now lets pick up the results, clean up, and return Rope Types exploratory code a major issue is how we recognize a rope, must catch all REF Rope.RopeRep?? intercepting Rope.RopeRep is not good enough, because we have to catch all stores of rope literals to a REF Rope.RopeRep. The following procedures follow the pattern of ordinary types this routine collects up to 500 chars of the rope. Perhaps we should change CedarOtherPureTypes interface to allow for a late collection of the chars, so we only need to collect as many as are needed. (further, we could collect more than 500 if the client wanted.) perhaps we should work in terms of the typed rep, instead of working in terms of the bits unimplemented types etc Get Pointer mechanism (If a general mechanism is possible, I am not sure) (for the moment, we supply an unimplemented error) Now we get down to business. (more or less, still basically unimplemented because pointers are now (September 1, 1989 10:19:36 am PDT) confused in my mind.) we nest a block to handle unknown address, allowing nodeData to be visible Cirio Address this is pretty crocky ส&Y•NewlineDelimiter –"cedarcode" style™code™Kšœ ฯeœC™NK™=K™,K™-K™,K™)—K˜Kšฯk œxžœDžœR˜œK˜šฯn œžœž˜KšžœjžœDžœH˜‚Kšžœ˜Kšžœ˜ K˜—K˜Kš žœžœžœŸœžœ žœ˜`K˜™Kšœ žœ˜$K˜Kšžœžœ&žœžœ˜NK˜Kšœžœžœ˜@Kšœžœžœ+˜SK˜KšŸœžœ˜K˜—™ K™K™สK™Kšœžœžœ˜.šœžœžœ˜"Kšœ˜K˜Kšœžœ˜ Kšœ˜Kšœž˜ Kšœ˜—K˜šŸ œžœžœžœžœžœžœ žœžœBžœ ˜ตKšœžœ˜,Kšœ*˜*Kšœžœ˜Kšœžœ˜Kšœžœ<žœ˜ZKšœžœžœ˜Kšžœžœžœ žœ˜IKš žœ žœžœžœžœ˜Ošžœ žœ žœ˜"K˜mKšœ*˜*Kšžœ ˜—šžœžœžœ˜Kšœ žœ:žœ˜MK˜c—šžœžœžœ˜K˜OKšžœžœ˜7Kšžœžœžœ@˜ZK˜"—šžœ˜Kšœžœ"˜5Kšœ žœžœ˜-šžœžœž˜Kšœžœžœ)˜7Kšœžœžœ žœ0˜JKšžœžœ˜—šžœ˜Kšžœ2˜6Kšžœ0˜4—Kšžœžœžœ+˜:šžœžœžœ˜/Kšœ ˜ Kšœ˜šžœž˜Kšœ˜Kšžœ ˜Kšžœ˜Kšœ žœ žœN˜kKšžœž˜—Kšœ˜—K˜—šœ žœ˜"K˜ Kšœ˜Kšœ˜Kšœ#˜#Kšœ ˜ —K˜Kšžœžœžœ9˜HKšžœžœžœžœ=˜Ršžœž˜ Kšžœžœ ˜2Kšžœžœ˜#—Kšœ˜Kšœ žœ˜K˜'—K˜š Ÿ œžœžœ"žœžœ˜^Kšœžœ˜.Kšžœ˜—K˜šŸœžœžœ,žœ ˜sKšœžœ˜.Kšœ žœžœ˜>Kšžœ=˜C—K˜Kšœ žœžœ$˜>K˜šŸœžœžœ˜EK˜Kšœ˜Kšœ˜—K˜šŸ œžœ+žœžœ ˜PKšžœ˜KšžœžœE˜Mšžœ˜Kšœ žœžœ"˜DKšžœJ˜PKšœ˜—Kšœ˜K˜—šŸœžœKžœ˜`Kšœ žœžœ*˜LKšœ6˜6Kšœ˜Kšœ žœ˜&Kšœžœžœ0˜<šœžœžœžœž˜Kšžœž˜šžœžœžœž˜šœžœ žœž˜4Kšœžœžœ˜Kšžœžœ<˜J—šœžœ žœž˜6Kšœžœžœ˜Kšžœžœ:˜H—Kšžœžœ5˜C——šžœžœžœ%žœ˜9K˜'—Kšžœ˜—K˜šŸœžœ-žœžœ ˜OKšœ žœžœ*˜LKšœ6˜6Kšœ˜Kšœ žœ˜&Kšœ žœžœ˜Kšœžœ˜#Kšœžœ.˜:Kšœ žœ˜K˜"K˜!K˜;Kšœžœ˜K˜K˜KšœJ™JKšœ˜šžœ˜Kšœ,žœ{žœ˜พKšžœžœ˜+K˜—K˜Kšžœžœžœ@˜PK˜K˜+K˜Kšžœ žœžœžœžœžœ@žœ˜“šœžœ˜K˜.šžœžœ˜K˜eKšœ žœ-˜;K˜-K˜+K˜@—šฯcœ˜Kšžœžœžœ ™˜ฑKšœžœ.˜Dšžœ$žœ˜,K˜SK˜5K˜—šžœ˜Kšœ žœT˜aK˜-—Kšœ˜—Kšœ˜Kšœg˜gKšœW˜Wšžœžœ˜šœžœ˜9Kšœ˜Kšœ˜K˜Kšœžœžœ˜—Kšžœ1˜7K˜—šžœ˜šœžœ˜=Kšœ$ $˜HKšœ ˜Kšœ)˜)Kšœžœžœ˜—KšžœC˜IK˜—Kšœ˜—šž˜Kšœžœ4˜L—Kšœ˜Kšœžœ˜—K˜š Ÿœžœžœžœžœžœ˜EKšœžœa˜g——K™™ K˜Kšœžœžœ˜0šœžœžœ˜$Kšœ˜Kšœ žœ˜Kšœ˜—K˜šŸœžœžœžœ žœžœžœžœžœ!žœ ˜ฃšœžœ˜7K˜ Kš œžœ žœžœ#žœžœ˜IKš œ žœ žœžœ$žœžœ˜N—KšœžœD˜\š žœ žœžœ žœžœ˜)Kš œ$žœžœžœžœžœ˜eKšžœ žœžœ˜-Kšžœ žœžœ˜0—K˜]Kšžœ˜—K˜š Ÿ œžœžœ1žœžœžœ˜uKšœžœ˜ K˜K˜(K˜)šœžœ˜8Kšœžœ˜—KšœžœD˜\K˜]Kšžœ˜K˜—š Ÿ œžœžœ"žœžœ˜_Kšœžœ˜/Kšžœ˜—K˜šŸœžœžœ,žœ ˜pKšœžœ˜/Kšœžœ%˜EKšžœA˜G—K˜Kšœžœžœ˜*Kšœžœžœ&˜EK˜šŸœžœžœ˜FKšœ˜K˜K˜—K˜šŸ œžœ+žœžœ ˜QKšžœžœžœ<˜UKšœžœ"˜FKšžœS˜Y—K˜šŸ œžœKžœ˜aKšœžœ*˜MKšœ:˜:Kšœ)žœ/˜^Kšœžœ˜/Kšœ žœG˜oKšžœ˜—K˜šŸœžœ-žœžœ ˜PKšœžœ*˜MKšœ:˜:K˜Kšœžœ!žœžœ˜CKšœ žœ0˜=Kšœ\˜\K˜4Kš œžœ4žœ%žœ žœ˜’Kšœ)žœK˜wšžœžœžœ žœ˜+KšžœBžœ˜QKšœižœ žœ˜}Kšœžœ˜8K˜2K˜—KšžœE˜KKšžœžœC˜aKšœ˜—K˜Kšœ žœžœ˜&šœžœžœ˜Kšœ˜Kšœ˜Kšœ*˜*Kšœžœ˜—K˜š Ÿœžœžœdžœžœžœ˜ดšŸ œžœžœžœ ˜K˜K˜K˜'Kšžœžœ'žœ^žœ ˜ค—K˜šŸ œžœ žœžœžœ&žœžœžœ˜šKšžœBžœ˜QKšœžœ˜Kšœžœ ˜1K˜4KšœF˜FKšœžœ!˜-Kšœžœ˜Kšœžœžœ˜Kšœžœžœ˜!šžœž˜Kšœ žœ'˜7K˜$šžœžœ˜Kšœ žœ'˜5šžœžœ˜K˜Kš žœžœžœžœžœžœ˜1Kšœžœ˜—K˜—Kšžœ˜—Kšžœžœžœ žœ˜9Kšžœ˜—K˜š Ÿœžœžœžœžœžœ ˜CKšœžœ˜&K˜1K˜6K˜#K˜DKšœ žœ+˜;Kšœ žœ˜%K˜XK˜VK˜LK˜'K˜?Kšœžœ.˜AKšœžœ˜+K˜^K˜_K˜UK˜Kšœ8˜8Kšœ.˜.K˜K˜CK˜IK˜Kšœ˜K˜Kšžœžœ[˜…K˜K™2šžœžœž˜ Kšž˜K˜yK˜hKšœ:˜:Kšœ=˜=Kšžœ ˜Kšžœ˜—Kšœ<˜˜DK˜——šŸœžœžœ˜FK˜Kšœ˜Kšœ˜—K˜šŸ œžœ+žœžœ ˜QšžœžœžœGžœ˜fKšœ žœžœ"˜EK˜K˜=Kšžœ0˜6Kšœ˜—Kšœ˜K˜—šŸ œžœKžœ˜aKšœ žœžœ*˜MK˜K˜=Kšœžœ žœ/˜^š œžœžœžœ žœž˜)Kšœžœžœ˜Kšžœžœ˜—K™KšžœžœžœžœZ˜lK˜&Kšžœ˜—˜KšœŠ™Š—šŸœžœ-žœžœ˜NKšž˜Kšœ žœžœ*˜MK˜K˜=˜@K™Y—K˜KKš žœ žœžœ$žœžœžœ˜kKšœ žœ#˜1Kšœ ˜ Kšœžœ.˜8K˜Kšžœ.žœžœ˜KKšœžœ˜—K™š œžœ žœžœžœ˜0˜K˜——K˜šŸœžœDžœ žœžœžœžœžœ˜‚Kšœžœ˜&Kšœžœ˜ Kšœžœ˜ Kšžœžœžœ˜šžœžœ˜Kšžœžœžœ˜)K˜3—šžœžœ˜Kšœžœ/˜:Kšœ žœžœžœ˜3Kšœ˜Kšœ&˜&Kšœžœžœ˜Kšžœžœžœ˜"K˜DKšœ+žœžœ˜8K˜6Kšžœ˜ —K˜@Kšœžœžœžœ,˜_Kšžœžœžœ˜"Kšœžœ˜šžœž˜šœ ˜Kšœf˜fKšœžœ0˜;Kšžœ3˜9—šœ˜Kšœf˜fKšœf˜fKšœžœ1˜9Kšœ žœ˜Kšžœ žœžœ/˜HKšžœžœžœ+˜JK˜7K˜7Kšžœ˜—šœ  ˜Kšœf˜fKšœi˜iKšœžœ1˜—Kšžœ˜—Kšœžœ˜)Kšžœžœ˜——K˜K˜—™K˜Kšœžœ+˜DK˜šŸœžœžœžœ3žœžœžœ˜yKšœžœ*˜3—K˜š Ÿœžœžœ2žœžœžœ ˜ošžœžœ˜K˜OKšžœ ˜—šžœ˜Kšœžœf˜„K˜KKšžœ˜—Kšœ˜—K˜š ŸœžœžœDžœžœ˜ˆK˜PKšžœW˜]Kšœ˜—K˜šŸœžœžœ,žœ ˜}Kšœžœžœ>˜`Kšžœ@˜F—K˜šœžœžœ˜$Kšœ˜Kšœ ˜ Kšœ˜—K˜šŸœžœžœ˜MK˜Kšœ˜Kšœ˜—K˜šŸœžœ+žœžœ˜VKšž˜šžœžœžœNž˜kKšž˜Kšœ žœžœ"˜LKšœ žœ˜:K˜Kšžœ0˜6Kšžœ˜—Kšžœ˜K˜—šŸœžœKžœ˜hKšœžœžœ*˜OKšœ/žœ/˜dK˜Kšœ žœ˜5K˜#Kšœžœ˜Kšœžœ˜Kšœ žœ(˜4š Ÿœžœžœžœžœ˜/Kšœžœ˜šžœ žœ˜Kšœžœ˜&Kšœžœžœžœ˜HK˜—Kšžœžœžœ žœ˜>Kšžœ˜—Kšžœžœžœ žœo˜›šžœžœžœ ž˜Kšœ+žœ žœžœ ˜dKšžœ˜—Kšžœ˜—K˜šŸœžœ-žœžœ ˜WKšœžœžœ*˜OK˜Kšœ žœ˜5K˜#Kšœžœ˜Kšœžœ˜Kšœžœ˜ Kšœ žœ˜šŸœžœžœžœ˜!Kš œžœžœ žœžœ ˜^Kšžœžœžœ˜1Kšžœžœ ˜—K˜%Kšžœ`žœF˜ฏ——K˜™K™3K™2K˜šŸœžœžœžœžœžœžœ˜NKšž˜Kšžœ˜Kšžœ˜—K˜K™K™šŸœžœžœ,žœ ˜uKšœ žœ˜4KšœF˜FKšœžœX˜qKšžœ:˜@—K˜š Ÿœžœžœ"žœžœ˜bKšœ žœ˜4Kšžœ˜—K˜šŸ œžœžœ˜IK˜Kšœ˜Kšœ˜—K˜Kšœžœžœ˜3šœžœžœ˜&Kšœ˜Kšœ;˜;Kšœ ˜ K˜—šŸœžœ+žœžœ ˜TKšžœ˜KšžœžœI˜Qšžœ˜Kšœžœ"˜DKšžœB˜HKšœ˜—Kšœ˜K˜—šŸ œžœKžœ˜dKšœ žœžœ*˜LKšœ6˜6Kšœ˜Kšœ žœ˜&Kšœ(žœ/˜]šžœ žœžœ%žœ˜>Kšœžœ˜2Kšœ6˜6—Kšžœ˜—K˜šŸ œžœ-žœžœ ˜SKšœžœ*˜LK˜.K˜Kšœ žœžœ˜K˜;K˜QšœJ™JKšž˜šžœ˜Kšœ,žœ{žœ˜พKšžœžœ˜+K˜——˜Kšœ žœ.˜