m68k: pin @shared variables to static storage

This commit is contained in:
Irmen de Jong committed 2026-10-08 04:17:40 +02:00
1 parent 9c9552174e
commit 0189903a63
20 files changed
+143 -37

No files matched your search

@@ -818,7 +818,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
val offset = eltSize * constIndex
addInstr(result, IRInstructions.binaryImmediate(Opcode.ADD, IRDataType.POINTER, pointerReg, offset), null)
} else {
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, true, targetArray.splitWords)
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, true)
result += code
if(eltSize!=1)
result += codeGen.multiplyByConst(DataType.UWORD, indexReg, eltSize)
@@ -830,7 +830,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
val offset = eltSize * constIndex
addInstr(result, IRInstructions.binaryImmediate(Opcode.ADD, IRDataType.POINTER, pointerReg, offset), null)
} else {
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, true, targetArray.splitWords)
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, true)
result += code
if(eltSize!=1)
result += codeGen.multiplyByConst(DataType.UWORD, indexReg, eltSize)
@@ -864,7 +864,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
}
result += chunk
} else {
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, codeGen.wordArrayIndex, targetArray.splitWords)
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, codeGen.wordArrayIndex)
result += code
val scaleZX = if(targetArray.splitWords) 1 else eltSize
result += IRCodeChunk(null, null).also {
@@ -885,7 +885,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
}
result += chunk
} else {
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, codeGen.wordArrayIndex, targetArray.splitWords)
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, codeGen.wordArrayIndex)
result += code
result += IRCodeChunk(null, null).also {
it += IRInstructions.storeMemory(Opcode.STOREX, targetDt, valueFpRegister, IRMemory.indexed(variable, indexReg, codeGen.options.compTarget.indexRegType, scale=eltSize))
@@ -906,7 +906,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
}
result += chunk
} else {
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, codeGen.wordArrayIndex, targetArray.splitWords)
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, codeGen.wordArrayIndex)
result += code
result += IRCodeChunk(null, null).also {
if(targetArray.splitWords) {
@@ -954,7 +954,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
}
} else {
// index is an expression
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, true, targetArray.splitWords)
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, true)
result += code
if(eltSize!=1)
result += codeGen.multiplyByConst(DataType.UWORD, indexReg, eltSize)
@@ -3062,7 +3062,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
private fun tryFoldStructArrayDirectWrite(addressExpr: PtExpression, zero: Boolean, valueReg: Int, targetDt: IRDataType, result: MutableList<IRCodeChunkBase>): Boolean {
val info = extractStructArrayIndexInfo(addressExpr, codeGen) ?: return false
val (idxCode, indexReg) = codeGen.loadIndexReg(info.idxExpr, info.structSize, codeGen.wordArrayIndex, false)
val (idxCode, indexReg) = codeGen.loadIndexReg(info.idxExpr, codeGen.wordArrayIndex)
result += idxCode
if(zero) {
result += IRCodeChunk(null, null).also {
@@ -876,7 +876,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
if(offset > 0)
addInstr(result, IRInstructions.binaryImmediate(Opcode.ADD, IRDataType.POINTER, pointerTr.resultReg, offset), null)
} else {
val (code, indexWordReg) = codeGen.loadIndexReg(target.index, eltSize, true, false)
val (code, indexWordReg) = codeGen.loadIndexReg(target.index, true)
result += code
if(eltSize!=1)
result += codeGen.multiplyByConst(DataType.UWORD, indexWordReg, eltSize)
@@ -946,7 +946,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
it += IRInstructions.storeZero(Opcode.STOREZX, IRDataType.BYTE, IRMemory.indexed(targetVariable.name, offsetReg, codeGen.options.compTarget.indexRegType))
}
} else {
val (code, indexReg) = codeGen.loadIndexReg(target.index, eltSize, codeGen.wordArrayIndex, false)
val (code, indexReg) = codeGen.loadIndexReg(target.index, codeGen.wordArrayIndex)
result += code
result += IRCodeChunk(null, null).also {
val offset = byteOffset(eltSize)
@@ -964,7 +964,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
it += IRInstructions.storeMemory(Opcode.STOREX, IRDataType.BYTE, valueTr.resultReg, IRMemory.indexed(targetVariable.name, offsetReg, codeGen.options.compTarget.indexRegType))
}
} else {
val (code, indexReg) = codeGen.loadIndexReg(target.index, eltSize, codeGen.wordArrayIndex, false)
val (code, indexReg) = codeGen.loadIndexReg(target.index, codeGen.wordArrayIndex)
result += code
result += IRCodeChunk(null, null).also {
val offset = byteOffset(eltSize)
@@ -985,7 +985,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val info = extractStructArrayIndexInfo(call.args[0], codeGen) ?: return null
val isZero = codeGen.isZero(call.args[1])
val result = mutableListOf<IRCodeChunkBase>()
val (idxCode, indexReg) = codeGen.loadIndexReg(info.idxExpr, info.structSize, codeGen.wordArrayIndex, false)
val (idxCode, indexReg) = codeGen.loadIndexReg(info.idxExpr, codeGen.wordArrayIndex)
result += idxCode
return if(isZero) {
result += IRCodeChunk(null, null).also {
@@ -645,7 +645,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
fun indexByExpression() {
val (code, indexReg) = codeGen.loadIndexReg(arrayIx.index, eltSize, codeGen.wordArrayIndex, arrayIx.splitWords)
val (code, indexReg) = codeGen.loadIndexReg(arrayIx.index, codeGen.wordArrayIndex)
result += code
val scale = if(arrayIx.splitWords) 1 else eltSize
if(vmDt==IRDataType.FLOAT) {
@@ -681,7 +681,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addInstr(result, IRInstructions.binaryImmediate(Opcode.ADD, IRDataType.POINTER, pointerReg, memOffset), null)
}
else {
val (code, indexWordReg) = codeGen.loadIndexReg(index, eltSize, true, false)
val (code, indexWordReg) = codeGen.loadIndexReg(index, true)
result += code
if(eltSize!=1)
result += codeGen.multiplyByConst(DataType.UWORD, indexWordReg, eltSize)
@@ -1895,7 +1895,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} else if(left.variable!!.type.isArray) {
// variable index: fold to single LOADX with scale=structSize, disp=fieldOffset
// only for known array symbols (not generic pointer derefs)
val (chunks, indexReg) = codeGen.loadIndexReg(left.index, struct.size.toInt(), codeGen.wordArrayIndex, false)
val (chunks, indexReg) = codeGen.loadIndexReg(left.index, codeGen.wordArrayIndex)
result += chunks
if (fieldVmDt == IRDataType.FLOAT) {
val fpReg = codeGen.registers.next(IRDataType.FLOAT)
@@ -1911,7 +1911,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val pointerTr = translateExpression(left.variable!!)
result += pointerTr.chunks
pointerReg = pointerTr.resultReg
val (chunks, indexReg) = codeGen.loadIndexReg(left.index, struct.size.toInt(), true, false)
val (chunks, indexReg) = codeGen.loadIndexReg(left.index, true)
result += chunks
if(struct.size.toInt()!=1)
result += codeGen.multiplyByConst(DataType.UWORD, indexReg, struct.size.toInt())
@@ -168,7 +168,7 @@ class IRCodeGen(
replacements += IRStStaticVariable(
variable.name, variable.dt, null, variable.length,
variable.zpwish, variable.align, variable.dirty,
variable.inBss, variable.readonly
variable.inBss, variable.readonly, variable.shared
)
}
is IRVariableInitializer.Str, is IRVariableInitializer.Array -> {
@@ -274,7 +274,8 @@ class IRCodeGen(
variable.align,
variable.dirty,
variable.inBss,
variable.readonly
variable.readonly,
variable.shared
)
irProg.st.add(clearedVar)
@@ -2218,7 +2219,7 @@ class IRCodeGen(
}
}
internal fun loadIndexReg(index: PtExpression, itemsize: Int, wordIndex: Boolean, arrayIsSplitWords: Boolean): Pair<IRCodeChunks, Int> {
internal fun loadIndexReg(index: PtExpression, wordIndex: Boolean): Pair<IRCodeChunks, Int> {
// returns the code to load the Index into the register, which is also returned.
// The returned register is always canonicalized to the expected index width
// (WORD on 32-bit targets, BYTE on 8-bit) so that LOADX/STOREX/STOREZX never
@@ -78,7 +78,7 @@ private class StToIrConverter(val romable: Boolean) {
val hasInit = initValue != null
val inBss = !hasInit || romable
val readonly = romable && hasInit
return IRStStaticVariable(name, variable.dt, initValue, variable.length, variable.zpwish, variable.align, variable.dirty, inBss, readonly)
return IRStStaticVariable(name, variable.dt, initValue, variable.length, variable.zpwish, variable.align, variable.dirty, inBss, readonly, variable.shared)
}
fun convert(variable: StMemVar): IRStMemVar {
@@ -389,7 +389,7 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
/** outcome of the frameability decision for one subroutine */
private sealed interface Frameability {
class Frameable(val layout: FrameLayoutResult) : Frameability
class NotFrameable(val reason: String) : Frameability
class NotFrameable() : Frameability
}
private fun frameableSubroutine(
@@ -403,7 +403,7 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
reentrant: Set<String>,
reachesFramePointerClobber: Map<String, ClobberReach>
): Frameability {
val static = { reason: String -> Frameability.NotFrameable(reason) }
val static = { reason: String -> Frameability.NotFrameable() }
// a %option noframe subroutine requires the legacy static convention (it manipulates
// the machine stack itself), so it never gets a frame
if (sub.noframe) return static("it is marked %option noframe")
@@ -1090,6 +1090,7 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
/** returns why the variable cannot be moved into a frame, or null when it can */
private fun frameableVariableProblem(v: IRStStaticVariable, name: String, addressTaken: Set<String>, asmTexts: List<String>, asmAllowed: Boolean = false): String? {
if (v.shared) return "it is marked @shared" // @shared guarantees a stable, externally visible address
if (name in addressTaken) return "its address is taken"
if (!asmAllowed && isLabelReferencedInAsm(name, asmTexts)) return "inline assembly refers to it"
if (v.initializationValue != null && v.initializationValue !is IRVariableInitializer.Numeric) return "it has a static initializer"
@@ -278,7 +278,7 @@ private fun PtVariable.prefixVariableOrThis(parent: PtNode, st: SymbolTable): Pt
else -> throw AssemblyError("weird array value element $elt")
}
}
val result = PtVariable(name, type, isSplitWordArray, zeropage, align, dirty, newValue, arraySize, position)
val result = PtVariable(name, type, isSplitWordArray, zeropage, align, dirty, newValue, arraySize, position, shared)
result.parent = parent
result
}