Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2622.mcz ==================== Summary ==================== Name: VMMaker.oscog-eem.2622 Author: eem Time: 19 December 2019, 1:44:05.748389 pm UUID: b40ebe82-e2bc-4c28-9358-2ffd69ef6acd Ancestors: VMMaker.oscog-eem.2621 Cogit: ARMv8: Resolve the confusion with CmpR: TempReg R: SPReg. The ARMv8 code was backwards. Indeed it can support CmpR: TempReg R: SPReg. Hence simplify compileStackOverflowCheck: and nuke hasCmpRSPReg. ARMv5 Cogit: Get the stop insruction (BKPT) correct. Cogit Tests: Add a better way of running execution tests, adding CogitForTests as a stripped down compiler for simle instruction sequences. Exemplify (and verify the correctness of compares on ARMv8) by adding AbstractInstructionTests>>runCmpRRJumpCond:on:. All other executio tests will be rewritten in the style soon... But for now commit the sngle functional example. Revise the various CogXXXCompilerForTests>>concretizeAt: to observe the new covention for assigning machineCodeSize with the result of concretizeAt:, not assighning within concretizeAt:. Simulation: Refactor providing the current insruction and register state on an illegal address lookup so that it can also be used by CogProcessorAlien>>reportPrimitiveFailure. =============== Diff against VMMaker.oscog-eem.2621 =============== Item was added: + ----- Method: AbstractInstructionTests>>isaName (in category 'accessing') ----- + isaName + self subclassResponsibility! Item was added: + ----- Method: AbstractInstructionTests>>runCmpRRJumpCond:on: (in category 'running') ----- + runCmpRRJumpCond: assertPrintBar on: aStream + "Compile and evaluate as many combinations of CmpR;R: JumpCond: as possible, checking that they produce the + expected result. Answer an array of the number of comparisons and the number of them that succeeded." + "self defaultTester runCmpRRJumpCond: false" + | cogit nTests nGood | + VMClass initializationOptions at: #ISA put: self isaName. + cogit := CogitForTests new. + nTests := nGood := 0. + self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do: + [:sreg :srgetter :srsetter| + self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do: + [:dreg :drgetter :drsetter| + (sreg ~= dreg "N.B. We do not expect the backEnd to provide CmpR: SPReg R: reg, only CmpR: reg R: SPReg" + and: [drgetter ~= #sp]) ifTrue: + [#( = ~= + > > >= >= + < < <= <=) + with: #(JumpZero: JumpNonZero: + JumpGreater: JumpAbove: JumpGreaterOrEqual: JumpAboveOrEqual: + JumpLess: JumpBelow: JumpLessOrEqual: JumpBelowOrEqual:) + do: [:comparison :instruction| | unsigned jmp instructions memory | + unsigned := (instruction includesSubstring: 'Above') + or: [instruction includesSubstring: 'Below']. + "(drgetter = #sp or: [srgetter = #sp]) ifTrue: [self halt]." + cogit resetGen. + cogit CmpR: dreg R: sreg. + jmp := cogit perform: instruction with: 0. + cogit + MoveCq: 0 R: cogit backEnd cResultRegister; + Jump: 1536. + jmp jmpTarget: (cogit MoveCq: 1 R: cogit backEnd cResultRegister). + cogit Jump: 1536. + instructions := cogit generatedMachineCodeAt: 1024. "Avoid any guard page effects in the simulators, i.e. Gdb's ARM32 requires pc >= 16" + "self processor disassembleFrom: 1024 to: instructions size - 1 in: instructions" + (memory := ByteArray new: 2048) replaceFrom: 1 to: instructions size with: instructions startingAt: 1. + cogit stopsFrom: instructions size to: memory size - 1 in: memory. + "self processor disassembleFrom: 1024 to: instructions size - 1024 * 2 + 1024 in: memory ''" + self pairs: { "-1 << 30. -1 << 16." -1 << 8. 0. 1 << 8. "1 << 16. 1 << 30" } do: + [:a :b| | bogus error expected nInsts | + nTests := nTests + 1. + error := false. + nInsts := 0. + self processor + reset; + pc: 1024; + perform: srsetter with: (processor convertIntegerToInternal: a); + perform: drsetter with: (processor convertIntegerToInternal: b). + [[processor pc ~= 1536 and: [nInsts < 16]] whileTrue: + [processor singleStepIn: memory. nInsts := nInsts + 1]] + on: Error + do: [:ex| error := true]. + nInsts >= 16 ifTrue: [error := true]. + "self processor printRegistersOn: Transcript. + Transcript show: (self processor disassembleInstructionAt: 0 In: memory); cr" + bogus := (processor pc = 1536 and: [#[0 1] includes: processor cResultRegister]) not. + assertPrintBar ifTrue: [self deny: bogus]. + expected := unsigned + ifTrue: [(a bitAnd: 1 << 32 - 1) perform: comparison with: (b bitAnd: 1 << 32 - 1)] + ifFalse: [a perform: comparison with: b]. + (bogus or: [error or: [self processor cResultRegister = 1 ~= expected]]) ifFalse: [nGood := nGood + 1]. + assertPrintBar + ifTrue: [self assert: self processor cResultRegister = 1 equals: expected] + ifFalse: + [self processor cResultRegister = 1 ~= expected ifTrue: + [aStream nextPutAll: srgetter; space; nextPutAll: comparison; space; nextPutAll: drgetter. + unsigned ifTrue: [aStream nextPutAll: ' (unsigned)']. + aStream nextPutAll: (error ifTrue: [' ERRORED'] ifFalse: [' is incorrect']); cr; flush. + bogus ifTrue: + [self processor printRegistersOn: aStream. + aStream nextPutAll: (self processor disassembleInstructionAt: 0 In: memory); cr; flush]]]]]]]]. + assertPrintBar ifFalse: + [aStream print: nTests; nextPutAll: ' tests; '; print: nGood; nextPutAll: ' good'; cr]. + ^{nTests. nGood}! Item was changed: ----- Method: AbstractInstructionTests>>runSubRR: (in category 'running') ----- runSubRR: assertPrintBar "self defaultTester runSubRR: false" self concreteCompilerClass dataRegistersWithAccessorsDo: [:sreg :srgetter :srsetter| self concreteCompilerClass dataRegistersWithAccessorsDo: [:dreg :drgetter :drsetter| | inst len memory | inst := self gen: SubRR operand: sreg operand: dreg. len := inst concretizeAt: 0. memory := self memoryAsBytes: inst machineCode. + self pairs: (-2 to: 2) do: - self pairs: (-2 to: 2) do: [:a :b| | bogus | self processor reset; perform: srsetter with: (processor convertIntegerToInternal: a); perform: drsetter with: (processor convertIntegerToInternal: b). [[processor pc < len] whileTrue: [self processor singleStepIn: memory]] on: Error do: [:ex| ]. "self processor printRegistersOn: Transcript. Transcript show: (self processor disassembleInstructionAt: 0 In: memory); cr" assertPrintBar ifTrue: [self assert: processor pc = inst machineCodeSize] ifFalse: [bogus := processor pc ~= inst machineCodeSize]. self concreteCompilerClass dataRegistersWithAccessorsDo: [:ireg :getter :setter| | expected | expected := drgetter == srgetter ifTrue: [0] ifFalse: [getter == drgetter ifTrue: [b - a] ifFalse: [getter = srgetter ifTrue: [a] ifFalse: [0]]]. assertPrintBar ifTrue: [self assert: (self processor convertInternalToInteger: (self processor perform: getter)) equals: expected] ifFalse: [(self processor convertInternalToInteger: (self processor perform: getter)) ~= expected ifTrue: [bogus := true]]]. assertPrintBar ifFalse: [Transcript nextPutAll: drgetter; nextPut: $(; print: b; nextPutAll: ') - '; nextPutAll: srgetter; nextPut: $(; print: a; nextPutAll: ') = '; print: (self processor convertInternalToInteger: (self processor perform: drgetter)); cr; flush. bogus ifTrue: [self processor printRegistersOn: Transcript. Transcript show: (self processor disassembleInstructionAt: 0 In: memory); cr]]]]]! Item was added: + ----- Method: AbstractInstructionTests>>sanityCheckRegisterEnumerator (in category 'private') ----- + sanityCheckRegisterEnumerator + ^String streamContents: + [:s| + self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do: + [:regNum :getter :setter| + s print: regNum; nextPutAll: ': '; nextPutAll: getter; space; nextPutAll: setter; cr]] + + "self subclasses collect: [:class| class -> class new sanityCheckRegisterEnumerator]"! Item was changed: ----- Method: CogARMCompiler>>stop (in category 'encoding') ----- stop + "Encode a BKPT ( - ARM_ARM v7 DDI10406 pp. A8-56) instruction. We could, given a good enough creative impulse and an over-active sense of humour, add some numerically encoded witticism to this instruction in bits 8-19 & 0-3. It has no effect on the execution but can be a way to specify which breakpoint has been hit etc." - "generate a BKPT ( - ARM_ARM v7 DDI10406 pp. A8-56) instruction. We could, given a good enough creative impulse and an over-active sense of humour, add some numerically encoded witticism to this instruction in bits 8-19 & 0-3. It has no effect on the execution but can be a way to specify which breakpoint has been hit etc." <inline: true> + ^AL << 28 bitOr: (16r12 << 20 bitOr: (7 << 4))! - ^AL << 28 bitOr: (16r42 << 20 bitOr: (7 << 4))! Item was added: + ----- Method: CogARMCompilerForTests class>>dataRegistersWithAccessorsGiven:do: (in category 'test support') ----- + dataRegistersWithAccessorsGiven: aProcessorSimulator do: aTrinaryBlock + "r0 ... sp. We can't use pc or RISCTempReg, because some opcodes may be encoded as multiple instructions and this, we need to be able to step." + (0 to: 14) withIndexDo: + [:reg :i| + (self isRISCTempRegister: reg) ifFalse: + [aTrinaryBlock + value: reg + value: (aProcessorSimulator registerStateGetters at: i) + value: (aProcessorSimulator registerStateSetters at: i)]]! Item was changed: ----- Method: CogARMCompilerForTests>>concretizeAt: (in category 'generate machine code') ----- concretizeAt: actualAddress "Override to check maxSize and machineCodeSize" + | size | - | result | maxSize ifNil: [maxSize := self computeMaximumSize]. + size := super concretizeAt: actualAddress. - result := super concretizeAt: actualAddress. self assert: (maxSize notNil and: [self isPCDependent + ifTrue: [maxSize >= size] + ifFalse: [maxSize = size]]). + ^size! - ifTrue: [maxSize >= machineCodeSize] - ifFalse: [maxSize = machineCodeSize]]). - ^result! Item was added: + ----- Method: CogARMCompilerTests>>isaName (in category 'accessing') ----- + isaName + ^#ARMv5! Item was changed: ----- Method: CogAbstractInstruction class>>isRISCTempRegister: (in category 'testing') ----- isRISCTempRegister: reg + "For tests to filter-out bogus values left in the RISCTempRegister, if any. + N.B. DO NOT USE ABSTRACT REGISTER NAMES SUCH AS RISCTempReg IN IMPLEMENTING THIS!!!!" - "For tests to filter-out bogus values left in the RISCTempRegister, if any." ^self subclassResponsibility! Item was removed: - ----- Method: CogAbstractInstruction>>hasCmpRSPReg (in category 'testing') ----- - hasCmpRSPReg - "Answer if the receiver can do CmpR: anyRegExceptSP R: SPReg. - If the answer is false the Cogit assumes that the receiver can do CmpR: SPReg R: anyRegExceptSP. - The back end has to do one or the other, by hook or by crook." - ^true! Item was added: + ----- Method: CogIA32CompilerForTests class>>dataRegistersWithAccessorsGiven:do: (in category 'accessing') ----- + dataRegistersWithAccessorsGiven: aProcessorSimulator do: aTrinaryBlock + (0 to: 7) withIndexDo: + [:reg :i| + aTrinaryBlock + value: reg + value: (aProcessorSimulator registerStateGetters at: i) + value: (aProcessorSimulator registerStateSetters at: i)]! Item was changed: ----- Method: CogIA32CompilerForTests>>concretizeAt: (in category 'generate machine code') ----- concretizeAt: actualAddress "Override to check maxSize and machineCodeSize" + | size | - | result | maxSize ifNil: [maxSize := self computeMaximumSize]. + size := super concretizeAt: actualAddress. - result := super concretizeAt: actualAddress. self assert: (maxSize notNil and: [self isPCDependent + ifTrue: [maxSize >= size] + ifFalse: [maxSize = size]]). + ^size! - ifTrue: [maxSize >= machineCodeSize] - ifFalse: [maxSize = machineCodeSize]]). - ^result! Item was added: + ----- Method: CogIA32CompilerTests>>isaName (in category 'accessing') ----- + isaName + ^#IA32! Item was changed: ----- Method: CogInLineLiteralsX64Compiler class>>isRISCTempRegister: (in category 'testing') ----- isRISCTempRegister: reg "For tests to filter-out bogus values left in the RISCTempRegister, if any." + ^reg = R8 or: [reg = R11]! - ^reg = RISCTempReg! Item was changed: + ----- Method: CogMIPSELCompilerForTests class>>dataRegistersWithAccessorsDo: (in category 'testing') ----- - ----- Method: CogMIPSELCompilerForTests class>>dataRegistersWithAccessorsDo: (in category 'as yet unclassified') ----- dataRegistersWithAccessorsDo: aTrinaryBlock #((16 s0 s0:) (17 s1 s1:) (18 s2 s2:) (19 s3 s3:) (20 s4 s4:) (21 s5 s5:) (22 s6 s6:) (29 sp sp:) (30 fp fp:) (31 ra ra:)) do: [:triple | aTrinaryBlock valueWithArguments: triple].! Item was added: + ----- Method: CogMIPSELCompilerForTests class>>dataRegistersWithAccessorsGiven:do: (in category 'testing') ----- + dataRegistersWithAccessorsGiven: aProcessorSimulator do: aTrinaryBlock + "We can't use RISCTempReg et al, because some opcodes may be encoded as multiple instructions using RISCTempReg." + (0 to: 31) withIndexDo: + [:reg :i| + (reg = 0 or: [self isRISCTempRegister: reg]) ifFalse: + [aTrinaryBlock + value: reg + value: (aProcessorSimulator registerStateGetters at: i) + value: (aProcessorSimulator registerStateSetters at: i)]]! Item was changed: + ----- Method: CogMIPSELCompilerForTests class>>isRISCTempRegister: (in category 'testing') ----- - ----- Method: CogMIPSELCompilerForTests class>>isRISCTempRegister: (in category 'as yet unclassified') ----- isRISCTempRegister: reg "For tests to filter-out bogus values left in the RISCTempRegister, if any." ^reg = AT or: [reg = Cmp or: [reg = Overflow or: [reg = BranchTemp]]]! Item was added: + ----- Method: CogMIPSELCompilerTests>>isaName (in category 'accessing') ----- + isaName + ^#MIPSEL! Item was changed: ----- Method: CogRTLOpcodes class>>initialize (in category 'class initialization') ----- (excessive size, no diff calculated) Item was added: + ----- Method: CogX64CompilerForTests class>>dataRegistersWithAccessorsGiven:do: (in category 'accessing') ----- + dataRegistersWithAccessorsGiven: aProcessorSimulator do: aTrinaryBlock + "We can't use RISCTempReg, because some opcodes may be encoded as multiple instructions using RISCTempReg." + (0 to: 15)withIndexDo: + [:reg :i| + (self isRISCTempRegister: reg) ifFalse: + [aTrinaryBlock + value: reg + value: (aProcessorSimulator registerStateGetters at: i) + value: (aProcessorSimulator registerStateSetters at: i)]]! Item was changed: ----- Method: CogX64CompilerForTests>>concretizeAt: (in category 'generate machine code') ----- concretizeAt: actualAddress "Override to check maxSize and machineCodeSize" + | size | - | result | maxSize ifNil: [maxSize := self computeMaximumSize]. + size := super concretizeAt: actualAddress. - result := super concretizeAt: actualAddress. self assert: (maxSize notNil and: [self isPCDependent + ifTrue: [maxSize >= size] + ifFalse: [maxSize = size]]). + ^size! - ifTrue: [maxSize >= machineCodeSize] - ifFalse: [maxSize = machineCodeSize]]). - ^result! Item was added: + ----- Method: CogX64CompilerTests>>isaName (in category 'accessing') ----- + isaName + ^#X64! Item was changed: ----- Method: Cogit>>CmpR:R: (in category 'abstract instructions') ----- CmpR: reg1 R: reg2 <inline: true> <returnTypeC: #'AbstractInstruction *'> + self deny: reg1 = SPReg. "See comment in CogRTLOpcodes class initialize" ^self gen: CmpRR operand: reg1 operand: reg2! Item was changed: ----- Method: Cogit>>compileStackOverflowCheck: (in category 'compile abstract instructions') ----- compileStackOverflowCheck: canContextSwitch "Compile the compare of stackLimit against the stack pointer, jumping to the stackOverflowCall if the stack pointer is below the limit. Answer a bytecode annotated label that follows the sequence. The stack check functions both as a genuine stack limit check to prevent calls overflowing stack pages, and as an event/context-switch break out. To cause an event check (including a check for a required context switch), stackLimit is set to the highest possible value, and hence all stack limit checks will fail. A path in the stack overflow abort then arranges to call event checking if it has been requested. Certain block activations (e.g. valueNoContextSwitch:) must not context switch, and in that case, SendNumArgs is set to zero to communicate to the stack overflow abort that it should + not perform event/context-switch (yet)." - not perform event/context-switch (yet). - A further complication is that certain back ends (currently ARMv8) can only do - CmpR: SPReg R: TempReg and not CmpR: TempReg R: SPReg" - | jumpSkip label | <inline: false> self MoveAw: coInterpreter stackLimitAddress R: TempReg. + "N.B. We do not expect the backEnd to provide CmpR: SPReg R: reg, only CmpR: reg R: SPReg" + self CmpR: TempReg R: SPReg. "N.B. FLAGS := SPReg - TempReg" + "If we can't context switch for this method, use a slightly + slower overflow check that clears SendNumArgsReg." + canContextSwitch - backEnd hasCmpRSPReg ifTrue: + [self JumpBelow: stackOverflowCall. + label := self Label] - [self CmpR: TempReg R: SPReg. "N.B. FLAGS := SPReg - TempReg" - "If we can't context switch for this method, use a slightly - slower overflow check that clears SendNumArgsReg." - canContextSwitch - ifTrue: - [self JumpBelow: stackOverflowCall. - label := self Label] - ifFalse: - [jumpSkip := self JumpAboveOrEqual: 0. - self MoveCq: 0 R: SendNumArgsReg. - self Jump: stackOverflowCall. - jumpSkip jmpTarget: (label := self Label)]] ifFalse: + [jumpSkip := self JumpAboveOrEqual: 0. + self MoveCq: 0 R: SendNumArgsReg. + self Jump: stackOverflowCall. + jumpSkip jmpTarget: (label := self Label)]. - [self CmpR: SPReg R: TempReg. "N.B. FLAGS := TempReg - SPReg" - "If we can't context switch for this method, use a slightly - slower overflow check that clears SendNumArgsReg." - canContextSwitch - ifTrue: - [self JumpAboveOrEqual: stackOverflowCall. - label := self Label] - ifFalse: - [jumpSkip := self JumpBelow: 0. - self MoveCq: 0 R: SendNumArgsReg. - self Jump: stackOverflowCall. - jumpSkip jmpTarget: (label := self Label)]]. self annotateBytecode: label. ^label! Item was changed: ----- Method: Cogit>>errorProcessingSimulationTrap:in: (in category 'simulation processor access') ----- errorProcessingSimulationTrap: aProcessorSimulationTrap in: aDictionary + self provideContextForCurrentInstruction. - printRegisters ifFalse: - [processor printRegistersOn: coInterpreter transcript]. - printInstructions ifFalse: - [self disassembleFrom: processor pc to: processor pc]. ^aDictionary errorKeyNotFound: aProcessorSimulationTrap address! Item was added: + ----- Method: Cogit>>provideContextForCurrentInstruction (in category 'simulation processor access') ----- + provideContextForCurrentInstruction + printRegisters ifFalse: + [processor printRegistersOn: coInterpreter transcript]. + printInstructions ifFalse: + [self disassembleFrom: processor pc to: processor pc]! Item was added: + Cogit subclass: #CogitForTests + instanceVariableNames: 'codeBytes' + classVariableNames: '' + poolDictionaries: '' + category: 'VMMaker-Tests'! Item was added: + ----- Method: CogitForTests>>byteAt:put: (in category 'accessing-memory') ----- + byteAt: zeroRelativeIndex put: aByte + ^codeBytes at: zeroRelativeIndex + 1 put: aByte! Item was added: + ----- Method: CogitForTests>>bytecodeFixupClass (in category 'accessing') ----- + bytecodeFixupClass + ^CogBytecodeFixup! Item was added: + ----- Method: CogitForTests>>coInterpreter (in category 'accessing') ----- + coInterpreter + ^self! Item was added: + ----- Method: CogitForTests>>generatedMachineCodeAt: (in category 'generate machine code') ----- + generatedMachineCodeAt: startAddress + | codeSize | + self computeMaximumSizes. + codeSize := self generateInstructionsAt: startAddress. + codeBytes := ByteArray new: startAddress + codeSize. + backEnd stopsFrom: 0 to: startAddress - 1. + self outputInstructionsAt: startAddress. + ^codeBytes! Item was added: + ----- Method: CogitForTests>>initialize (in category 'initialization') ----- + initialize + "Ugh, this needs fixing!!!!" + CogCompilerClass := nil. + self class initializeMiscConstants. + objectMemory := self. + backEnd := CogCompilerClass for: self. + methodLabel := CogCompilerClass for: self. + (literalsManager := backEnd class literalsManagerClass new) cogit: self. + debugOpcodeIndices := #(). + self initializeBackend. + self allocateOpcodes: 64 bytecodes: 64. + self resetGen! Item was added: + ----- Method: CogitForTests>>long32At:put: (in category 'accessing-memory') ----- + long32At: zeroRelativeIndex put: word + ^codeBytes unsignedLongAt: zeroRelativeIndex + 1 put: word! Item was added: + ----- Method: CogitForTests>>long64At:put: (in category 'accessing-memory') ----- + long64At: zeroRelativeIndex put: aByte + ^codeBytes unsignedLong64At: zeroRelativeIndex + 1 put: aByte! Item was added: + ----- Method: CogitForTests>>longAt:put: (in category 'accessing-memory') ----- + longAt: zeroRelativeByteIndex put: aWord + ^codeBytes integerAt: zeroRelativeByteIndex + 1 put: aWord size: backEnd class wordSize signed: false! Item was added: + ----- Method: CogitForTests>>lookupAddress: (in category 'accessing') ----- + lookupAddress: address + ^nil! Item was added: + ----- Method: CogitForTests>>resetGen (in category 'testing') ----- + resetGen + opcodeIndex := 0. + literalsManager resetLiterals! Item was added: + ----- Method: CogitForTests>>stopsFrom:to: (in category 'accessing-memory') ----- + stopsFrom: start to: stop + backEnd stopsFrom: start to: stop! Item was added: + ----- Method: CogitForTests>>stopsFrom:to:in: (in category 'accessing-memory') ----- + stopsFrom: start to: stop in: aByteArray + | save | + save := codeBytes. + codeBytes := aByteArray. + [backEnd stopsFrom: start to: stop] + ensure: [codeBytes := save]! Item was added: + ----- Method: CogitForTests>>wordSize (in category 'accessing') ----- + wordSize + ^backEnd class wordSize! |
Free forum by Nabble | Edit this page |