C2CAddressingOpsImpl.mesa
Copyright Ó 1987, 1988, 1989, 1990, 1991, 1993 by Xerox Corporation. All rights reserved.
Christian Jacobi, March 10, 1988 2:46:34 pm PST
Christian Jacobi, January 25, 1993 7:14 pm PST
Jim Foote December 18, 1987 3:18:44 pm PST
DIRECTORY
C2CAddressing,
C2CAddressingOps,
C2CBasics,
C2CDefs,
C2CEmit,
C2CIntCodeUtils,
C2CCodeUtils,
C2CMain,
C2CMode,
C2CStateUtils,
C2CTarget,
C2CTypes,
IntCodeDefs,
Convert,
Rope;
C2CAddressingOpsImpl: CEDAR MONITOR
IMPORTS C2CBasics, C2CCodeUtils, C2CEmit, C2CIntCodeUtils, C2CMain, C2CMode, C2CStateUtils, C2CTarget, C2CTypes, Convert, Rope
EXPORTS C2CAddressingOps =
BEGIN
OPEN IntCodeDefs, C2CBasics, C2CDefs, C2CMain, C2CMode;
ROPE: TYPE = Rope.ROPE;
LoadArithNode: PUBLIC PROC [node: IntCodeDefs.Node] RETURNS [cc: CodeCont] = {
hasLab: BOOL ¬ C2CIntCodeUtils.StatementJumps[node: node];
bits: INT ¬ node.bits;
mode: Mode ¬ C2CMode.UseValue[bits];
IF bits>INT[C2CTarget.bitsPerDoubleWord] OR bits<=0 THEN
C2CBasics.FatalError["bad size expression"];
IF ~hasLab
THEN {
done: BOOL ¬ FALSE;
IF node.bits=1 THEN {
[done, cc] ¬ TrySpecialLoadBool[node];
};
IF NOT done THEN cc ¬ GenNode[node, mode];
}
ELSE {
sz: INT ¬ C2CTarget.TemporaryBits[bits];
tempName: ROPE ¬ C2CStateUtils.DeclareVariable[temporaryDeclarations, sz];
m1: Mode ¬ SetAssUnits[mode, tempName, sz];
cc ¬ GenNode[node, m1];
cc.ec ¬ C2CEmit.IdentCode[tempName];
C2CMode.FreeMode[m1];
};
IF cc.ec=NIL THEN CantHappen;
C2CMode.FreeMode[mode];
};
TrySpecialLoadBool: PROC [node: IntCodeDefs.Node] RETURNS [done: BOOL ¬ FALSE, cc: CodeCont ¬ [NIL, NIL, NIL]] = {
--just try, maybe we fetch just a sign bit...
IF node.bits#1 THEN RETURN;
WITH node SELECT FROM
var: Var => {
WITH var.location SELECT FROM
field: FieldLocation => IF field.start MOD 8 = 0 THEN {
WITH field.base SELECT FROM
bvar: Var => {
--Special checks in pointer case, (usage of alignment info!)
IF ISTYPE[bvar.location, DerefLocation] THEN {
TryPtr: PROC [bits: INT, type: ROPE] = {
IF field.start MOD bits = 0 THEN {
WITH bvar.location SELECT FROM
deref: DerefLocation => IF deref.align>=bits THEN {
cc ¬ LoadArithNode[deref.addr];
cc.ec ¬ C2CEmit.MinPrecedence[cc.ec, unaryPrecedence];
cc.ec ¬ C2CEmit.Cat["(", type, "*)", cc.ec];
IF field.start>0 THEN cc.ec ¬ C2CEmit.Cat["(", cc.ec, " + ", C2CCodeUtils.ConstI[field.start/bits], ")"];
cc.ec ¬ C2CEmit.Cat["*", cc.ec, "<0"];
cc.ec ¬ C2CEmit.SetPrecedence[cc.ec, orderPrecedence];
done ¬ TRUE;
RETURN
};
ENDCASE;
};
};
TryPtr[C2CTarget.bitsPerWord, C2CTarget.signedWord];
IF NOT done AND C2CTarget.hasHalfWords THEN
TryPtr[C2CTarget.bitsPerHalfWord, C2CTarget.signedHalf];
RETURN;
};
--non pointer case
IF field.start MOD C2CTarget.bitsPerWord = 0 AND C2CIntCodeUtils.SizeIsProvableOk[bvar] AND bvar.bits>=field.start+C2CTarget.bitsPerWord THEN {
n: Node ¬ NEW[VarRep ¬ var­];
n.bits ¬ C2CTarget.bitsPerWord;
cc ¬ LoadArithNode[n];
cc.ec ¬ C2CEmit.MinPrecedence[cc.ec, unaryPrecedence];
cc.ec ¬ C2CEmit.Cat["(int)", cc.ec, "<0"];
cc.ec ¬ C2CEmit.SetPrecedence[cc.ec, orderPrecedence];
done ¬ TRUE;
RETURN
};
};
ENDCASE;
};
ENDCASE;
};
ENDCASE;
};
ModizeArithCode: PUBLIC PROC [incc: CodeCont, mode: Mode, bits: INT ¬ 0] RETURNS [cc: CodeCont] = {
AssCast: PROC [] RETURNS [ROPE] = {
type: ROPE ¬ C2CTypes.DefineType[bits];
RETURN [Rope.Cat[" = (", type, ") "]];
};
am: C2CAddressing.AddressMode ¬ GetAMode[mode];
IF bits<1 THEN {
SELECT am FROM
skip, getAddr, getBitAddr, assBitAddr => {};
ENDCASE => NotYetImpl;
};
cc ¬ incc;
IF cc.xbc#NIL THEN NotYetImpl;
IF cc.ec#NIL
THEN cc.ec ¬ C2CEmit.MinPrecedence[cc.ec, unaryPrecedence]
ELSE IF am#skip THEN NotYetImpl;
SELECT am FROM
skip => {
IF cc.ec#NIL THEN cc.sc ¬ C2CEmit.Cat[cc.sc, "(void) ", cc.ec, ";\n"];
cc.ec ¬ NIL;
};
value, plain, maskNShift => {};
assAddr => {
cont: ROPE ¬ GetTemplate[mode];
IF C2CEmit.GetAddressable[cc.ec]
THEN cc.sc ¬ C2CEmit.Cat[cc.sc, cont, " = ", C2CEmit.TakeAddr[cc.ec], ";\n"]
ELSE CantHappen;
cc.ec ¬ NIL;
};
getAddr => {
IF C2CEmit.GetAddressable[cc.ec]
THEN cc.ec ¬ C2CEmit.TakeAddr[cc.ec, TRUE]
ELSE CantHappen;
};
getBitAddr => {
--convert from right adjusted value mode to left adjusted getBitAddr mode
unitSz: INT ¬ C2CTarget.TemporaryBits[bits];
cc.xbc ¬ NIL;
IF C2CEmit.GetAddressable[cc.ec]
THEN {
cc.ec ¬ C2CEmit.TakeAddr[cc.ec];
}
ELSE {
template: ROPE ¬ C2CStateUtils.DeclareVariable[temporaryDeclarations, unitSz];
preC: Code ¬ C2CEmit.Cat[template, AssCast[], cc.ec, ",\n"];
cc.ec ¬ C2CEmit.Cat[preC, " &", template];
cc.ec ¬ C2CEmit.ParentizeAndLn[cc.ec];
};
IF bits<unitSz THEN {
convert from right adjusted value mode to left adjusted getBitAddr mode
cc.xbc ¬ C2CCodeUtils.ConstI[unitSz-bits]; --allways positive
};
};
assBitAddr => {
--convert from right adjusted value mode to left adjusted getBitAddr mode
unitSz: INT ¬ C2CTarget.TemporaryBits[bits];
bitOff: INT ¬ unitSz-bits;
ac: C2CAddressing.AddressContainer ¬ GetAddrContainer[mode];
IF ~C2CEmit.GetAddressable[cc.ec] THEN {
template: ROPE ¬ C2CStateUtils.DeclareVariable[temporaryDeclarations, unitSz];
cc.sc ¬ C2CEmit.Cat[cc.sc, template, AssCast[], cc.ec, ";\n"];
cc.ec ¬ C2CEmit.IdentCode[template];
};
cc.sc ¬ C2CEmit.Cat[cc.sc, ac.words, " = ", C2CEmit.TakeAddr[cc.ec], "; "];
cc.sc ¬ C2CEmit.Cat[cc.sc, ac.bits, " = ", Convert.RopeFromInt[bitOff], ";\n"];
cc.ec ¬ NIL;
};
assUnits => {
cc.sc ¬ C2CEmit.Cat[cc.sc, CodeToAssUnits[cc.ec, mode]]; cc.ec ¬ NIL;
};
ENDCASE => NotYetImpl;
};
CodeToAssUnits: PUBLIC PROC [ec: Code, mode: Mode] RETURNS [sc: Code] = {
--ec expression code to be assigned to container stored with mode
--mode must have AssUnits addressing mode
--ec must have a size which allows simple assignment
template: ROPE ¬ GetTemplate[mode];
am: C2CAddressing.AddressMode ¬ GetAMode[mode];
csz: INT ¬ ContainerSize[mode];
IF am#assUnits OR csz<=0 THEN CantHappen;
IF csz<=C2CTarget.bitsPerWord THEN {
ec ¬ C2CEmit.PreventCastingToWord[ec];
ec ¬ C2CEmit.MinPrecedence[ec, unaryPrecedence];
ec ¬ C2CEmit.Cat[" (", C2CTypes.DefineType[csz], ") ", ec];
ec ¬ C2CEmit.SetPrecedence[ec, unaryPrecedence];
};
ec ¬ C2CEmit.MinPrecedence[ec, assignPrecedence];
sc ¬ C2CEmit.Cat[template, " = ", ec, ";\n"];
};
END.