<<>> <> <> <> <> <> DIRECTORY C2CAddressing, C2CBasics, C2CCodePlaces, C2CDefs, C2CStateUtils, C2CTarget, C2CEmit, C2CNames, C2CTypes, IntCodeUtils, IO, Rope, SymTab; C2CTypesAndStateImpl: CEDAR PROGRAM IMPORTS C2CBasics, C2CNames, C2CTarget, C2CTypes, C2CEmit, IntCodeUtils, IO, Rope, SymTab EXPORTS C2CTypes, C2CStateUtils = BEGIN bitsPerWord: INT ¬ C2CTarget.bitsPerWord; ROPE: TYPE = Rope.ROPE; TypesDescRec: TYPE = RECORD [ macroNames: SymTab.Ref ¬ NIL, arrays: IntCodeUtils.IdTab, ptrs: IntCodeUtils.IdTab, fields: IntCodeUtils.IdTab, fCast: ROPE ¬ NIL, procDescType: ROPE ¬ NIL, ptrProcDescType: ROPE ¬ NIL ]; globalTypes: REF TypesDescRec; DeclareTypeLine: PROC [line: ROPE] = { C2CEmit.AppendCode[typeDeclarations, C2CEmit.Cat[line, ";\n"]]; }; DefineType: PUBLIC PROC [numberOfBits: INT] RETURNS [name: ROPE] = { <<--allways return the canonical type for size>> <<--canonical type are arranged such that we won't need double word alignment on sun 4>> <<--never returns "double": that type behaves too funny>> IF numberOfBits=0 THEN C2CBasics.CantHappen; numberOfBits ¬ C2CTarget.PointeeBits[numberOfBits]; SELECT TRUE FROM numberOfBits=bitsPerWord => RETURN [C2CTarget.word]; numberOfBits=8 => RETURN [C2CTarget.byte]; numberOfBits=C2CTarget.bitsPerHalfWord => RETURN [C2CTarget.halfWord]; ENDCASE => { declaration: ROPE; types: REF TypesDescRec ~ globalTypes; WITH IntCodeUtils.Fetch[types.arrays, numberOfBits] SELECT FROM r: ROPE => RETURN [r] ENDCASE => NULL; name ¬ C2CNames.TryName[IO.PutFR1["W%g", [integer[numberOfBits/bitsPerWord]]]]; [] ¬ IntCodeUtils.Store[types.arrays, numberOfBits, name]; IF numberOfBits<=C2CTarget.maxBitsForSimpleStructs THEN { <<--make special declarations of small structures for more easy access of fields>> declaration ¬ "typedef struct {word f0"; FOR i: INT IN [1..numberOfBits/bitsPerWord) DO declaration ¬ IO.PutFR["%g, f%g", IO.rope[declaration], IO.int[i]]; ENDLOOP; declaration ¬ Rope.Cat[declaration, ";} ", name]; } ELSE { <<--build type with powers of two; >> <<--using subtypes of canonical sizes reduces the necessary number of subtypes.>> piece: INT ¬ C2CTarget.bitsPerWord; WHILE (piece+piece) RETURN [C2CTarget.wordPtr]; numberOfBits=8 => RETURN [C2CTarget.bytePtr]; numberOfBits=C2CTarget.bitsPerHalfWord => RETURN [C2CTarget.halfWordPtr]; ENDCASE => { baseType: ROPE; types: REF TypesDescRec ~ globalTypes; WITH IntCodeUtils.Fetch[types.ptrs, numberOfBits] SELECT FROM r: ROPE => RETURN [r] ENDCASE => NULL; IF numberOfBits=0 THEN { <<--the front end thinks the size does not matter...>> name ¬ C2CNames.TryName["PointerTo0BitsShouldNotBeUsed"]; DeclareTypeLine[IO.PutFR1["typedef int *%g", [rope[name]]]]; [] ¬ IntCodeUtils.Store[types.ptrs, numberOfBits, name]; RETURN }; baseType ¬ DefineType[numberOfBits]; name ¬ C2CNames.TryName[Rope.Concat[baseType, "Pt"]]; [] ¬ IntCodeUtils.Store[types.ptrs, numberOfBits, name]; DeclareTypeLine[IO.PutFR["typedef %g *%g", [rope[baseType]], [rope[name]]]]; }; }; DefineFTypeCast: PUBLIC PROC [] RETURNS [cast: ROPE] = { types: REF TypesDescRec ~ globalTypes; IF types.fCast#NIL THEN RETURN [types.fCast] ELSE { name: ROPE ¬ C2CNames.TryName["fPt"]; DeclareTypeLine[IO.PutFR["typedef %g (*%g)()", [rope[C2CTarget.word]], [rope[name]]]]; cast ¬ types.fCast ¬ Rope.Cat[" (", name, ") "]; } }; DefineProcDescPtrType: PUBLIC PROC [] RETURNS [name: ROPE] = { types: REF TypesDescRec ~ globalTypes; IF types.ptrProcDescType#NIL THEN RETURN [types.ptrProcDescType] ELSE { types.ptrProcDescType ¬ name ¬ C2CNames.TryName["PDPt"]; DeclareTypeLine[ IO.PutFR["typedef %g *%g", IO.rope[DefineProcDescBodyType[]], IO.rope[name]] ]; } }; DefineProcDescBodyType: PUBLIC PROC [] RETURNS [name: ROPE] = { types: REF TypesDescRec ~ globalTypes; IF types.procDescType#NIL THEN RETURN [types.procDescType] ELSE { types.procDescType ¬ name ¬ C2CNames.TryName["PDBody"]; DeclareTypeLine[ IO.PutFR["typedef struct {%g proc; %g link;} %g", IO.rope[C2CTarget.word], IO.rope[C2CTarget.word], IO.rope[name]] ]; } }; AccessKey: PROC [off: INT, bits: INT, total: INT] RETURNS [INT] = { IF off<0 OR bits<0 OR bits+off>total THEN C2CBasics.CantHappen; SELECT TRUE FROM total=C2CTarget.bitsPerWord => total ¬ 0; total=8 AND C2CTarget.hasBytes => total ¬ 1; total=C2CTarget.bitsPerHalfWord AND C2CTarget.hasHalfWords => total ¬ 2; ENDCASE => C2CBasics.CantHappen; RETURN [total + 4 * (bits + off*C2CTarget.bitsPerWord)]; }; NewModule: PROC = { globalTypes ¬ NEW[TypesDescRec¬[ macroNames: SymTab.Create[], arrays: IntCodeUtils.NewIdTab[], ptrs: IntCodeUtils.NewIdTab[], fields: IntCodeUtils.NewIdTab[] ]]; }; Macro: TYPE = REF MacroRep; MacroRep: PUBLIC TYPE = RECORD [name: ROPE, def: ROPE]; DeclareVariable: PUBLIC PROC [place: C2CCodePlaces.CodePlace, bits: INT, prefix: ROPE ¬ NIL] RETURNS [name: ROPE] = { code: C2CDefs.Code; IF bits<=0 THEN C2CBasics.CantHappen; IF prefix=NIL THEN SELECT place FROM moduleDeclarations => prefix ¬ "g"; ENDCASE => prefix ¬ "x"; name ¬ C2CNames.InternalName[prefix]; code ¬ C2CEmit.Cat[C2CTypes.DefineType[bits], " ", name, ";\n"]; SELECT place FROM moduleHeader, typeDeclarations, macroDeclarations, moduleDeclarations, moduleDeclarationsP => code ¬ C2CEmit.Cat["static ", code]; procedureDeclarations, blockDeclarations, temporaryDeclarations => {}; moduleContents, moduleInitializations => C2CBasics.CantHappen; ENDCASE => C2CBasics.NotYetImpl; C2CEmit.AppendCode[place, code]; }; DefineProcDesc: PUBLIC PROC [procName: ROPE] RETURNS [descAddr: ROPE] = { name: ROPE ¬ C2CNames.InternalName[Rope.Concat["PD", procName]]; pdType: ROPE ¬ C2CTypes.DefineProcDescBodyType[]; C2CEmit.AppendCode[moduleDeclarations, C2CEmit.Cat["static ", pdType, " ", name, C2CEmit.Cat[" = {(word) ", procName, ", 0};\n"]]]; descAddr ¬ Rope.Concat["&", name]; }; DefineMacro: PUBLIC PROC [name: ROPE, def: C2CDefs.CodeOrRope] RETURNS [Macro] = { [] ¬ C2CNames.Reserve[name]; RETURN [NEW[MacroRep ¬ [name: name, def: C2CEmit.CodeToRopeD[def]]]]; }; MacroName: PUBLIC PROC [macro: Macro] RETURNS [ROPE] = { r: REF TypesDescRec ¬ globalTypes; IF ~SymTab.Fetch[r.macroNames, macro.name].found THEN { [] ¬ SymTab.Insert[r.macroNames, macro.name, macro]; C2CEmit.AppendCode[macroDeclarations, C2CEmit.Cat["#define ", macro.name, macro.def, C2CEmit.line]]; }; RETURN [macro.name]; }; ANewBitAddress: PUBLIC PROC [] RETURNS [c: C2CAddressing.AddressContainer] = { c.words ¬ DeclareVariable[temporaryDeclarations, C2CTarget.bitsPerWord, "wAddr"]; c.bits ¬ DeclareVariable[temporaryDeclarations, C2CTarget.bitsPerWord, "bOff"]; }; C2CBasics.CallbackWhenC2CIsCalled[NewModule]; END.