// BTRN1.bcpl - BCPL Compiler -- Trans, Part 1. // Copyright Xerox Corporation 1980 // Last modified on Sun 29 Oct 72 0438.48 by jec. // last modified by Butterfield, January 25, 1979 3:19 PM // - Trans, ignore END - 1/25/79 // Trans Translate a piece of AE-Tree into OCODE. get "btrnx" // Declarations for Trans. let Trans(x) be [ if x eq 0 return let lab = 0 // For RESULTIS, DOCASE switchon H1!x into [ case LET: TransLET(x) return case EXT: case MANIFEST: case STATIC: case STRUCTURE: [ let S = SSP let SB = SwitchBlock SwitchBlock = false Trans(H2!x) unless S eq SSP do TRNreport(-1) SwitchBlock = SB return ] case LINE: Curline = H2!x if SWList do [ if SWOcode do WW($*n); WriteLine(Curline) ] test FrameLevel eq 0 then Out2(LINE, Curline) or Out2(PLINE, Curline) Trans(H3!x) return case END: Trans(H3!x) return case ASS: unless Assign(H2!x, H3!x) eq 0 do TRNreport(3) // Expression list too short. return case RTAP: Transcall(x) return case GOTO: Load(H2!x) Out1(GOTO) SSP = SSP - 1 return case COLON: Complentry(H5!x, H4!x) Out2(STACK, SSP) Trans(H3!x) return case IF: case UNLESS: [ let L = Nextparam() Jumpcond(H2!x, H1!x eq UNLESS, L) Trans(H3!x) Complab(L) return ] case TEST: [ let L, M = Nextparam(), Nextparam() Jumpcond(H2!x, false, L) Trans(H3!x) Compjump(M) Complab(L) Trans(H4!x) Complab(M) return ] case BREAK: unless RepeatBlock do TRNreport(4) if Breaklabel eq 0 do Breaklabel = Nextparam() Compjump(Breaklabel) return case LOOP: unless RepeatBlock do TRNreport(4) if Looplabel eq 0 do Looplabel = Nextparam() Compjump(Looplabel) return case RETURN: unless RoutineBody do TRNreport(5) Out1(RTRN) return case FINISH: case ABORT: Out1(H1!x) return case DOCASE: // Same action as RESULTIS, jump to different place unless Endcaselabel do [ TRNreport(6); return ] // out of context unless Docaselabel do Docaselabel = Nextparam() lab = Docaselabel case RESULTIS: unless lab do lab = Resultlabel Load(H2!x) unless lab do TRNreport(5) // Occurs for RESULTIS only. Out2P(RES, lab) SSP = SSP - 1 return case WHILE: case UNTIL: [ let L = Nextparam() // Label for the beginning of the block, to jump back to. let LL, BL = Looplabel, Breaklabel and RB = RepeatBlock RepeatBlock = true // break and loop are now legal. Looplabel = Nextparam() Breaklabel = 0 Compjump(Looplabel) // Jump to the test. Complab(L) Trans(H3!x) Complab(Looplabel) Jumpcond(H2!x, H1!x eq WHILE, L) unless Breaklabel eq 0 do [ Complab(Breaklabel); Out2(STACK, SSP) ] Breaklabel, Looplabel = BL, LL RepeatBlock = RB return ] case REPEAT: case REPEATWHILE: case REPEATUNTIL: [ let L = Nextparam() // Label for the beginning of the block. let LL, BL = Looplabel, Breaklabel and RB = RepeatBlock RepeatBlock = true Breaklabel = 0 Looplabel = H1!x eq REPEAT ? L, 0 Complab(L) Trans(H2!x) test H1!x eq REPEAT ifso Compjump(L) ifnot [ unless Looplabel eq 0 do Complab(Looplabel) Jumpcond(H3!x, H1!x eq REPEATWHILE, L) ] unless Breaklabel eq 0 do [ Complab(Breaklabel); Out2(STACK, SSP) ] Looplabel, Breaklabel = LL, BL RepeatBlock = RB return ] case CASE: [ unless SwitchBlock do TRNreport(7) if CaseP + CaseN > CaseT do [ TRNreport(8); return ] // Too many cases. let L = Nextparam() // The label for this piece of code. Casetable!CaseP = GetConst(H2+x) // The case constant. Casetable!(CaseP+1) = L Casetable!(CaseP+2) = H4!x // The line number. CaseP = CaseP + CaseN Complab(L) // Place the label. Trans(H3!x) return ] case CASETO: // Case label with limits. [ unless SwitchBlock do TRNreport(7) // Must be in a switch block. let M = Nextparam() // The label the cases refer to. let L, U = GetConst(H2+x), GetConst(H3+x) // The limits. let N = U - L + 1 // Number of cases to generate. unless N > 0 do [ TRNreport(12); return ] // Oops. unless CaseP + CaseN*N le CaseT do [ TRNreport(8); return ] for k = 0 to N-1 do // Place the cases. [ Casetable! CaseP = L + k // The value. Casetable!(CaseP+1) = M // The label. Casetable!(CaseP+2) = H5!x // The line number. CaseP = CaseP + CaseN ] Complab(M) // Place the label. Trans(H4!x) return ] case DEFAULT: unless SwitchBlock do TRNreport(7) // Not in a switch block. unless Defaultlabel eq 0 do TRNreport(10) // default used twice. Defaultlabel = Nextparam() Complab(Defaultlabel) Trans(H2!x) return case ENDCASE: if Endcaselabel eq 0 do [ TRNreport(6); return ] // Not in a switch block. Compjump(Endcaselabel) return case SWITCHON: Transswitch(x) return case FOR: [ let LL, BL = Looplabel, Breaklabel and RB, SB = RepeatBlock, SwitchBlock Looplabel, Breaklabel = 0, 0 RepeatBlock, SwitchBlock = true, false let L = Nextparam() // Label for the test. and M = Nextparam() // Label for the body. let S1 = SSP // The stack position into which the controlled variable goes. let d = H2!x; H2!d = S1 // Declare the controlled variable Load(H3!x) // Load the lower limit into the stack. Out1(NEWLOCAL); OutL(H1!d & NameMask) let Stepsize = H5!x eq 0 ? 1, GetConst(H5+x) // The increment. let S2 = SSP // The stack position for the upper limit. and Limit = nil // The value of the upper limit, if it is a constant. Limit = CheckConst(H4+x) // Optimize the upper limit. test Limit > 0 // Is its value known at compile time? ifso S2, Limit = -1, rv Limit // Yes, so set S2 < 0 as a switch. ifnot [ Load(H4!x) // No, so load it into stack position S2. Out1(NEWLOCAL); OutL(0) ] Out1(STORE) Compjump(L) // Jump to the test. Complab(M) // The label for the body. Trans(H6!x) // ... unless Looplabel eq 0 do Complab(Looplabel) Out2(LP, S1); OutL(d!0 & NameMask) // Load the controlled variable. Out2(LN, Stepsize); OutL(0) Out1(PLUS) Out2(SP, S1); OutL(d!0 & NameMask) // Add the step size and store back. Complab(L) // Label the test. Out2(LP, S1); OutL(d!0 & NameMask) // Load the controlled variable. test S2 > 0 ifso Out2(LP, S2) ifnot Out2(LN, Limit); OutL(0) Out1(Stepsize > 0 ? LE, GE); Out2P(JT, M) // The appropriate test. unless Breaklabel eq 0 do Complab(Breaklabel) SSP = S1 // Put it back. Out2(STACK, SSP) Breaklabel, Looplabel = BL, LL RepeatBlock, SwitchBlock = RB, SB return ] case SEQ: Trans(H2!x) Trans(H3!x) return ///*DCS* conditional compilation case COMPILETEST: Trans(H2!x) return default: TRNreport(-2) // Error report. ] ]