1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-20 23:30:43 +00:00

Ensured we do not coalesce across segments.

This commit is contained in:
jespergravgaard 2023-04-23 23:25:28 +02:00
parent 606ea29132
commit 11c86793d3
4 changed files with 77 additions and 25 deletions

View File

@ -583,30 +583,30 @@ public class Pass4CodeGeneration {
if (registerMainMem.getAddress() == null) {
// Generate into the data segment
// Set segment
// // We check first the bank of the variable. Only local variables can be stored in the bank.
// // Parameters must be stored in main memory.
// if(!variable.getDataSegment().equals(Scope.SEGMENT_DATA_DEFAULT)) {
// if(scope instanceof Procedure) {
// Procedure procedure = (Procedure) scope;
// List<Variable> parameters = procedure.getParameters();
// if (variable.isKindPhiVersion()) {
// Variable master = variable.getPhiMaster();
// if (master != null) {
// if (parameters.contains(master) || master.getLocalName().equals("return")) {
// variable.setDataSegment(Scope.SEGMENT_DATA_DEFAULT);
// }
// }
// }
// }
// }
//
// // Intermediate variables are placed at the banked data segment, but parameters and return values are kept untouched.
// if (variable.isKindIntermediate()) {
// if (scope instanceof Procedure) {
// Procedure procedure = (Procedure) scope;
// variable.setDataSegment(procedure.getSegmentData());
// }
// }
// We check first the bank of the variable. Only local variables can be stored in the bank.
// Parameters must be stored in main memory.
if(!variable.getDataSegment().equals(Scope.SEGMENT_DATA_DEFAULT)) {
if(scope instanceof Procedure) {
Procedure procedure = (Procedure) scope;
List<Variable> parameters = procedure.getParameters();
if (variable.isKindPhiVersion()) {
Variable master = variable.getPhiMaster();
if (master != null) {
if (parameters.contains(master) || master.getLocalName().equals("return")) {
variable.setDataSegment(Scope.SEGMENT_DATA_DEFAULT);
}
}
}
}
}
// Intermediate variables are placed at the banked data segment, but parameters and return values are kept untouched.
if (variable.isKindIntermediate()) {
if (scope instanceof Procedure) {
Procedure procedure = (Procedure) scope;
variable.setDataSegment(procedure.getSegmentData());
}
}
setCurrentSegment(variable.getDataSegment(), asm);
// Add any comments
generateComments(asm, variable.getComments());
@ -925,7 +925,7 @@ public class Pass4CodeGeneration {
if(Bank.CallingDistance.NEAR.equals(callingDistance)) {
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program);
} else {
throw new CompileError("Call procedure not supported in banked mode " + toProcedure.toString(program));
throw new CompileError("Stack Call procedure not supported in banked mode " + toProcedure.toString(program));
}
RValue procedureRVal = call.getProcedureRVal();
if (!(procedureRVal instanceof ProcedureRef)) {

View File

@ -53,6 +53,7 @@ public abstract class Pass4MemoryCoalesce extends Pass2Base {
return
canCoalesceNotEqual(ec1, ec2) &&
canCoalesceCompatible(ec1, ec2, program) &&
canCoalesceSegments(ec1, ec2, program) &&
canCoalesceVolatile(ec1, ec2, program) &&
canCoalesceThreads(ec1, ec2, threadHeads, program) &&
canCoalesceClobber(ec1, ec2, unknownFragments, program);
@ -69,6 +70,21 @@ public abstract class Pass4MemoryCoalesce extends Pass2Base {
return !ec1.equals(ec2);
}
/**
* Determines if two live range equivalence classes are candidates for coalescing by ensuring they are not from different data segments.
* @param ec1 One equivalence class
* @param ec2 Another equivalence class
* @param program The program
* @return True if the two equivalence classes can be coalesced into one without problems.
*/
private static boolean canCoalesceSegments(LiveRangeEquivalenceClass ec1, LiveRangeEquivalenceClass ec2, Program program) {
final VariableRef variableRef1 = ec1.getVariables().get(0);
final String dataSegment1 = program.getScope().getVar(variableRef1).getDataSegment();
final VariableRef variableRef2 = ec2.getVariables().get(0);
final String dataSegment2 = program.getScope().getVar(variableRef2).getDataSegment();
return dataSegment1.equals(dataSegment2);
}
/**
* Determines if two live range equivalence classes can be coalesced without cross-thread clobber.
* This is possible if they are both only called from the same thread head.

View File

@ -1581,6 +1581,12 @@ public class TestProgramsFast extends TestPrograms {
compileAndCompare("call-banked-phi-case-6-close-1.c");
}
@Test
public void testBankedPhiMemvars() throws IOException {
compileAndCompare("call-banked-phi-memvars.c", log());
}
@Test
public void testBankedStackCase2Close0() throws IOException {
assertError("call-banked-stack-case-2-close-0.c", "Stack Call procedure not supported in banked mode");

View File

@ -0,0 +1,30 @@
/**
* Test banked calls with memory variables.
* The parameters & return should end up in the shared/common bank.
*/
#pragma link("call-banked-phi.ld")
#pragma var_model(mem)
int* const SCREEN = (int*)0x0400;
#pragma code_seg(Code)
#pragma nobank
void main(void) {
for(char i=0;i<5; i++) {
SCREEN[i] = plus(100, (int)i);
SCREEN[10+i] = plus(200, (int)i);
}
}
#pragma code_seg(RAM_Bank1)
#pragma data_seg(RAM_Bank1)
#pragma bank(cx16_ram, 1)
int plus(int a, int b) {
int r = 2;
r += a;
r += b;
r += a;
r += b;
return r;
}