mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-14 10:37:36 +00:00
Fixed word constructor detection to detect all inline word constructors.
This commit is contained in:
parent
212e8572de
commit
4a7dd31d40
@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
|
||||
/** A {@link ValueReplacer} that replaces symbols with their alias. */
|
||||
@ -83,7 +84,7 @@ public class AliasReplacer implements ValueReplacer.Replacer {
|
||||
* @param replaceable The replaceable value
|
||||
*/
|
||||
@Override
|
||||
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ControlFlowBlock currentBlock) {
|
||||
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
if (replaceable.get() != null) {
|
||||
RValue replacement = getReplacement(replaceable.get(), aliases);
|
||||
if (replacement != null) {
|
||||
|
@ -15,62 +15,28 @@ public class Pass1ExtractInlineStrings extends Pass1Base {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, currentBlock) -> {
|
||||
ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> {
|
||||
String nameHint = null;
|
||||
if(currentStmt instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) currentStmt;
|
||||
List<RValue> parameters = call.getParameters();
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
for(int i = 0; i < parameters.size(); i++) {
|
||||
RValue parameter = parameters.get(i);
|
||||
if(parameter.equals(replaceable.get())) {
|
||||
// The replaceable value is the parameter - use the parameter name as name hint
|
||||
Procedure procedure = getProgram().getScope().getProcedure(call.getProcedure());
|
||||
Procedure procedure = Pass1ExtractInlineStrings.this.getProgram().getScope().getProcedure(call.getProcedure());
|
||||
nameHint = procedure.getParameterNames().get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Scope blockScope = getProgram().getScope().getScope(currentBlock.getScope());
|
||||
Scope blockScope = Pass1ExtractInlineStrings.this.getProgram().getScope().getScope(currentBlock.getScope());
|
||||
RValue value = replaceable.get();
|
||||
if(value instanceof ConstantString) {
|
||||
ConstantVar strConst = createStringConstantVar(blockScope, (ConstantString) replaceable.get(), nameHint);
|
||||
ConstantVar strConst = Pass1ExtractInlineStrings.this.createStringConstantVar(blockScope, (ConstantString) replaceable.get(), nameHint);
|
||||
replaceable.set(strConst.getRef());
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
for (ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
|
||||
Scope blockScope = getProgram().getScope().getScope(block.getScope());
|
||||
while (stmtIt.hasNext()) {
|
||||
Statement statement = stmtIt.next();
|
||||
if (statement instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) statement;
|
||||
Procedure procedure = getProgram().getScope().getProcedure(call.getProcedure());
|
||||
List<RValue> parameters = call.getParameters();
|
||||
int size = parameters.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String parameterName = procedure.getParameterNames().get(i);
|
||||
execute(new ValueReplacer.ReplaceableCallParameter(call, i), blockScope, parameterName);
|
||||
}
|
||||
} else if (statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(assignment.getrValue1()==null && assignment.getOperator()==null && assignment.getrValue2() instanceof ConstantString) {
|
||||
// This will be picked up later as a constant - the temporary constant variable is not needed
|
||||
continue;
|
||||
}
|
||||
if(assignment.getrValue1() instanceof ConstantString && assignment.getrValue2() instanceof ConstantString) {
|
||||
// This will be picked up later as a constant - the temporary constant variable is not needed
|
||||
continue;
|
||||
}
|
||||
execute(new ValueReplacer.ReplaceableRValue1(assignment), blockScope, null);
|
||||
execute(new ValueReplacer.ReplaceableRValue2(assignment), blockScope, null);
|
||||
} else if (statement instanceof StatementReturn) {
|
||||
execute(new ValueReplacer.ReplaceableReturn((StatementReturn) statement), blockScope, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@ package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* Identifies word constructors <code>{ b1, b2 }</code> and replaces
|
||||
* them with a binary operator <code>word w = b1 w= b2 ;</code>
|
||||
@ -14,35 +16,54 @@ public class Pass2FixWordConstructors extends Pass2SsaOptimization{
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
boolean optimized = false;
|
||||
ProgramScope programScope = getProgram().getScope();
|
||||
for (ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
if (statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(assignment.getrValue1()==null && assignment.getOperator()==null) {
|
||||
if(assignment.getrValue2() instanceof ValueList) {
|
||||
ValueList list = (ValueList) assignment.getrValue2();
|
||||
if(list.getList().size()==2) {
|
||||
// We have a simple assignment of a length 2 value list to a variable
|
||||
SymbolType lType = SymbolTypeInference.inferType(programScope, assignment.getlValue());
|
||||
SymbolType elmType1 = SymbolTypeInference.inferType(programScope, list.getList().get(0));
|
||||
SymbolType elmType2 = SymbolTypeInference.inferType(programScope, list.getList().get(1));
|
||||
if(SymbolType.isWord(lType) && SymbolType.isByte(elmType1) && SymbolType.isByte(elmType2)) {
|
||||
// Types are word = { byte, byte } - perform the modification
|
||||
assignment.setrValue1(list.getList().get(0));
|
||||
assignment.setOperator(Operator.WORD);
|
||||
assignment.setrValue2(list.getList().get(1));
|
||||
getLog().append("Fixing word constructor with " + assignment.toString());
|
||||
optimized = true;
|
||||
final boolean[] optimized = {false};
|
||||
|
||||
ValueReplacer.executeAll(getGraph(), new ValueReplacer.Replacer() {
|
||||
@Override
|
||||
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
RValue rValue = replaceable.get();
|
||||
if(rValue instanceof ValueList) {
|
||||
ValueList list = (ValueList) rValue;
|
||||
if(list.getList().size() == 2) {
|
||||
// We have a simple assignment of a length 2 value list to a variable
|
||||
SymbolType elmType1 = SymbolTypeInference.inferType(Pass2FixWordConstructors.this.getScope(), list.getList().get(0));
|
||||
SymbolType elmType2 = SymbolTypeInference.inferType(Pass2FixWordConstructors.this.getScope(), list.getList().get(1));
|
||||
if(SymbolType.isByte(elmType1) && SymbolType.isByte(elmType2)) {
|
||||
// We have a 2-element list { byte, byte }
|
||||
|
||||
// Check if we are assigning into a declared byte array
|
||||
if(currentStmt instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) currentStmt;
|
||||
if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2().equals(rValue)) {
|
||||
SymbolType lType = SymbolTypeInference.inferType(Pass2FixWordConstructors.this.getScope(), assignment.getlValue());
|
||||
if(lType instanceof SymbolTypeArray && SymbolType.isByte(((SymbolTypeArray) lType).getElementType())) {
|
||||
// We are assigning into a declared byte array - do not convert!
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert list to a word constructor in a new tmp variable
|
||||
Scope currentScope = getScope().getScope(currentBlock.getScope());
|
||||
VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
|
||||
tmpVar.setTypeInferred(SymbolType.WORD);
|
||||
// Move backward - to insert before the current statement
|
||||
stmtIt.previous();
|
||||
// Add assignment of the new tmpVar
|
||||
StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), list.getList().get(0), Operator.WORD, list.getList().get(1));
|
||||
stmtIt.add(assignment);
|
||||
// Move back before the current statement
|
||||
stmtIt.next();
|
||||
// Replace current value with the reference
|
||||
replaceable.set(tmpVar.getRef());
|
||||
Pass2FixWordConstructors.this.getLog().append("Fixing word constructor with " + assignment.toString());
|
||||
optimized[0] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return optimized;
|
||||
});
|
||||
return optimized[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* A replacer capable to alias all usages of a variable (or constant var) with a suitable replacement
|
||||
@ -15,10 +16,11 @@ public class ValueReplacer {
|
||||
/**
|
||||
* Execute replacement of a replaceable value.
|
||||
* @param replaceable The replaceable value
|
||||
* @param currentStmt The current statement that the value is a part of
|
||||
* @param currentStmt The statement iterator - just past the current statement that the value is a part of. Current statment can be retrieved by calling
|
||||
* @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block.
|
||||
* @param currentBlock The current block that the value is a part of
|
||||
*/
|
||||
void execute(ReplaceableValue replaceable, Statement currentStmt, ControlFlowBlock currentBlock);
|
||||
void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -29,31 +31,33 @@ public class ValueReplacer {
|
||||
*/
|
||||
public static void executeAll(ControlFlowGraph graph, Replacer replacer) {
|
||||
for (ControlFlowBlock block : graph.getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
|
||||
while(statementsIt.hasNext()) {
|
||||
Statement statement = statementsIt.next();
|
||||
if (statement instanceof StatementAssignment) {
|
||||
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, block);
|
||||
executeAll(new ReplaceableRValue1((StatementAssignment) statement), replacer, statement, block);
|
||||
executeAll(new ReplaceableRValue2((StatementAssignment) statement), replacer, statement, block);
|
||||
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
|
||||
executeAll(new ReplaceableRValue1((StatementAssignment) statement), replacer, statement, statementsIt, block);
|
||||
executeAll(new ReplaceableRValue2((StatementAssignment) statement), replacer, statement,statementsIt, block);
|
||||
} else if (statement instanceof StatementCall) {
|
||||
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, block);
|
||||
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
|
||||
StatementCall call = (StatementCall) statement;
|
||||
if (call.getParameters() != null) {
|
||||
int size = call.getParameters().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
executeAll(new ReplaceableCallParameter(call, i), replacer, statement, block);
|
||||
executeAll(new ReplaceableCallParameter(call, i), replacer, statement, statementsIt, block);
|
||||
}
|
||||
}
|
||||
} else if (statement instanceof StatementConditionalJump) {
|
||||
executeAll(new ReplaceableCondRValue1((StatementConditionalJump) statement), replacer, statement, block);
|
||||
executeAll(new ReplaceableCondRValue2((StatementConditionalJump) statement), replacer, statement, block);
|
||||
executeAll(new ReplaceableCondRValue1((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
|
||||
executeAll(new ReplaceableCondRValue2((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
|
||||
} else if (statement instanceof StatementReturn) {
|
||||
executeAll(new ReplaceableReturn((StatementReturn) statement), replacer, statement, block);
|
||||
executeAll(new ReplaceableReturn((StatementReturn) statement), replacer, statement, statementsIt, block);
|
||||
} else if (statement instanceof StatementPhiBlock) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||
executeAll(new ReplaceablePhiVariable(phiVariable), replacer, statement, block);
|
||||
executeAll(new ReplaceablePhiVariable(phiVariable), replacer, statement, statementsIt, block);
|
||||
int size = phiVariable.getValues().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
executeAll(new ReplaceablePhiValue(phiVariable, i), replacer, statement, block);
|
||||
executeAll(new ReplaceablePhiValue(phiVariable, i), replacer, statement, statementsIt, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,10 +70,10 @@ public class ValueReplacer {
|
||||
* @param replaceable The replaceable value
|
||||
* @param replacer The value replacer
|
||||
*/
|
||||
public static void executeAll(ReplaceableValue replaceable, Replacer replacer, Statement currentStmt, ControlFlowBlock currentBlock ) {
|
||||
replacer.execute(replaceable, currentStmt, currentBlock);
|
||||
public static void executeAll(ReplaceableValue replaceable, Replacer replacer, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock ) {
|
||||
replacer.execute(replaceable, currentStmt, stmtIt, currentBlock);
|
||||
for (ReplaceableValue subValue : replaceable.getSubValues()) {
|
||||
executeAll(subValue, replacer, currentStmt, currentBlock);
|
||||
executeAll(subValue, replacer, currentStmt, stmtIt, currentBlock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10067,8 +10067,8 @@ Multiple usages for variable. Not optimizing sub-constant (byte) init_plot_table
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) init_plot_tables::y#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) init_plot_tables::y#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte*) init_plot_tables::yoffs#2
|
||||
Fixing word constructor with plot::plotter_x#0 ← *(plot_xhi#0 + plot::x#4) w= *(plot_xlo#0 + plot::x#4)
|
||||
Fixing word constructor with plot::plotter_y#0 ← *(plot_yhi#0 + plot::y#4) w= *(plot_ylo#0 + plot::y#4)
|
||||
Fixing word constructor with plot::$2 ← *(plot_xhi#0 + plot::x#4) w= *(plot_xlo#0 + plot::x#4)
|
||||
Fixing word constructor with plot::$3 ← *(plot_yhi#0 + plot::y#4) w= *(plot_ylo#0 + plot::y#4)
|
||||
Succesful SSA optimization Pass2FixWordConstructors
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
@ -10346,8 +10346,10 @@ line_ydxd::@return: scope:[line_ydxd] from line_ydxd::@2
|
||||
plot: scope:[plot] from line_xdyd::@1 line_xdyi::@1 line_ydxd::@1 line_ydxi::@1
|
||||
(byte) plot::y#4 ← phi( line_xdyd::@1/(byte) plot::y#1 line_xdyi::@1/(byte) plot::y#0 line_ydxd::@1/(byte) plot::y#3 line_ydxi::@1/(byte) plot::y#2 )
|
||||
(byte) plot::x#4 ← phi( line_xdyd::@1/(byte) plot::x#1 line_xdyi::@1/(byte) plot::x#0 line_ydxd::@1/(byte) plot::x#3 line_ydxi::@1/(byte) plot::x#2 )
|
||||
(word) plot::plotter_x#0 ← *((const byte*) plot_xhi#0 + (byte) plot::x#4) w= *((const byte*) plot_xlo#0 + (byte) plot::x#4)
|
||||
(word) plot::plotter_y#0 ← *((const byte*) plot_yhi#0 + (byte) plot::y#4) w= *((const byte*) plot_ylo#0 + (byte) plot::y#4)
|
||||
(word~) plot::$2 ← *((const byte*) plot_xhi#0 + (byte) plot::x#4) w= *((const byte*) plot_xlo#0 + (byte) plot::x#4)
|
||||
(word) plot::plotter_x#0 ← (word~) plot::$2
|
||||
(word~) plot::$3 ← *((const byte*) plot_yhi#0 + (byte) plot::y#4) w= *((const byte*) plot_ylo#0 + (byte) plot::y#4)
|
||||
(word) plot::plotter_y#0 ← (word~) plot::$3
|
||||
(word~) plot::$0 ← (word) plot::plotter_x#0 + (word) plot::plotter_y#0
|
||||
(byte*) plot::plotter#0 ← ((byte*)) (word~) plot::$0
|
||||
(byte~) plot::$1 ← *((byte*) plot::plotter#0) | *((const byte*) plot_bit#0 + (byte) plot::x#4)
|
||||
@ -10703,8 +10705,10 @@ line_ydxd::@return: scope:[line_ydxd] from line_ydxd::@2
|
||||
plot: scope:[plot] from line_xdyd::@1 line_xdyi::@1 line_ydxd::@1 line_ydxi::@1
|
||||
(byte) plot::y#4 ← phi( line_xdyd::@1/(byte) plot::y#1 line_xdyi::@1/(byte) plot::y#0 line_ydxd::@1/(byte) plot::y#3 line_ydxi::@1/(byte) plot::y#2 )
|
||||
(byte) plot::x#4 ← phi( line_xdyd::@1/(byte) plot::x#1 line_xdyi::@1/(byte) plot::x#0 line_ydxd::@1/(byte) plot::x#3 line_ydxi::@1/(byte) plot::x#2 )
|
||||
(word) plot::plotter_x#0 ← *((const byte*) plot_xhi#0 + (byte) plot::x#4) w= *((const byte*) plot_xlo#0 + (byte) plot::x#4)
|
||||
(word) plot::plotter_y#0 ← *((const byte*) plot_yhi#0 + (byte) plot::y#4) w= *((const byte*) plot_ylo#0 + (byte) plot::y#4)
|
||||
(word~) plot::$2 ← *((const byte*) plot_xhi#0 + (byte) plot::x#4) w= *((const byte*) plot_xlo#0 + (byte) plot::x#4)
|
||||
(word) plot::plotter_x#0 ← (word~) plot::$2
|
||||
(word~) plot::$3 ← *((const byte*) plot_yhi#0 + (byte) plot::y#4) w= *((const byte*) plot_ylo#0 + (byte) plot::y#4)
|
||||
(word) plot::plotter_y#0 ← (word~) plot::$3
|
||||
(word~) plot::$0 ← (word) plot::plotter_x#0 + (word) plot::plotter_y#0
|
||||
(byte*) plot::plotter#0 ← ((byte*)) (word~) plot::$0
|
||||
(byte~) plot::$1 ← *((byte*) plot::plotter#0) | *((const byte*) plot_bit#0 + (byte) plot::x#4)
|
||||
@ -10849,6 +10853,8 @@ Not aliassing across scopes: plot::y#3 line_ydxd::y#3
|
||||
Not aliassing across scopes: plot::x#4 plot::x#1
|
||||
Not aliassing across scopes: plot::y#4 plot::y#1
|
||||
Alias (byte) lines::l#2 = (byte/word~) lines::$0 (byte/word~) lines::$1
|
||||
Alias (word) plot::plotter_x#0 = (word~) plot::$2
|
||||
Alias (word) plot::plotter_y#0 = (word~) plot::$3
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
|
@ -678,9 +678,41 @@ main::@return: scope:[main] from main::@3
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Fixing word constructor with main::w#0 ← *(main::his#2 + main::h#4) w= main::l#2
|
||||
Fixing word constructor with main::$8 ← *(main::his#2 + main::h#4) w= main::l#2
|
||||
Succesful SSA optimization Pass2FixWordConstructors
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
main: scope:[main] from @1
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
(byte) main::h#4 ← phi( main/(const byte) main::h#0 main::@3/(byte) main::h#1 )
|
||||
(byte[]) main::his#2 ← phi( main/(const byte[]) main::his#0 main::@3/(byte[]) main::his#2 )
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@2
|
||||
(byte) main::l#2 ← phi( main::@1/(const byte) main::l#0 main::@2/(byte) main::l#1 )
|
||||
(word~) main::$8 ← *((byte[]) main::his#2 + (byte) main::h#4) w= (byte) main::l#2
|
||||
(word) main::w#0 ← (word~) main::$8
|
||||
(byte*) main::sc#0 ← ((byte*)) (word) main::w#0
|
||||
*((byte*) main::sc#0) ← (byte) '*'
|
||||
(byte) main::l#1 ← ++ (byte) main::l#2
|
||||
if((byte) main::l#1!=(byte/signed byte/word/signed word) 8) goto main::@2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
(byte) main::h#1 ← ++ (byte) main::h#4
|
||||
if((byte) main::h#1!=(byte/signed byte/word/signed word) 3) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main param-assignment
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Alias (word) main::w#0 = (word~) main::$8
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
main: scope:[main] from @1
|
||||
|
@ -4225,7 +4225,7 @@ main::@return: scope:[main] from main::@16
|
||||
to:@end
|
||||
@end: scope:[] from @35
|
||||
|
||||
Fixing word constructor with getFAC::return#0 ← *(memHi#0) w= *(memLo#0)
|
||||
Fixing word constructor with getFAC::$0 ← *(memHi#0) w= *(memLo#0)
|
||||
Succesful SSA optimization Pass2FixWordConstructors
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
@ -4306,7 +4306,8 @@ setFAC::@return: scope:[setFAC] from setFAC::@1
|
||||
to:@return
|
||||
getFAC: scope:[getFAC] from main::@13
|
||||
asm { jsr$b1aasty$festa$ff }
|
||||
(word) getFAC::return#0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
|
||||
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
|
||||
(word) getFAC::return#0 ← (word~) getFAC::$0
|
||||
to:getFAC::@return
|
||||
getFAC::@return: scope:[getFAC] from getFAC
|
||||
return
|
||||
@ -4435,6 +4436,208 @@ Culled Empty Block (label) main::@5
|
||||
Culled Empty Block (label) @35
|
||||
Succesful SSA optimization Pass2CullEmptyBlocks
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
to:@34
|
||||
print_ln: scope:[print_ln] from main::@15
|
||||
to:print_ln::@1
|
||||
print_ln::@1: scope:[print_ln] from print_ln print_ln::@1
|
||||
(byte*) line_cursor#6 ← phi( print_ln/(byte*) line_cursor#13 print_ln::@1/(byte*) line_cursor#1 )
|
||||
(byte*) line_cursor#1 ← (byte*) line_cursor#6 + (byte/signed byte/word/signed word) 40
|
||||
if((byte*) line_cursor#1<(byte*) char_cursor#10) goto print_ln::@1
|
||||
to:print_ln::@return
|
||||
print_ln::@return: scope:[print_ln] from print_ln::@1
|
||||
return
|
||||
to:@return
|
||||
print_word: scope:[print_word] from main::@14
|
||||
(byte) print_byte::b#0 ← > (word) print_word::w#0
|
||||
call print_byte param-assignment
|
||||
to:print_word::@1
|
||||
print_word::@1: scope:[print_word] from print_word
|
||||
(byte) print_byte::b#1 ← < (word) print_word::w#0
|
||||
call print_byte param-assignment
|
||||
to:print_word::@return
|
||||
print_word::@return: scope:[print_word] from print_word::@1
|
||||
return
|
||||
to:@return
|
||||
print_byte: scope:[print_byte] from print_word print_word::@1
|
||||
(byte*) char_cursor#31 ← phi( print_word/(byte*) char_cursor#32 print_word::@1/(byte*) char_cursor#10 )
|
||||
(byte) print_byte::b#2 ← phi( print_word/(byte) print_byte::b#0 print_word::@1/(byte) print_byte::b#1 )
|
||||
(byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (byte/signed byte/word/signed word) 4
|
||||
(byte) print_char::ch#0 ← *((const byte[]) print_byte::hextab#0 + (byte~) print_byte::$0)
|
||||
call print_char param-assignment
|
||||
to:print_byte::@1
|
||||
print_byte::@1: scope:[print_byte] from print_byte
|
||||
(byte~) print_byte::$2 ← (byte) print_byte::b#2 & (byte/signed byte/word/signed word) 15
|
||||
(byte) print_char::ch#1 ← *((const byte[]) print_byte::hextab#0 + (byte~) print_byte::$2)
|
||||
call print_char param-assignment
|
||||
to:print_byte::@return
|
||||
print_byte::@return: scope:[print_byte] from print_byte::@1
|
||||
return
|
||||
to:@return
|
||||
print_char: scope:[print_char] from print_byte print_byte::@1
|
||||
(byte*) char_cursor#23 ← phi( print_byte/(byte*) char_cursor#31 print_byte::@1/(byte*) char_cursor#10 )
|
||||
(byte) print_char::ch#2 ← phi( print_byte/(byte) print_char::ch#0 print_byte::@1/(byte) print_char::ch#1 )
|
||||
*((byte*) char_cursor#23) ← (byte) print_char::ch#2
|
||||
(byte*) char_cursor#10 ← ++ (byte*) char_cursor#23
|
||||
to:print_char::@return
|
||||
print_char::@return: scope:[print_char] from print_char
|
||||
return
|
||||
to:@return
|
||||
prepareMEM: scope:[prepareMEM] from addMEMtoFAC divMEMbyFAC mulFACbyMEM setFAC setMEMtoFAC
|
||||
(byte*) prepareMEM::mem#5 ← phi( addMEMtoFAC/(const byte[]) prepareMEM::mem#2 divMEMbyFAC/(const byte[]) prepareMEM::mem#3 mulFACbyMEM/(byte*) prepareMEM::mem#4 setFAC/(byte*) prepareMEM::mem#0 setMEMtoFAC/(byte*) prepareMEM::mem#1 )
|
||||
(byte~) prepareMEM::$0 ← < (byte*) prepareMEM::mem#5
|
||||
*((const byte*) memLo#0) ← (byte~) prepareMEM::$0
|
||||
(byte~) prepareMEM::$1 ← > (byte*) prepareMEM::mem#5
|
||||
*((const byte*) memHi#0) ← (byte~) prepareMEM::$1
|
||||
to:prepareMEM::@return
|
||||
prepareMEM::@return: scope:[prepareMEM] from prepareMEM
|
||||
return
|
||||
to:@return
|
||||
setFAC: scope:[setFAC] from main main::@1 main::@8
|
||||
(word) setFAC::w#3 ← phi( main/(const word) setFAC::w#0 main::@1/(word) setFAC::w#1 main::@8/(const word) setFAC::w#2 )
|
||||
(byte*) prepareMEM::mem#0 ← ((byte*)) (word) setFAC::w#3
|
||||
call prepareMEM param-assignment
|
||||
to:setFAC::@1
|
||||
setFAC::@1: scope:[setFAC] from setFAC
|
||||
asm { ldy$felda$ffjsr$b391 }
|
||||
to:setFAC::@return
|
||||
setFAC::@return: scope:[setFAC] from setFAC::@1
|
||||
return
|
||||
to:@return
|
||||
getFAC: scope:[getFAC] from main::@13
|
||||
asm { jsr$b1aasty$festa$ff }
|
||||
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
|
||||
(word) getFAC::return#0 ← (word~) getFAC::$0
|
||||
to:getFAC::@return
|
||||
getFAC::@return: scope:[getFAC] from getFAC
|
||||
return
|
||||
to:@return
|
||||
setMEMtoFAC: scope:[setMEMtoFAC] from main::@4 main::@7
|
||||
(byte*) setMEMtoFAC::mem#2 ← phi( main::@4/(const byte[]) setMEMtoFAC::mem#0 main::@7/(const byte[]) setMEMtoFAC::mem#1 )
|
||||
(byte*) prepareMEM::mem#1 ← (byte*) setMEMtoFAC::mem#2
|
||||
call prepareMEM param-assignment
|
||||
to:setMEMtoFAC::@1
|
||||
setMEMtoFAC::@1: scope:[setMEMtoFAC] from setMEMtoFAC
|
||||
asm { ldx$feldy$ffjsr$bbd4 }
|
||||
to:setMEMtoFAC::@return
|
||||
setMEMtoFAC::@return: scope:[setMEMtoFAC] from setMEMtoFAC::@1
|
||||
return
|
||||
to:@return
|
||||
addMEMtoFAC: scope:[addMEMtoFAC] from main::@12
|
||||
call prepareMEM param-assignment
|
||||
to:addMEMtoFAC::@1
|
||||
addMEMtoFAC::@1: scope:[addMEMtoFAC] from addMEMtoFAC
|
||||
asm { lda$feldy$ffjsr$b867 }
|
||||
to:addMEMtoFAC::@return
|
||||
addMEMtoFAC::@return: scope:[addMEMtoFAC] from addMEMtoFAC::@1
|
||||
return
|
||||
to:@return
|
||||
divMEMbyFAC: scope:[divMEMbyFAC] from main::@9
|
||||
call prepareMEM param-assignment
|
||||
to:divMEMbyFAC::@1
|
||||
divMEMbyFAC::@1: scope:[divMEMbyFAC] from divMEMbyFAC
|
||||
asm { lda$feldy$ffjsr$bb0f }
|
||||
to:divMEMbyFAC::@return
|
||||
divMEMbyFAC::@return: scope:[divMEMbyFAC] from divMEMbyFAC::@1
|
||||
return
|
||||
to:@return
|
||||
mulFACbyMEM: scope:[mulFACbyMEM] from main::@11 main::@6
|
||||
(byte*) mulFACbyMEM::mem#2 ← phi( main::@11/(const byte[]) mulFACbyMEM::mem#1 main::@6/(const byte*) mulFACbyMEM::mem#0 )
|
||||
(byte*) prepareMEM::mem#4 ← (byte*) mulFACbyMEM::mem#2
|
||||
call prepareMEM param-assignment
|
||||
to:mulFACbyMEM::@1
|
||||
mulFACbyMEM::@1: scope:[mulFACbyMEM] from mulFACbyMEM
|
||||
asm { lda$feldy$ffjsr$ba28 }
|
||||
to:mulFACbyMEM::@return
|
||||
mulFACbyMEM::@return: scope:[mulFACbyMEM] from mulFACbyMEM::@1
|
||||
return
|
||||
to:@return
|
||||
sinFAC: scope:[sinFAC] from main::@10
|
||||
asm { jsr$e26b }
|
||||
to:sinFAC::@return
|
||||
sinFAC::@return: scope:[sinFAC] from sinFAC
|
||||
return
|
||||
to:@return
|
||||
divFACby10: scope:[divFACby10] from main::@3
|
||||
asm { jsr$bafe }
|
||||
to:divFACby10::@return
|
||||
divFACby10::@return: scope:[divFACby10] from divFACby10
|
||||
return
|
||||
to:@return
|
||||
main: scope:[main] from @34
|
||||
call setFAC param-assignment
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main
|
||||
call divFACby10 param-assignment
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@3
|
||||
call setMEMtoFAC param-assignment
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main::@16 main::@4
|
||||
(byte*) line_cursor#13 ← phi( main::@16/(byte*) line_cursor#1 main::@4/(const byte*) char_cursor#0 )
|
||||
(byte*) char_cursor#32 ← phi( main::@16/(byte*) line_cursor#1 main::@4/(const byte*) char_cursor#0 )
|
||||
(byte) main::i#10 ← phi( main::@16/(byte) main::i#1 main::@4/(const byte) main::i#0 )
|
||||
(word) setFAC::w#1 ← ((word)) (byte) main::i#10
|
||||
call setFAC param-assignment
|
||||
to:main::@6
|
||||
main::@6: scope:[main] from main::@1
|
||||
call mulFACbyMEM param-assignment
|
||||
to:main::@7
|
||||
main::@7: scope:[main] from main::@6
|
||||
call setMEMtoFAC param-assignment
|
||||
to:main::@8
|
||||
main::@8: scope:[main] from main::@7
|
||||
call setFAC param-assignment
|
||||
to:main::@9
|
||||
main::@9: scope:[main] from main::@8
|
||||
call divMEMbyFAC param-assignment
|
||||
to:main::@10
|
||||
main::@10: scope:[main] from main::@9
|
||||
call sinFAC param-assignment
|
||||
to:main::@11
|
||||
main::@11: scope:[main] from main::@10
|
||||
call mulFACbyMEM param-assignment
|
||||
to:main::@12
|
||||
main::@12: scope:[main] from main::@11
|
||||
call addMEMtoFAC param-assignment
|
||||
to:main::@13
|
||||
main::@13: scope:[main] from main::@12
|
||||
call getFAC param-assignment
|
||||
(word) getFAC::return#2 ← (word) getFAC::return#0
|
||||
to:main::@14
|
||||
main::@14: scope:[main] from main::@13
|
||||
(word) print_word::w#0 ← (word) getFAC::return#2
|
||||
call print_word param-assignment
|
||||
to:main::@15
|
||||
main::@15: scope:[main] from main::@14
|
||||
call print_ln param-assignment
|
||||
to:main::@16
|
||||
main::@16: scope:[main] from main::@15
|
||||
(byte) main::i#1 ← ++ (byte) main::i#10
|
||||
if((byte) main::i#1!=(byte/signed byte/word/signed word) 26) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@16
|
||||
return
|
||||
to:@return
|
||||
@34: scope:[] from @begin
|
||||
call main param-assignment
|
||||
to:@end
|
||||
@end: scope:[] from @34
|
||||
|
||||
Not aliassing across scopes: line_cursor#6 line_cursor#13
|
||||
Not aliassing across scopes: print_byte::b#2 print_byte::b#0
|
||||
Not aliassing across scopes: char_cursor#31 char_cursor#32
|
||||
Not aliassing across scopes: print_char::ch#2 print_char::ch#0
|
||||
Not aliassing across scopes: char_cursor#23 char_cursor#31
|
||||
Not aliassing across scopes: prepareMEM::mem#1 setMEMtoFAC::mem#2
|
||||
Not aliassing across scopes: prepareMEM::mem#4 mulFACbyMEM::mem#2
|
||||
Not aliassing across scopes: char_cursor#32 line_cursor#1
|
||||
Not aliassing across scopes: line_cursor#13 line_cursor#1
|
||||
Not aliassing across scopes: getFAC::return#2 getFAC::return#0
|
||||
Not aliassing across scopes: print_word::w#0 getFAC::return#2
|
||||
Alias (word) getFAC::return#0 = (word~) getFAC::$0
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
to:@34
|
||||
print_ln: scope:[print_ln] from main::@15
|
||||
|
@ -12954,7 +12954,7 @@ Multiple usages for variable. Not optimizing sub-constant (byte) init::i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) place_sprites::spr_x#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte*) gen_sprites::spr#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte*) gen_chargen_sprite::sprite#4
|
||||
Fixing word constructor with getFAC::return#0 ← *(memHi#0) w= *(memLo#0)
|
||||
Fixing word constructor with getFAC::$0 ← *(memHi#0) w= *(memLo#0)
|
||||
Succesful SSA optimization Pass2FixWordConstructors
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
@ -12982,7 +12982,8 @@ setFAC::@return: scope:[setFAC] from setFAC::@1
|
||||
to:@return
|
||||
getFAC: scope:[getFAC] from gen_sintab::@21
|
||||
asm { jsr$b1aasty$festa$ff }
|
||||
(word) getFAC::return#0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
|
||||
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
|
||||
(word) getFAC::return#0 ← (word~) getFAC::$0
|
||||
to:getFAC::@return
|
||||
getFAC::@return: scope:[getFAC] from getFAC
|
||||
return
|
||||
@ -13444,7 +13445,8 @@ setFAC::@return: scope:[setFAC] from setFAC::@1
|
||||
to:@return
|
||||
getFAC: scope:[getFAC] from gen_sintab::@21
|
||||
asm { jsr$b1aasty$festa$ff }
|
||||
(word) getFAC::return#0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
|
||||
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
|
||||
(word) getFAC::return#0 ← (word~) getFAC::$0
|
||||
to:getFAC::@return
|
||||
getFAC::@return: scope:[getFAC] from getFAC
|
||||
return
|
||||
@ -13917,7 +13919,8 @@ setFAC::@return: scope:[setFAC] from setFAC::@1
|
||||
to:@return
|
||||
getFAC: scope:[getFAC] from gen_sintab::@21
|
||||
asm { jsr$b1aasty$festa$ff }
|
||||
(word) getFAC::return#0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
|
||||
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
|
||||
(word) getFAC::return#0 ← (word~) getFAC::$0
|
||||
to:getFAC::@return
|
||||
getFAC::@return: scope:[getFAC] from getFAC
|
||||
return
|
||||
@ -14353,6 +14356,7 @@ Not aliassing across scopes: gen_chargen_sprite::sprite#11 gen_chargen_sprite::s
|
||||
Not aliassing across scopes: progress_cursor#34 progress_cursor#22
|
||||
Not aliassing across scopes: getFAC::return#2 getFAC::return#0
|
||||
Not aliassing across scopes: gen_sintab::$23 getFAC::return#2
|
||||
Alias (word) getFAC::return#0 = (word~) getFAC::$0
|
||||
Alias (byte) init::i#2 = (byte/word~) init::$1
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
|
@ -0,0 +1,26 @@
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
jsr main
|
||||
main: {
|
||||
.const b = 4
|
||||
.const pos = $501
|
||||
.const bgcol = $d021
|
||||
.const w = b*$100+0
|
||||
.const w2 = 1*$100+1+w+0*$100+0
|
||||
.const sc = w2
|
||||
lda bs+1
|
||||
sta sc
|
||||
lda pos
|
||||
cmp #'m'
|
||||
bne b1
|
||||
lda #5
|
||||
sta bgcol
|
||||
breturn:
|
||||
rts
|
||||
b1:
|
||||
lda #2
|
||||
sta bgcol
|
||||
jmp breturn
|
||||
bs: .byte 'c', 'm'
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi() [ ] ( )
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi() [ ] ( )
|
||||
[2] call main param-assignment [ ] ( )
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi() [ ] ( )
|
||||
main: scope:[main] from @1
|
||||
[4] *((const byte*) main::sc#0) ← *((const byte[]) main::bs#0+(byte/signed byte/word/signed word) 1) [ ] ( main:2 [ ] )
|
||||
[5] if(*((const byte*) main::pos#0)!=(byte) 'm') goto main::@1 [ ] ( main:2 [ ] )
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main
|
||||
[6] *((const byte*) main::bgcol#0) ← (byte/signed byte/word/signed word) 5 [ ] ( main:2 [ ] )
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1 main::@3
|
||||
[7] return [ ] ( main:2 [ ] )
|
||||
to:@return
|
||||
main::@1: scope:[main] from main
|
||||
[8] *((const byte*) main::bgcol#0) ← (byte/signed byte/word/signed word) 2 [ ] ( main:2 [ ] )
|
||||
to:main::@return
|
1019
src/main/java/dk/camelot64/kickc/test/ref/true-inline-words.log
Normal file
1019
src/main/java/dk/camelot64/kickc/test/ref/true-inline-words.log
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@3
|
||||
(label) main::@return
|
||||
(byte) main::b
|
||||
(const byte) main::b#0 b = (byte/signed byte/word/signed word) 4
|
||||
(byte*) main::bgcol
|
||||
(const byte*) main::bgcol#0 bgcol = ((byte*))(word) 53281
|
||||
(byte[]) main::bs
|
||||
(const byte[]) main::bs#0 bs = { (byte) 'c', (byte) 'm' }
|
||||
(byte*) main::pos
|
||||
(const byte*) main::pos#0 pos = ((byte*))(word/signed word) 1281
|
||||
(byte*) main::sc
|
||||
(const byte*) main::sc#0 sc = ((byte*))(const word) main::w2#0
|
||||
(word) main::w
|
||||
(const word) main::w#0 w = (const byte) main::b#0*(word/signed word) 256+(byte/signed byte/word/signed word) 0
|
||||
(word) main::w2
|
||||
(const word) main::w2#0 w2 = (byte/signed byte/word/signed word) 1*(word/signed word) 256+(byte/signed byte/word/signed word) 1+(const word) main::w#0+(byte/signed byte/word/signed word) 0*(word/signed word) 256+(byte/signed byte/word/signed word) 0
|
||||
|
@ -1,10 +1,19 @@
|
||||
|
||||
void main() {
|
||||
byte[] bs = { 'c', 'm' }; // constant byte array
|
||||
byte b = 4; // constant byte
|
||||
word w = { b, 0 }; // constant inline word
|
||||
word w2 = { 1, 1 } + w; // constant inline word inside expression
|
||||
byte* sc = w2; // implicit cast to (byte*)
|
||||
*sc = bs[0];
|
||||
byte[] bs = { 'c', 'm' }; // constant byte array
|
||||
byte b = 4; // constant byte
|
||||
word w = { b, 0 }; // constant inline word
|
||||
word w2 = { 1, 1 } + w + { 0, 0 }; // constant inline words inside expression
|
||||
byte* sc = w2; // implicit cast to (byte*)
|
||||
*sc = bs[1]; // In the end $501 is set to 'c'
|
||||
|
||||
// Test the result
|
||||
byte* pos = $501;
|
||||
byte* bgcol = $d021;
|
||||
if(*pos=='m') {
|
||||
*bgcol = 5;
|
||||
} else {
|
||||
*bgcol = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user