mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-13 03:39:12 +00:00
Implemented C-classic struct functionality for loadstore struct variables. Works for most scenarios: declaration, initialization, assignment, member-access. Structs containing arrays not working yet.
This commit is contained in:
parent
3b043e11a7
commit
e8a0478e5f
src
main/java/dk/camelot64/kickc
test
java/dk/camelot64/kickc/test
kc
struct-13.kcstruct-14.kcstruct-15.kcstruct-16.kcstruct-17.kcstruct-18.kcstruct-19.kcstruct-20.kcstruct-21.kcstruct-22.kcstruct-23.kc
ref
complex/splines
declared-memory-var-3.asmdeclared-memory-var-3.cfgdeclared-memory-var-3.logdeclared-memory-var-3.symdeclared-memory-var-4.symdeclared-memory-var-5.asmdeclared-memory-var-5.cfgdeclared-memory-var-5.logdeclared-memory-var-5.symsizeof-struct.logstruct-13.asmstruct-13.cfgstruct-13.logstruct-13.symstruct-14.asmstruct-14.cfgstruct-14.logstruct-14.symstruct-15.asmstruct-15.cfgstruct-15.logstruct-15.symstruct-16.asmstruct-16.cfgstruct-16.logstruct-16.symstruct-17.asmstruct-17.cfgstruct-17.logstruct-17.symstruct-18.asmstruct-18.cfgstruct-18.logstruct-18.symstruct-19.asmstruct-19.cfgstruct-19.logstruct-19.symstruct-20.asmstruct-20.cfgstruct-20.logstruct-20.symstruct-21.asmstruct-21.cfgstruct-21.logstruct-21.symstruct-22.asmstruct-22.cfgstruct-22.logstruct-22.symstruct-23.asmstruct-23.cfgstruct-23.logstruct-23.symstruct-6.logstruct-7.logstruct-8.logstruct-9.logstruct-ptr-12.asmstruct-ptr-12.cfgstruct-ptr-12.logstruct-ptr-12.symstruct-ptr-14.asmstruct-ptr-14.cfgstruct-ptr-14.logstruct-ptr-14.sym@ -190,6 +190,7 @@ public class Compiler {
|
||||
new Pass1PointerSizeofFix(program).execute(); // After this point in the code all pointer math is byte-based
|
||||
new PassNSizeOfSimplification(program).execute(); // Needed to eliminate sizeof() referencing pointer value variables
|
||||
|
||||
new Pass1UnwindStructVariables(program).execute();
|
||||
new Pass1UnwindStructValues(program).execute();
|
||||
new PassNStructPointerRewriting(program).execute();
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package dk.camelot64.kickc.model;
|
||||
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.SymbolVariableRef;
|
||||
|
||||
@ -45,31 +47,29 @@ public class StructUnwinding {
|
||||
public static class VariableUnwinding implements StructMemberUnwinding {
|
||||
|
||||
/** Maps member names to the unwound variables. */
|
||||
Map<String, SymbolVariableRef> memberUnwinding = new LinkedHashMap<>();
|
||||
Map<String, RValue> memberUnwinding = new LinkedHashMap<>();
|
||||
|
||||
/** Maps member names to the unwound variable types. */
|
||||
Map<String, SymbolType> typesUnwinding = new LinkedHashMap<>();
|
||||
|
||||
/** Set how a member variable was unwound to a specific (new) variable. */
|
||||
public void setMemberUnwinding(String memberName, SymbolVariableRef memberVariableUnwound) {
|
||||
public void setMemberUnwinding(String memberName, RValue memberVariableUnwound, SymbolType memberType) {
|
||||
this.memberUnwinding.put(memberName, memberVariableUnwound);
|
||||
this.typesUnwinding.put(memberName, memberType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the names of the members of the struct
|
||||
*
|
||||
* @return the names
|
||||
*/
|
||||
public List<String> getMemberNames() {
|
||||
return new ArrayList<>(memberUnwinding.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the (new) variable that a specific member was unwound to
|
||||
*
|
||||
* @param memberName The member name
|
||||
* @return The new variable
|
||||
*/
|
||||
public RValue getMemberUnwinding(String memberName) {
|
||||
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
return this.memberUnwinding.get(memberName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return this.typesUnwinding.get(memberName);
|
||||
}
|
||||
}
|
||||
|
||||
/** Information about how members of an struct Lvalue is unwound. */
|
||||
@ -86,8 +86,16 @@ public class StructUnwinding {
|
||||
* Get the RValue that a specific member was unwound to
|
||||
*
|
||||
* @param memberName The member name
|
||||
* @param programScope The program scope
|
||||
* @return The unwinding of the member
|
||||
*/
|
||||
RValue getMemberUnwinding(String memberName);
|
||||
RValue getMemberUnwinding(String memberName, ProgramScope programScope);
|
||||
|
||||
/**
|
||||
* Get the type of a specific member
|
||||
* @param memberName The name of the struct member
|
||||
* @return The type of the member
|
||||
*/
|
||||
SymbolType getMemberType(String memberName);
|
||||
}
|
||||
}
|
||||
|
@ -539,6 +539,27 @@ public class Variable implements Symbol {
|
||||
return isVolatile || inferredVolatile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the variable a struct that should be unwound to member variables
|
||||
*
|
||||
* @return true if an unwinding struct
|
||||
*/
|
||||
public boolean isStructUnwind() {
|
||||
if(getType() instanceof SymbolTypeStruct)
|
||||
return isKindPhiMaster() || isKindIntermediate() || isKindPhiVersion();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the variable a struct that should be handled using C Classic memory layout
|
||||
*
|
||||
* @return true if an classic struct
|
||||
*/
|
||||
public boolean isStructClassic() {
|
||||
return getType() instanceof SymbolTypeStruct && isKindLoadStore();
|
||||
}
|
||||
|
||||
public List<Comment> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
||||
if(returnVarUnwinding!=null) {
|
||||
ArrayList<RValue> unwoundReturnVars = new ArrayList<>();
|
||||
for(String memberName : returnVarUnwinding.getMemberNames()) {
|
||||
unwoundReturnVars.add(returnVarUnwinding.getMemberUnwinding(memberName));
|
||||
unwoundReturnVars.add(returnVarUnwinding.getMemberUnwinding(memberName, getScope()));
|
||||
}
|
||||
procReturnVarRef = new ValueList(unwoundReturnVars);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
@ -18,10 +18,9 @@ import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/** Convert all struct values that are not used as pointers (address-of used or declared volatile) into variables representing each member */
|
||||
/** Convert all unwinding struct values into variables representing each member */
|
||||
public class Pass1UnwindStructValues extends Pass1Base {
|
||||
|
||||
|
||||
public Pass1UnwindStructValues(Program program) {
|
||||
super(program);
|
||||
}
|
||||
@ -31,9 +30,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
if(getProgram().getStructUnwinding() == null) {
|
||||
getProgram().setStructUnwinding(new StructUnwinding());
|
||||
}
|
||||
// Iterate through all scopes generating member-variables for each struct
|
||||
boolean modified = false;
|
||||
modified |= unwindStructVariables();
|
||||
// Unwind all procedure declaration parameters
|
||||
modified |= unwindStructParameters();
|
||||
// Unwind all usages of struct values
|
||||
@ -76,7 +73,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
if(structMemberRef.getStruct() instanceof VariableRef) {
|
||||
StructUnwinding.StructMemberUnwinding memberVariables = getStructMemberUnwinding(structMemberRef.getStruct(), currentStmt, stmtIt, currentBlock);
|
||||
if(memberVariables != null && memberVariables != POSTPONE_UNWINDING) {
|
||||
RValue structMemberVariable = memberVariables.getMemberUnwinding(structMemberRef.getMemberName());
|
||||
RValue structMemberVariable = memberVariables.getMemberUnwinding(structMemberRef.getMemberName(), getScope());
|
||||
getLog().append("Replacing struct member reference " + structMemberRef.toString(getProgram()) + " with member unwinding reference " + structMemberVariable.toString(getProgram()));
|
||||
programValue.set(structMemberVariable);
|
||||
modified.set(true);
|
||||
@ -99,7 +96,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
if(lValueUnwinding != null && lValueUnwinding != POSTPONE_UNWINDING) {
|
||||
ArrayList<RValue> unwoundMembers = new ArrayList<>();
|
||||
for(String memberName : lValueUnwinding.getMemberNames()) {
|
||||
unwoundMembers.add(lValueUnwinding.getMemberUnwinding(memberName));
|
||||
unwoundMembers.add(lValueUnwinding.getMemberUnwinding(memberName, getScope()));
|
||||
}
|
||||
ValueList unwoundLValue = new ValueList(unwoundMembers);
|
||||
call.setlValue(unwoundLValue);
|
||||
@ -116,7 +113,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
if(parameterUnwinding != null && parameterUnwinding != POSTPONE_UNWINDING) {
|
||||
// Passing a struct variable - convert it to member variables
|
||||
for(String memberName : parameterUnwinding.getMemberNames()) {
|
||||
unwoundParameters.add(parameterUnwinding.getMemberUnwinding(memberName));
|
||||
unwoundParameters.add(parameterUnwinding.getMemberUnwinding(memberName, getScope()));
|
||||
}
|
||||
unwound = true;
|
||||
anyParameterUnwound = true;
|
||||
@ -146,7 +143,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
if(returnVarUnwinding != null && returnVarUnwinding != POSTPONE_UNWINDING) {
|
||||
ArrayList<RValue> unwoundMembers = new ArrayList<>();
|
||||
for(String memberName : returnVarUnwinding.getMemberNames()) {
|
||||
unwoundMembers.add(returnVarUnwinding.getMemberUnwinding(memberName));
|
||||
unwoundMembers.add(returnVarUnwinding.getMemberUnwinding(memberName, getScope()));
|
||||
}
|
||||
ValueList unwoundReturnValue = new ValueList(unwoundMembers);
|
||||
statementReturn.setValue(unwoundReturnValue);
|
||||
@ -171,7 +168,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
||||
StructUnwinding.VariableUnwinding parameterUnwinding = structUnwinding.getVariableUnwinding(parameter.getRef());
|
||||
for(String memberName : parameterUnwinding.getMemberNames()) {
|
||||
SymbolVariableRef memberUnwinding = (SymbolVariableRef) parameterUnwinding.getMemberUnwinding(memberName);
|
||||
SymbolVariableRef memberUnwinding = (SymbolVariableRef) parameterUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
unwoundParameterNames.add(memberUnwinding.getLocalName());
|
||||
procedureUnwound = true;
|
||||
}
|
||||
@ -188,40 +185,6 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all scopes generating member-variables for each struct variable
|
||||
*
|
||||
* @return Information about all unwound struct variables
|
||||
*/
|
||||
private boolean unwindStructVariables() {
|
||||
boolean modified = false;
|
||||
// Iterate through all scopes generating member-variables for each struct
|
||||
for(Variable variable : getScope().getAllVariables(true)) {
|
||||
if(variable.getType() instanceof SymbolTypeStruct) {
|
||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
||||
if(structUnwinding.getVariableUnwinding(variable.getRef()) == null) {
|
||||
// A non-volatile struct variable
|
||||
Scope scope = variable.getScope();
|
||||
if(!(scope instanceof StructDefinition)) {
|
||||
// Not inside another struct
|
||||
StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope());
|
||||
StructUnwinding.VariableUnwinding variableUnwinding = structUnwinding.createVariableUnwinding(variable.getRef());
|
||||
for(Variable member : structDefinition.getAllVars(false)) {
|
||||
boolean isParameter = scope instanceof Procedure && ((Procedure) scope).getParameters().contains(variable);
|
||||
Variable memberVariable = Variable.createStructMemberUnwound(variable, member, isParameter);
|
||||
scope.add(memberVariable);
|
||||
variableUnwinding.setMemberUnwinding(member.getLocalName(), memberVariable.getRef());
|
||||
getLog().append("Created struct value member variable " + memberVariable.toString(getProgram()));
|
||||
}
|
||||
getLog().append("Converted struct value to member variables " + variable.toString(getProgram()));
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwind an assignment to a struct value variable into assignment of each member
|
||||
*
|
||||
@ -244,12 +207,12 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
List<RValue> membersUnwound = new ArrayList<>();
|
||||
stmtIt.previous();
|
||||
for(String memberName : memberUnwinding.getMemberNames()) {
|
||||
SymbolVariableRef memberVarRef = (SymbolVariableRef) memberUnwinding.getMemberUnwinding(memberName);
|
||||
LValue memberVarRef = (LValue) memberUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
membersUnwound.add(memberVarRef);
|
||||
Variable memberVar = getScope().getVariable(memberVarRef);
|
||||
StatementSource statementSource = assignment.getSource();
|
||||
RValue initValue = Initializers.createZeroValue(memberVar.getType(), statementSource);
|
||||
Statement initStmt = new StatementAssignment((LValue) memberVarRef, initValue, assignment.isInitialAssignment(), statementSource, Comment.NO_COMMENTS);
|
||||
SymbolType memberType = memberUnwinding.getMemberType(memberName);
|
||||
RValue initValue = Initializers.createZeroValue(memberType, statementSource);
|
||||
Statement initStmt = new StatementAssignment(memberVarRef, initValue, assignment.isInitialAssignment(), statementSource, Comment.NO_COMMENTS);
|
||||
stmtIt.add(initStmt);
|
||||
getLog().append("Adding struct value member variable default initializer " + initStmt.toString(getProgram(), false));
|
||||
}
|
||||
@ -271,7 +234,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
List<RValue> membersUnwound = new ArrayList<>();
|
||||
int idx = 0;
|
||||
for(String memberName : memberUnwinding.getMemberNames()) {
|
||||
LValue memberLvalue = (LValue) memberUnwinding.getMemberUnwinding(memberName);
|
||||
LValue memberLvalue = (LValue) memberUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
membersUnwound.add(memberLvalue);
|
||||
Statement initStmt = new StatementAssignment(memberLvalue, valueList.getList().get(idx++), assignment.isInitialAssignment(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||
stmtIt.add(initStmt);
|
||||
@ -301,8 +264,8 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
List<RValue> membersUnwound = new ArrayList<>();
|
||||
stmtIt.previous();
|
||||
for(String memberName : memberUnwinding.getMemberNames()) {
|
||||
LValue assignedMemberVarRef = (LValue) memberUnwinding.getMemberUnwinding(memberName);
|
||||
RValue sourceMemberVarRef = sourceMemberUnwinding.getMemberUnwinding(memberName);
|
||||
LValue assignedMemberVarRef = (LValue) memberUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
RValue sourceMemberVarRef = sourceMemberUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
membersUnwound.add(assignedMemberVarRef);
|
||||
Statement copyStmt = new StatementAssignment(assignedMemberVarRef, sourceMemberVarRef, assignment.isInitialAssignment(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||
stmtIt.add(copyStmt);
|
||||
@ -335,12 +298,17 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
*/
|
||||
private StructUnwinding.StructMemberUnwinding getStructMemberUnwinding(RValue value, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
if(value != null) {
|
||||
SymbolType lValueType = SymbolTypeInference.inferType(getScope(), value);
|
||||
if(lValueType instanceof SymbolTypeStruct) {
|
||||
SymbolTypeStruct structType = (SymbolTypeStruct) lValueType;
|
||||
SymbolType valueType = SymbolTypeInference.inferType(getScope(), value);
|
||||
if(valueType instanceof SymbolTypeStruct) {
|
||||
SymbolTypeStruct structType = (SymbolTypeStruct) valueType;
|
||||
if(value instanceof VariableRef) {
|
||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
||||
return structUnwinding.getVariableUnwinding((VariableRef) value);
|
||||
Variable variable = getScope().getVariable((VariableRef) value);
|
||||
if(variable.isStructUnwind()) {
|
||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
||||
return structUnwinding.getVariableUnwinding((VariableRef) value);
|
||||
} else if(variable.isStructClassic()) {
|
||||
return new StructVariableMemberUnwinding(variable, structType.getStructDefinition(getScope()), currentBlock, stmtIt, currentStmt);
|
||||
}
|
||||
} else if(value instanceof StructMemberRef && ((StructMemberRef) value).getStruct() instanceof VariableRef) {
|
||||
return POSTPONE_UNWINDING;
|
||||
} else if(value instanceof PointerDereferenceSimple) {
|
||||
@ -348,7 +316,9 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
} else if(value instanceof PointerDereferenceIndexed) {
|
||||
return new StructMemberUnwindingPointerDerefIndexed((PointerDereferenceIndexed) value, structType.getStructDefinition(getScope()), stmtIt, currentBlock, currentStmt);
|
||||
} else if(value instanceof ConstantStructValue) {
|
||||
return new StructMemberUnwindingConstantValue((ConstantStructValue) value, structType.getStructDefinition(getScope()), stmtIt, currentBlock, currentStmt);
|
||||
return new StructMemberUnwindingConstantValue((ConstantStructValue) value, structType.getStructDefinition(getScope()));
|
||||
} else if(value instanceof StructZero) {
|
||||
return new StructMemberUnwindingZero((StructZero) value, structType.getStructDefinition(getScope()));
|
||||
} else {
|
||||
throw new InternalError("Struct unwinding not implemented for " + value.toString(getProgram()));
|
||||
}
|
||||
@ -365,13 +335,18 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LValue getMemberUnwinding(String memberName) {
|
||||
public LValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/** Unwinding for a simple pointer deref to a struct. */
|
||||
private class StructMemberUnwindingPointerDerefSimple implements StructUnwinding.StructMemberUnwinding {
|
||||
private static class StructMemberUnwindingPointerDerefSimple implements StructUnwinding.StructMemberUnwinding {
|
||||
private final StructDefinition structDefinition;
|
||||
private final ControlFlowBlock currentBlock;
|
||||
private final ListIterator<Statement> stmtIt;
|
||||
@ -397,10 +372,10 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LValue getMemberUnwinding(String memberName) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(getScope(), structDefinition, memberName);
|
||||
public LValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
Scope scope = getScope().getScope(currentBlock.getScope());
|
||||
Scope scope = programScope.getScope(currentBlock.getScope());
|
||||
Variable memberAddress = scope.addVariableIntermediate();
|
||||
memberAddress.setType(new SymbolTypePointer(member.getType()));
|
||||
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(member.getType()), pointerDeref.getPointer());
|
||||
@ -409,14 +384,19 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
// Unwind to *(ptr_struct+OFFSET_STRUCT_NAME_MEMBER)
|
||||
return new PointerDereferenceSimple(memberAddress.getRef());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
}
|
||||
|
||||
/** Unwinding for a indexed pointer deref to a struct. */
|
||||
private class StructMemberUnwindingPointerDerefIndexed implements StructUnwinding.StructMemberUnwinding {
|
||||
private static class StructMemberUnwindingPointerDerefIndexed implements StructUnwinding.StructMemberUnwinding {
|
||||
private final PointerDereferenceIndexed pointerDeref;
|
||||
private final StructDefinition structDefinition;
|
||||
private final ControlFlowBlock currentBlock;
|
||||
private final ListIterator<Statement> stmtIt;
|
||||
private final PointerDereferenceIndexed pointerDeref;
|
||||
private final Statement currentStmt;
|
||||
|
||||
StructMemberUnwindingPointerDerefIndexed(PointerDereferenceIndexed pointerDeref, StructDefinition structDefinition, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) {
|
||||
@ -438,10 +418,10 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LValue getMemberUnwinding(String memberName) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(getScope(), structDefinition, memberName);
|
||||
public LValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
Scope scope = getScope().getScope(currentBlock.getScope());
|
||||
Scope scope = programScope.getScope(currentBlock.getScope());
|
||||
Variable memberAddress = scope.addVariableIntermediate();
|
||||
memberAddress.setType(new SymbolTypePointer(member.getType()));
|
||||
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(member.getType()), pointerDeref.getPointer());
|
||||
@ -450,18 +430,57 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
// Unwind to *(ptr_struct+OFFSET_STRUCT_NAME_MEMBER[idx]
|
||||
return new PointerDereferenceIndexed(memberAddress.getRef(), pointerDeref.getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Unwinding for a simple pointer deref to a struct. */
|
||||
private class StructMemberUnwindingConstantValue implements StructUnwinding.StructMemberUnwinding {
|
||||
/** Unwinding for constant struct value. */
|
||||
private static class StructMemberUnwindingConstantValue implements StructUnwinding.StructMemberUnwinding {
|
||||
private final ConstantStructValue constantStructValue;
|
||||
private final StructDefinition structDefinition;
|
||||
|
||||
StructMemberUnwindingConstantValue(ConstantStructValue constantStructValue, StructDefinition structDefinition) {
|
||||
this.constantStructValue = constantStructValue;
|
||||
this.structDefinition = structDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMemberNames() {
|
||||
Collection<Variable> structMemberVars = structDefinition.getAllVariables(false);
|
||||
ArrayList<String> memberNames = new ArrayList<>();
|
||||
for(Variable structMemberVar : structMemberVars) {
|
||||
memberNames.add(structMemberVar.getLocalName());
|
||||
}
|
||||
return memberNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
return constantStructValue.getValue(member.getRef());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Unwinding for a struct value with C-classic memory layout. */
|
||||
private static class StructVariableMemberUnwinding implements StructUnwinding.StructMemberUnwinding {
|
||||
private Variable variable;
|
||||
private StructDefinition structDefinition;
|
||||
private final ControlFlowBlock currentBlock;
|
||||
private final ListIterator<Statement> stmtIt;
|
||||
private final Statement currentStmt;
|
||||
|
||||
StructMemberUnwindingConstantValue(ConstantStructValue constantStructValue, StructDefinition structDefinition, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) {
|
||||
this.constantStructValue = constantStructValue;
|
||||
public StructVariableMemberUnwinding(Variable variable, StructDefinition structDefinition, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt, Statement currentStmt) {
|
||||
this.variable = variable;
|
||||
this.structDefinition = structDefinition;
|
||||
this.currentBlock = currentBlock;
|
||||
this.stmtIt = stmtIt;
|
||||
@ -479,11 +498,56 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberUnwinding(String memberName) {
|
||||
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
return constantStructValue.getValue(member.getRef());
|
||||
Scope scope = programScope.getScope(currentBlock.getScope());
|
||||
Variable memberAddress = scope.addVariableIntermediate();
|
||||
memberAddress.setType(new SymbolTypePointer(member.getType()));
|
||||
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(variable.getRef());
|
||||
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(member.getType()), structPointer);
|
||||
// Add statement $1 = ptr_struct + OFFSET_STRUCT_NAME_MEMBER
|
||||
stmtIt.add(new StatementAssignment((LValue) memberAddress.getRef(), structTypedPointer, Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
|
||||
// Unwind to *(ptr_struct+OFFSET_STRUCT_NAME_MEMBER)
|
||||
return new PointerDereferenceSimple(memberAddress.getRef());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Unwinding for StructZero */
|
||||
private static class StructMemberUnwindingZero implements StructUnwinding.StructMemberUnwinding {
|
||||
private StructZero structZero;
|
||||
private StructDefinition structDefinition;
|
||||
|
||||
public StructMemberUnwindingZero(StructZero structZero, StructDefinition structDefinition) {
|
||||
this.structZero = structZero;
|
||||
this.structDefinition = structDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMemberNames() {
|
||||
Collection<Variable> structMemberVars = structDefinition.getAllVariables(false);
|
||||
ArrayList<String> memberNames = new ArrayList<>();
|
||||
for(Variable structMemberVar : structMemberVars) {
|
||||
memberNames.add(structMemberVar.getLocalName());
|
||||
}
|
||||
return memberNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
return ZeroConstantValues.zeroValue(getMemberType(memberName), programScope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,63 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.StructUnwinding;
|
||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||
import dk.camelot64.kickc.model.symbols.Scope;
|
||||
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||
|
||||
/** Create unwindings for all unwinding struct variables. The unwinding is a conversion to one variable per member.
|
||||
* The unwindings are stored in {@link Program#getStructUnwinding()}
|
||||
* */
|
||||
public class Pass1UnwindStructVariables extends Pass1Base {
|
||||
|
||||
public Pass1UnwindStructVariables(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
if(getProgram().getStructUnwinding() == null) {
|
||||
getProgram().setStructUnwinding(new StructUnwinding());
|
||||
}
|
||||
// Iterate through all scopes generating member-variables for each struct
|
||||
return unwindStructVariables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all scopes generating member-variables for each struct variable
|
||||
*
|
||||
* @return Information about all unwound struct variables
|
||||
*/
|
||||
private boolean unwindStructVariables() {
|
||||
boolean modified = false;
|
||||
// Iterate through all scopes generating member-variables for each struct
|
||||
for(Variable variable : getScope().getAllVariables(true)) {
|
||||
if(variable.isStructUnwind()) {
|
||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
||||
if(structUnwinding.getVariableUnwinding(variable.getRef()) == null) {
|
||||
// A non-volatile struct variable
|
||||
Scope scope = variable.getScope();
|
||||
if(!(scope instanceof StructDefinition)) {
|
||||
// Not inside another struct
|
||||
StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope());
|
||||
StructUnwinding.VariableUnwinding variableUnwinding = structUnwinding.createVariableUnwinding(variable.getRef());
|
||||
for(Variable member : structDefinition.getAllVars(false)) {
|
||||
boolean isParameter = scope instanceof Procedure && ((Procedure) scope).getParameters().contains(variable);
|
||||
Variable memberVariable = Variable.createStructMemberUnwound(variable, member, isParameter);
|
||||
scope.add(memberVariable);
|
||||
variableUnwinding.setMemberUnwinding(member.getLocalName(), memberVariable.getRef(), memberVariable.getType());
|
||||
getLog().append("Created struct value member variable " + memberVariable.toString(getProgram()));
|
||||
}
|
||||
getLog().append("Converted struct value to member variables " + variable.toString(getProgram()));
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
}
|
@ -45,7 +45,7 @@ public class Pass1UnwindStructVersions extends Pass1Base {
|
||||
while(memberDefIt.hasNext()) {
|
||||
Variable memberVar = memberDefIt.next();
|
||||
RValue memberVal = memberUnwoundIt.next();
|
||||
versionedUnwinding.setMemberUnwinding(memberVar.getLocalName(), (VariableRef) memberVal);
|
||||
versionedUnwinding.setMemberUnwinding(memberVar.getLocalName(), memberVal, memberVar.getType());
|
||||
}
|
||||
getLog().append("Adding versioned struct unwinding for "+assignment.getlValue().toString(getProgram()));
|
||||
modified = true;
|
||||
|
@ -33,7 +33,7 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
|
||||
|
||||
// Add all versions of volatile variables to the same equivalence class
|
||||
for(Variable variable : getSymbols().getAllVariables(true)) {
|
||||
if(variable.isKindPhiVersion() && variable.isAnyVolatile()) {
|
||||
if(variable.isKindPhiVersion() && variable.isAnyVolatile() && !variable.isStructUnwind()) {
|
||||
// Found a volatile non-versioned variable
|
||||
for(Variable otherVariable : variable.getScope().getAllVariables(false)) {
|
||||
if(otherVariable.isKindPhiVersion()) {
|
||||
@ -51,10 +51,15 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add all other variables one by one to an available equivalence class - or create a new one
|
||||
EquivalenceClassAdder equivalenceClassAdder = new EquivalenceClassAdder(liveRangeEquivalenceClassSet);
|
||||
equivalenceClassAdder.visitGraph(getGraph());
|
||||
|
||||
// Add any remaining struct load/store variables
|
||||
for(Variable variable : getSymbols().getAllVariables(true))
|
||||
if(variable.isStructClassic())
|
||||
addToEquivalenceClassSet(variable.getVariableRef(), new ArrayList<>(), liveRangeEquivalenceClassSet );
|
||||
|
||||
getLog().append("Complete equivalence classes");
|
||||
for(LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
getLog().append(liveRangeEquivalenceClass.toString());
|
||||
@ -63,6 +68,36 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
|
||||
getProgram().setLiveRangeEquivalenceClassSet(liveRangeEquivalenceClassSet);
|
||||
}
|
||||
|
||||
void addToEquivalenceClassSet(VariableRef lValVar, List<VariableRef> preferences, LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
|
||||
LiveRangeVariables liveRangeVariables = getProgram().getLiveRangeVariables();
|
||||
LiveRangeEquivalenceClass lValEquivalenceClass =
|
||||
liveRangeEquivalenceClassSet.getEquivalenceClass(lValVar);
|
||||
if(lValEquivalenceClass == null) {
|
||||
LiveRange lValLiveRange = liveRangeVariables.getLiveRange(lValVar);
|
||||
// Variable in need of an equivalence class - Look through preferences
|
||||
LiveRangeEquivalenceClass chosen = null;
|
||||
for(VariableRef preference : preferences) {
|
||||
LiveRangeEquivalenceClass preferenceEquivalenceClass = liveRangeEquivalenceClassSet.getEquivalenceClass(preference);
|
||||
if(preferenceEquivalenceClass != null) {
|
||||
Variable potentialVariable = getProgram().getSymbolInfos().getVariable(preference);
|
||||
Variable lValVariable = getProgram().getSymbolInfos().getVariable(lValVar);
|
||||
if(lValVariable.getType().equals(potentialVariable.getType())) {
|
||||
if(!lValLiveRange.overlaps(preferenceEquivalenceClass.getLiveRange())) {
|
||||
chosen = preferenceEquivalenceClass;
|
||||
chosen.addVariable(lValVar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(chosen == null) {
|
||||
// No preference usable - create a new one
|
||||
chosen = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(lValVar);
|
||||
}
|
||||
getLog().append("Added variable " + lValVar + " to live range equivalence class " + chosen);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all variables to a non-overlapping equivalence or create a new one.
|
||||
*/
|
||||
@ -79,7 +114,7 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
|
||||
if(assignment.getlValue() instanceof VariableRef) {
|
||||
VariableRef lValVar = (VariableRef) assignment.getlValue();
|
||||
List<VariableRef> preferences = new ArrayList<>();
|
||||
addToEquivalenceClassSet(lValVar, preferences);
|
||||
addToEquivalenceClassSet(lValVar, preferences, liveRangeEquivalenceClassSet);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -89,7 +124,7 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
|
||||
if(call.getlValue() instanceof VariableRef) {
|
||||
VariableRef lValVar = (VariableRef) call.getlValue();
|
||||
List<VariableRef> preferences = new ArrayList<>();
|
||||
addToEquivalenceClassSet(lValVar, preferences);
|
||||
addToEquivalenceClassSet(lValVar, preferences, liveRangeEquivalenceClassSet);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -99,41 +134,11 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
|
||||
if(callFinalize.getlValue() instanceof VariableRef) {
|
||||
VariableRef lValVar = (VariableRef) callFinalize.getlValue();
|
||||
List<VariableRef> preferences = new ArrayList<>();
|
||||
addToEquivalenceClassSet(lValVar, preferences);
|
||||
addToEquivalenceClassSet(lValVar, preferences, liveRangeEquivalenceClassSet);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addToEquivalenceClassSet(VariableRef lValVar, List<VariableRef> preferences) {
|
||||
LiveRangeVariables liveRangeVariables = getProgram().getLiveRangeVariables();
|
||||
LiveRangeEquivalenceClass lValEquivalenceClass =
|
||||
liveRangeEquivalenceClassSet.getEquivalenceClass(lValVar);
|
||||
if(lValEquivalenceClass == null) {
|
||||
LiveRange lValLiveRange = liveRangeVariables.getLiveRange(lValVar);
|
||||
// Variable in need of an equivalence class - Look through preferences
|
||||
LiveRangeEquivalenceClass chosen = null;
|
||||
for(VariableRef preference : preferences) {
|
||||
LiveRangeEquivalenceClass preferenceEquivalenceClass = liveRangeEquivalenceClassSet.getEquivalenceClass(preference);
|
||||
if(preferenceEquivalenceClass != null) {
|
||||
Variable potentialVariable = getProgram().getSymbolInfos().getVariable(preference);
|
||||
Variable lValVariable = getProgram().getSymbolInfos().getVariable(lValVar);
|
||||
if(lValVariable.getType().equals(potentialVariable.getType())) {
|
||||
if(!lValLiveRange.overlaps(preferenceEquivalenceClass.getLiveRange())) {
|
||||
chosen = preferenceEquivalenceClass;
|
||||
chosen.addVariable(lValVar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(chosen == null) {
|
||||
// No preference usable - create a new one
|
||||
chosen = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(lValVar);
|
||||
}
|
||||
getLog().append("Added variable " + lValVar + " to live range equivalence class " + chosen);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public class PassNEliminateUnusedVars extends Pass2SsaOptimization {
|
||||
} else if(!variable.isAnyVolatile() && !variable.isExport()) {
|
||||
// Not volatile
|
||||
eliminate = true;
|
||||
} else if(variable.isAnyVolatile() && variable.getType() instanceof SymbolTypeStruct) {
|
||||
} else if(variable.isStruct()) {
|
||||
if(assignment.getOperator()==null && assignment.getrValue2() instanceof StructUnwoundPlaceholder) {
|
||||
eliminate = true;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.ListIterator;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
@ -28,6 +29,8 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
|
||||
@Override
|
||||
public boolean step() {
|
||||
AtomicBoolean modified = new AtomicBoolean(false);
|
||||
|
||||
// Examine all expressions
|
||||
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
Value value = programValue.get();
|
||||
if(value instanceof ConstantSymbolPointer) {
|
||||
@ -36,11 +39,11 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
|
||||
Symbol toSymbol = getScope().getSymbol(toSymbolRef);
|
||||
if(toSymbol.getType() instanceof SymbolTypeStruct) {
|
||||
RValue rewrite = rewriteStructAddressOf((VariableRef) toSymbol.getRef());
|
||||
if(rewrite!=null) {
|
||||
if(rewrite != null) {
|
||||
programValue.set(rewrite);
|
||||
getLog().append("Rewriting struct address-of to first member " + value.toString(getProgram()));
|
||||
modified.set(true);
|
||||
}
|
||||
getLog().append("Rewriting struct address-of to first member "+value.toString(getProgram()));
|
||||
modified.set(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -50,16 +53,16 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) ) {
|
||||
if(Operators.ADDRESS_OF.equals(assignment.getOperator())) {
|
||||
RValue rValue = assignment.getrValue2();
|
||||
if(rValue instanceof SymbolVariableRef) {
|
||||
Symbol toSymbol = getScope().getSymbol((SymbolVariableRef) rValue);
|
||||
if(toSymbol.getType() instanceof SymbolTypeStruct) {
|
||||
RValue rewrite = rewriteStructAddressOf((VariableRef) toSymbol.getRef());
|
||||
if(rewrite!=null) {
|
||||
if(rewrite != null) {
|
||||
assignment.setOperator(null);
|
||||
assignment.setrValue2(rewrite);
|
||||
getLog().append("Rewriting struct address-of to first member "+assignment.toString(getProgram(), false));
|
||||
getLog().append("Rewriting struct address-of to first member " + assignment.toString(getProgram(), false));
|
||||
}
|
||||
modified.set(true);
|
||||
}
|
||||
@ -68,6 +71,22 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all StructUnwoundPlaceholder assignments for C-classic structs
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
|
||||
while(stmtIt.hasNext()) {
|
||||
Statement statement = stmtIt.next();
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(assignment.getrValue2() instanceof StructUnwoundPlaceholder && assignment.getlValue() instanceof VariableRef)
|
||||
if(getScope().getVariable((SymbolVariableRef) assignment.getlValue()).isStructClassic()) {
|
||||
getLog().append("Removing C-classic struct-unwound assignment "+assignment.toString(getProgram(), false));
|
||||
stmtIt.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return modified.get();
|
||||
}
|
||||
|
||||
@ -90,8 +109,11 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
|
||||
if(assignment.getrValue2() instanceof StructUnwoundPlaceholder) {
|
||||
// Found placeholder assignment!
|
||||
StructUnwoundPlaceholder placeholder = (StructUnwoundPlaceholder) assignment.getrValue2();
|
||||
SymbolRef firstMember = (SymbolRef) placeholder.getUnwoundMembers().get(0);
|
||||
return new ConstantCastValue(new SymbolTypePointer(placeholder.getTypeStruct()), new ConstantSymbolPointer(firstMember));
|
||||
RValue firstUnwoundMember = placeholder.getUnwoundMembers().get(0);
|
||||
if(firstUnwoundMember instanceof SymbolRef) {
|
||||
SymbolRef firstMember = (SymbolRef) firstUnwoundMember;
|
||||
return new ConstantCastValue(new SymbolTypePointer(placeholder.getTypeStruct()), new ConstantSymbolPointer(firstMember));
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -112,6 +112,31 @@ public class PassNStructPointerRewriting extends Pass2SsaOptimization {
|
||||
programValue.set(new PointerDereferenceIndexed(memberAddress.getRef(), ((PointerDereferenceIndexed) struct).getIndex()));
|
||||
}
|
||||
modified.set(true);
|
||||
} else if(struct instanceof SymbolVariableRef) {
|
||||
Variable structVar = getScope().getVar((SymbolVariableRef) struct);
|
||||
if(structVar.isStructClassic()) {
|
||||
SymbolType structType = SymbolTypeInference.inferType(getScope(), struct);
|
||||
if(!(structType instanceof SymbolTypeStruct)) {
|
||||
throw new CompileError("Accessing member of a non-struct ", currentStmt.getSource());
|
||||
}
|
||||
StructDefinition structDefinition = ((SymbolTypeStruct) structType).getStructDefinition(getScope());
|
||||
ConstantRef memberOffsetConstant = getMemberOffsetConstant(getScope(), structDefinition, structMemberRef.getMemberName());
|
||||
SymbolType memberType = SymbolTypeInference.inferType(getScope(), structMemberRef);
|
||||
Variable memberVar = structDefinition.getMember(structMemberRef.getMemberName());
|
||||
getLog().append("Rewriting struct member access " + programValue.get().toString(getProgram()));
|
||||
// Cast struct pointer to the type of the member
|
||||
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(memberType), new ConstantSymbolPointer(structVar.getRef()));
|
||||
// Create temporary variable to hold pointer to member ($1)
|
||||
Scope scope = getScope().getScope(currentBlock.getScope());
|
||||
Variable memberAddress = scope.addVariableIntermediate();
|
||||
memberAddress.setType(new SymbolTypePointer(memberType));
|
||||
// Add statement $1 = ptr_struct + OFFSET_STRUCT_NAME_MEMBER
|
||||
stmtIt.previous();
|
||||
stmtIt.add(new StatementAssignment((LValue) memberAddress.getRef(), structTypedPointer, Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
|
||||
stmtIt.next();
|
||||
// Replace struct.x with *($1)
|
||||
programValue.set(new PointerDereferenceSimple(memberAddress.getRef()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1127,6 +1127,61 @@ public class TestPrograms {
|
||||
assertError("struct-err-0", "Unknown struct type");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct23() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-23");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct22() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-22");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct21() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-21");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct20() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-20");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct19() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-19");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct18() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-18");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct17() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-17");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct16() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-16");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct15() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-15");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct14() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-14");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct13() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-13");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct12() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-12", log());
|
||||
@ -1194,7 +1249,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testStruct0() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-0", log());
|
||||
compileAndCompare("struct-0");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
17
src/test/kc/struct-13.kc
Normal file
17
src/test/kc/struct-13.kc
Normal file
@ -0,0 +1,17 @@
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
__ma struct Point point;
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
point.x = 2;
|
||||
point.y = 3;
|
||||
SCREEN[0] = point.x;
|
||||
SCREEN[1] = point.y;
|
||||
}
|
17
src/test/kc/struct-14.kc
Normal file
17
src/test/kc/struct-14.kc
Normal file
@ -0,0 +1,17 @@
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
struct Point[1] points;
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
points[0].x = 2;
|
||||
points[0].y = 3;
|
||||
SCREEN[0] = points[0].x;
|
||||
SCREEN[1] = points[0].y;
|
||||
}
|
17
src/test/kc/struct-15.kc
Normal file
17
src/test/kc/struct-15.kc
Normal file
@ -0,0 +1,17 @@
|
||||
// Minimal struct with C-Standard behavior - copying
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
__ma struct Point point1;
|
||||
point1.x = 2;
|
||||
point1.y = 3;
|
||||
__ma struct Point point2 = point1;
|
||||
SCREEN[0] = point2.x;
|
||||
SCREEN[1] = point2.y;
|
||||
}
|
14
src/test/kc/struct-16.kc
Normal file
14
src/test/kc/struct-16.kc
Normal file
@ -0,0 +1,14 @@
|
||||
// Minimal struct with C-Standard behavior - initializer
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
__ma struct Point point1 = { 2, 3 };
|
||||
SCREEN[0] = point1.x;
|
||||
SCREEN[1] = point1.y;
|
||||
}
|
25
src/test/kc/struct-17.kc
Normal file
25
src/test/kc/struct-17.kc
Normal file
@ -0,0 +1,25 @@
|
||||
// Minimal struct with C-Standard behavior - struct containing struct
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
struct Vector {
|
||||
struct Point p;
|
||||
struct Point q;
|
||||
};
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
__ma struct Vector v;
|
||||
v.p.x = 2;
|
||||
v.p.y = 3;
|
||||
v.q.x = 4;
|
||||
v.q.y = 5;
|
||||
SCREEN[0] = v.p.x;
|
||||
SCREEN[1] = v.p.y;
|
||||
SCREEN[2] = v.q.x;
|
||||
SCREEN[3] = v.q.y;
|
||||
}
|
21
src/test/kc/struct-18.kc
Normal file
21
src/test/kc/struct-18.kc
Normal file
@ -0,0 +1,21 @@
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
struct Vector {
|
||||
struct Point p;
|
||||
struct Point q;
|
||||
};
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
__ma struct Vector v = { {2, 3}, {4, 5} };
|
||||
SCREEN[0] = v.p.x;
|
||||
SCREEN[1] = v.p.y;
|
||||
SCREEN[2] = v.q.x;
|
||||
SCREEN[3] = v.q.y;
|
||||
}
|
25
src/test/kc/struct-19.kc
Normal file
25
src/test/kc/struct-19.kc
Normal file
@ -0,0 +1,25 @@
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
struct Vector {
|
||||
struct Point p;
|
||||
struct Point q;
|
||||
};
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
__ma struct Vector v;
|
||||
__ma struct Point p1 = { 2, 3 };
|
||||
__ma struct Point p2 = { 4, 5 };
|
||||
v.p = p1;
|
||||
v.q = p2;
|
||||
SCREEN[0] = v.p.x;
|
||||
SCREEN[1] = v.p.y;
|
||||
SCREEN[2] = v.q.x;
|
||||
SCREEN[3] = v.q.y;
|
||||
}
|
23
src/test/kc/struct-20.kc
Normal file
23
src/test/kc/struct-20.kc
Normal file
@ -0,0 +1,23 @@
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
struct Vector {
|
||||
struct Point p;
|
||||
struct Point q;
|
||||
};
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
__ma struct Point p1 = { 2, 3 };
|
||||
__ma struct Point p2 = { 4, 5 };
|
||||
__ma struct Vector v = { p1, p2 };
|
||||
SCREEN[0] = v.p.x;
|
||||
SCREEN[1] = v.p.y;
|
||||
SCREEN[2] = v.q.x;
|
||||
SCREEN[3] = v.q.y;
|
||||
}
|
15
src/test/kc/struct-21.kc
Normal file
15
src/test/kc/struct-21.kc
Normal file
@ -0,0 +1,15 @@
|
||||
// Minimal struct with C-Standard behavior - address-of
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
__ma struct Point point1 = { 2, 3 };
|
||||
struct Point* ptr = &point1;
|
||||
SCREEN[0] = ptr->x;
|
||||
SCREEN[1] = ptr->y;
|
||||
}
|
20
src/test/kc/struct-22.kc
Normal file
20
src/test/kc/struct-22.kc
Normal file
@ -0,0 +1,20 @@
|
||||
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
void main() {
|
||||
__ma struct Point point1 = { 2, 3 };
|
||||
__ma struct Point point2 = { 4, 5 };
|
||||
print(point1);
|
||||
print(point2);
|
||||
}
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void print(struct Point p) {
|
||||
SCREEN[0] = p.x;
|
||||
SCREEN[1] = p.y;
|
||||
}
|
22
src/test/kc/struct-23.kc
Normal file
22
src/test/kc/struct-23.kc
Normal file
@ -0,0 +1,22 @@
|
||||
// Minimal struct with C-Standard behavior - call return value (not supported yet)
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
__ma struct Point point1 = getPoint(2, 3);
|
||||
SCREEN[0] = point1.x;
|
||||
SCREEN[1] = point1.y;
|
||||
__ma struct Point point2 = getPoint(4, 5);
|
||||
SCREEN[2] = point2.x;
|
||||
SCREEN[3] = point2.y;
|
||||
}
|
||||
|
||||
struct Point getPoint(char x, char y) {
|
||||
struct Point p = { x, y };
|
||||
return p;
|
||||
}
|
@ -121,6 +121,12 @@ Converted struct value to member variables (struct SplineVector16) rotate::vecto
|
||||
Created struct value member variable (signed word) rotate::rotated_x
|
||||
Created struct value member variable (signed word) rotate::rotated_y
|
||||
Converted struct value to member variables (struct SplineVector16) rotate::rotated
|
||||
Created struct value member variable (signed word) show_letter::segment_to_x
|
||||
Created struct value member variable (signed word) show_letter::segment_to_y
|
||||
Converted struct value to member variables (struct SplineVector16) show_letter::segment_to
|
||||
Created struct value member variable (signed word) show_letter::segment_via_x
|
||||
Created struct value member variable (signed word) show_letter::segment_via_y
|
||||
Converted struct value to member variables (struct SplineVector16) show_letter::segment_via
|
||||
Converted procedure struct value parameter to member unwinding (void()) spline_16seg((signed word) spline_16seg::p0_x , (signed word) spline_16seg::p0_y , (signed word) spline_16seg::p1_x , (signed word) spline_16seg::p1_y , (signed word) spline_16seg::p2_x , (signed word) spline_16seg::p2_y)
|
||||
Converted procedure struct value parameter to member unwinding (void()) spline_8seg((signed word) spline_8seg::p0_x , (signed word) spline_8seg::p0_y , (signed word) spline_8seg::p1_x , (signed word) spline_8seg::p1_y , (signed word) spline_8seg::p2_x , (signed word) spline_8seg::p2_y)
|
||||
Converted procedure struct value parameter to member unwinding (void()) spline_8segB((signed word) spline_8segB::p0_x , (signed word) spline_8segB::p0_y , (signed word) spline_8segB::p1_x , (signed word) spline_8segB::p1_y , (signed word) spline_8segB::p2_x , (signed word) spline_8segB::p2_y)
|
||||
@ -331,12 +337,6 @@ Replacing struct member reference (struct SplineVector16) rotate::vector.x with
|
||||
Replacing struct member reference (struct SplineVector16) rotate::vector.y with member unwinding reference (signed word) rotate::vector_y
|
||||
Replacing struct member reference (struct SplineVector16) rotate::vector.y with member unwinding reference (signed word) rotate::vector_y
|
||||
Replacing struct member reference (struct SplineVector16) rotate::vector.x with member unwinding reference (signed word) rotate::vector_x
|
||||
Created struct value member variable (signed word) show_letter::segment_to_x
|
||||
Created struct value member variable (signed word) show_letter::segment_to_y
|
||||
Converted struct value to member variables (struct SplineVector16) show_letter::segment_to
|
||||
Created struct value member variable (signed word) show_letter::segment_via_x
|
||||
Created struct value member variable (signed word) show_letter::segment_via_y
|
||||
Converted struct value to member variables (struct SplineVector16) show_letter::segment_via
|
||||
Adding struct value member variable copy (signed word) show_letter::segment_to_x ← (signed word) show_letter::to_x
|
||||
Adding struct value member variable copy (signed word) show_letter::segment_to_y ← (signed word) show_letter::to_y
|
||||
Adding struct value member variable copy (signed word) show_letter::segment_via_x ← (signed word) show_letter::via_x
|
||||
|
@ -6,19 +6,18 @@
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
__bbegin:
|
||||
lda #'a'
|
||||
sta bar_thing1
|
||||
sta bar
|
||||
lda #'b'
|
||||
sta bar_thing2
|
||||
sta bar+OFFSET_STRUCT_FOO_THING2
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label barp = bar_thing1
|
||||
.label barp = bar
|
||||
lda barp
|
||||
sta SCREEN
|
||||
lda barp+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
bar: .byte 0, 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
@begin: scope:[] from
|
||||
[0] (byte) bar_thing1 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2 ← (byte) 'b'
|
||||
[0] *((byte*)&(struct foo) bar) ← (byte) 'a'
|
||||
[1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b'
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
|
@ -1,18 +1,18 @@
|
||||
Setting inferred volatile on symbol affected by address-of (struct foo*) main::barp ← &(struct foo) bar
|
||||
Created struct value member variable (byte) bar_thing1
|
||||
Created struct value member variable (byte) bar_thing2
|
||||
Converted struct value to member variables (struct foo) bar
|
||||
Adding struct value member variable copy (byte) bar_thing1 ← (byte) 'a'
|
||||
Adding struct value member variable copy (byte) bar_thing2 ← (byte) 'b'
|
||||
Adding struct value member variable copy *((byte*~) $0) ← (byte) 'a'
|
||||
Adding struct value member variable copy *((byte*~) $1) ← (byte) 'b'
|
||||
Rewriting struct pointer member access *((struct foo*) main::barp).thing1
|
||||
Rewriting struct pointer member access *((struct foo*) main::barp).thing2
|
||||
Identified constant variable (struct foo*) main::barp
|
||||
Adding versioned struct unwinding for (struct foo) bar
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte) bar_thing1 ← (byte) 'a'
|
||||
(byte) bar_thing2 ← (byte) 'b'
|
||||
(struct foo) bar ← struct-unwound {(byte) bar_thing1, (byte) bar_thing2}
|
||||
(byte*~) $0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
*((byte*~) $0) ← (byte) 'a'
|
||||
(byte*~) $1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
*((byte*~) $1) ← (byte) 'b'
|
||||
(struct foo) bar ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
@ -36,6 +36,8 @@ main::@return: scope:[main] from main
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(byte*~) $0
|
||||
(byte*~) $1
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
@ -43,8 +45,6 @@ SYMBOL TABLE SSA
|
||||
(const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(struct foo) bar loadstore
|
||||
(byte) bar_thing1 loadstore
|
||||
(byte) bar_thing2 loadstore
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
@ -67,20 +67,23 @@ Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Rewriting struct address-of to first member &(struct foo) bar
|
||||
Successful SSA optimization PassNStructAddressOfRewriting
|
||||
Constant right-side identified [4] (byte*~) main::$0 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Constant right-side identified [7] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Removing C-classic struct-unwound assignment [4] (struct foo) bar ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
|
||||
Constant right-side identified [0] (byte*~) $0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Constant right-side identified [2] (byte*~) $1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Constant right-side identified [6] (byte*~) main::$0 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Constant right-side identified [9] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) $0 = (byte*)&bar+OFFSET_STRUCT_FOO_THING1
|
||||
Constant (const byte*) $1 = (byte*)&bar+OFFSET_STRUCT_FOO_THING2
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Constant (const byte*) main::$0 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING1
|
||||
Constant (const byte*) main::$1 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING2
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero (byte*)main::barp in
|
||||
Simplifying expression containing zero main::SCREEN in [5] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0)
|
||||
Simplifying expression containing zero (byte*)&bar in
|
||||
Simplifying expression containing zero main::SCREEN in [7] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (struct foo) bar and assignment [2] (struct foo) bar ← struct-unwound {(byte) bar_thing1, (byte) bar_thing2}
|
||||
Eliminating unused variable (byte) main::i#2 and assignment [6] (byte) main::i#2 ← ++ (byte) main::i#1
|
||||
Eliminating unused variable (byte) main::i#2 and assignment [5] (byte) main::i#2 ← ++ (byte) main::i#1
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant right-side identified [3] (byte) main::i#1 ← ++ (const byte) main::i#0
|
||||
@ -92,6 +95,8 @@ Inlining constant with different constant siblings (const byte) main::i#1
|
||||
Constant inlined main::i#0 = (byte) 0
|
||||
Constant inlined main::i#1 = ++(byte) 0
|
||||
Constant inlined main::$1 = (byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Constant inlined $0 = (byte*)&(struct foo) bar
|
||||
Constant inlined $1 = (byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Constant inlined main::$0 = (byte*)(const struct foo*) main::barp
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(main::SCREEN+++0)
|
||||
@ -112,8 +117,8 @@ Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] (byte) bar_thing1 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2 ← (byte) 'b'
|
||||
[0] *((byte*)&(struct foo) bar) ← (byte) 'a'
|
||||
[1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b'
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
@ -133,21 +138,17 @@ main::@return: scope:[main] from main
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) bar_thing1 loadstore 20.0
|
||||
(byte) bar_thing2 loadstore 20.0
|
||||
(struct foo) bar loadstore
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(byte) main::i
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable bar_thing1 to live range equivalence class [ bar_thing1 ]
|
||||
Added variable bar_thing2 to live range equivalence class [ bar_thing2 ]
|
||||
Added variable bar to live range equivalence class [ bar ]
|
||||
Complete equivalence classes
|
||||
[ bar_thing1 ]
|
||||
[ bar_thing2 ]
|
||||
Allocated mem[1] [ bar_thing1 ]
|
||||
Allocated mem[1] [ bar_thing2 ]
|
||||
[ bar ]
|
||||
Allocated mem[2] [ bar ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
@ -162,12 +163,12 @@ Target platform is c64basic / MOS6502X
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
|
||||
lda #'a'
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
sta bar
|
||||
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
|
||||
lda #'b'
|
||||
sta bar_thing2
|
||||
sta bar+OFFSET_STRUCT_FOO_THING2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
@ -183,7 +184,7 @@ __bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label barp = bar_thing1
|
||||
.label barp = bar
|
||||
// [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp
|
||||
sta SCREEN
|
||||
@ -197,29 +198,23 @@ main: {
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
bar: .byte 0, 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] (byte) bar_thing1 ← (byte) 'a' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [1] (byte) bar_thing2 ← (byte) 'b' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [0] *((byte*)&(struct foo) bar) ← (byte) 'a' [ bar ] ( [ bar ] ) always clobbers reg byte a
|
||||
Statement [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Potential registers mem[1] [ bar_thing1 ] : mem[1] ,
|
||||
Potential registers mem[1] [ bar_thing2 ] : mem[1] ,
|
||||
Potential registers mem[2] [ bar ] : mem[2] ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [] 20: mem[1] [ bar_thing1 ] 20: mem[1] [ bar_thing2 ]
|
||||
Uplift Scope [foo]
|
||||
Uplift Scope [main]
|
||||
Uplift Scope [] 0: mem[2] [ bar ]
|
||||
|
||||
Uplifting [] best 49 combination mem[1] [ bar_thing1 ] mem[1] [ bar_thing2 ]
|
||||
Uplifting [foo] best 49 combination
|
||||
Uplifting [main] best 49 combination
|
||||
Attempting to uplift remaining variables inmem[1] [ bar_thing1 ]
|
||||
Uplifting [] best 49 combination mem[1] [ bar_thing1 ]
|
||||
Attempting to uplift remaining variables inmem[1] [ bar_thing2 ]
|
||||
Uplifting [] best 49 combination mem[1] [ bar_thing2 ]
|
||||
Uplifting [] best 49 combination mem[2] [ bar ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -233,12 +228,12 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
|
||||
lda #'a'
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
sta bar
|
||||
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
|
||||
lda #'b'
|
||||
sta bar_thing2
|
||||
sta bar+OFFSET_STRUCT_FOO_THING2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
@ -254,7 +249,7 @@ __bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label barp = bar_thing1
|
||||
.label barp = bar
|
||||
// [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp
|
||||
sta SCREEN
|
||||
@ -268,8 +263,7 @@ main: {
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
bar: .byte 0, 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
@ -291,18 +285,16 @@ FINAL SYMBOL TABLE
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(byte) bar_thing1 loadstore mem[1] 20.0
|
||||
(byte) bar_thing2 loadstore mem[1] 20.0
|
||||
(struct foo) bar loadstore mem[2]
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*) 1024
|
||||
(const struct foo*) main::barp = (struct foo*)&(byte) bar_thing1
|
||||
(const struct foo*) main::barp = &(struct foo) bar
|
||||
(byte) main::i
|
||||
|
||||
mem[1] [ bar_thing1 ]
|
||||
mem[1] [ bar_thing2 ]
|
||||
mem[2] [ bar ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
@ -320,12 +312,12 @@ Score: 46
|
||||
// @begin
|
||||
__bbegin:
|
||||
// bar = { 'a', 'b' }
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
|
||||
lda #'a'
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
sta bar
|
||||
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
|
||||
lda #'b'
|
||||
sta bar_thing2
|
||||
sta bar+OFFSET_STRUCT_FOO_THING2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [3] call main
|
||||
@ -336,7 +328,7 @@ __bbegin:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label barp = bar_thing1
|
||||
.label barp = bar
|
||||
// SCREEN[i++] = barp->thing1
|
||||
// [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp
|
||||
@ -351,6 +343,5 @@ main: {
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
bar: .byte 0, 0
|
||||
|
||||
|
@ -2,15 +2,13 @@
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(byte) bar_thing1 loadstore mem[1] 20.0
|
||||
(byte) bar_thing2 loadstore mem[1] 20.0
|
||||
(struct foo) bar loadstore mem[2]
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*) 1024
|
||||
(const struct foo*) main::barp = (struct foo*)&(byte) bar_thing1
|
||||
(const struct foo*) main::barp = &(struct foo) bar
|
||||
(byte) main::i
|
||||
|
||||
mem[1] [ bar_thing1 ]
|
||||
mem[1] [ bar_thing2 ]
|
||||
mem[2] [ bar ]
|
||||
|
@ -1,20 +1,17 @@
|
||||
(const string) $0 = (string) "qwe"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2
|
||||
(byte) bar_thing1 loadstore mem[1] 20.0
|
||||
(byte) bar_thing2 loadstore mem[1] 20.0
|
||||
(const byte*) bar_thing3 loadstore zp[2]:2 20.0
|
||||
(struct foo) bar loadstore mem[14]
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(const byte*) foo::thing3 = { fill( $c, 0) }
|
||||
(const byte*) foo::thing3[(number) $c] = { fill( $c, 0) }
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*) 1024
|
||||
(const struct foo*) main::barp = (struct foo*)&(byte) bar_thing1
|
||||
(const struct foo*) main::barp = &(struct foo) bar
|
||||
(byte) main::i
|
||||
(byte) main::i#3 reg byte x 7.333333333333333
|
||||
(byte) main::i#4 reg byte x 16.5
|
||||
@ -24,6 +21,4 @@
|
||||
|
||||
reg byte y [ main::j#2 main::j#1 ]
|
||||
reg byte x [ main::i#4 main::i#3 ]
|
||||
mem[1] [ bar_thing1 ]
|
||||
mem[1] [ bar_thing2 ]
|
||||
zp[2]:2 [ bar_thing3 ]
|
||||
mem[14] [ bar ]
|
||||
|
@ -1,15 +1,22 @@
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
// Test a memory variable struct value
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
.const bar_thing1 = 'a'
|
||||
.const bar_thing2 = 'b'
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
__bbegin:
|
||||
lda #'a'
|
||||
sta bar
|
||||
lda #'b'
|
||||
sta bar+OFFSET_STRUCT_FOO_THING2
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
lda #bar_thing1
|
||||
lda bar
|
||||
sta SCREEN
|
||||
lda #bar_thing2
|
||||
lda bar+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
||||
bar: .byte 0, 0
|
||||
|
@ -1,18 +1,19 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
[0] *((byte*)&(struct foo) bar) ← (byte) 'a'
|
||||
[1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b'
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
[4] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1
|
||||
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2
|
||||
[5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar)
|
||||
[6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[6] return
|
||||
[7] return
|
||||
to:@return
|
||||
|
@ -1,23 +1,26 @@
|
||||
Created struct value member variable (byte) bar_thing1
|
||||
Created struct value member variable (byte) bar_thing2
|
||||
Converted struct value to member variables (struct foo) bar
|
||||
Adding struct value member variable copy (byte) bar_thing1 ← (byte) 'a'
|
||||
Adding struct value member variable copy (byte) bar_thing2 ← (byte) 'b'
|
||||
Replacing struct member reference (struct foo) bar.thing1 with member unwinding reference (byte) bar_thing1
|
||||
Replacing struct member reference (struct foo) bar.thing2 with member unwinding reference (byte) bar_thing2
|
||||
Identified constant variable (byte) bar_thing1
|
||||
Identified constant variable (byte) bar_thing2
|
||||
Adding struct value member variable copy *((byte*~) $0) ← (byte) 'a'
|
||||
Adding struct value member variable copy *((byte*~) $1) ← (byte) 'b'
|
||||
Replacing struct member reference (struct foo) bar.thing1 with member unwinding reference *((byte*~) main::$0)
|
||||
Replacing struct member reference (struct foo) bar.thing2 with member unwinding reference *((byte*~) main::$1)
|
||||
Adding versioned struct unwinding for (struct foo) bar
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte*~) $0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
*((byte*~) $0) ← (byte) 'a'
|
||||
(byte*~) $1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
*((byte*~) $1) ← (byte) 'b'
|
||||
(struct foo) bar ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(byte) main::i#0 ← (number) 0
|
||||
*((const byte*) main::SCREEN + (byte) main::i#0) ← (const byte) bar_thing1
|
||||
*((const byte*) main::SCREEN + (byte) main::i#0) ← *((byte*~) main::$0)
|
||||
(byte*~) main::$0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
(byte) main::i#1 ← ++ (byte) main::i#0
|
||||
*((const byte*) main::SCREEN + (byte) main::i#1) ← (const byte) bar_thing2
|
||||
*((const byte*) main::SCREEN + (byte) main::i#1) ← *((byte*~) main::$1)
|
||||
(byte*~) main::$1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
(byte) main::i#2 ← ++ (byte) main::i#1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
@ -31,15 +34,20 @@ main::@return: scope:[main] from main
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(byte*~) $0
|
||||
(byte*~) $1
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) bar_thing1 = (byte) 'a'
|
||||
(const byte) bar_thing2 = (byte) 'b'
|
||||
(const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(struct foo) bar loadstore
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(byte*~) main::$0
|
||||
(byte*~) main::$1
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*)(number) $400
|
||||
(byte) main::i
|
||||
@ -56,13 +64,26 @@ Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [4] (struct foo) bar ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
|
||||
Constant right-side identified [0] (byte*~) $0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Constant right-side identified [2] (byte*~) $1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Constant right-side identified [7] (byte*~) main::$0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Constant right-side identified [10] (byte*~) main::$1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) $0 = (byte*)&bar+OFFSET_STRUCT_FOO_THING1
|
||||
Constant (const byte*) $1 = (byte*)&bar+OFFSET_STRUCT_FOO_THING2
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Constant (const byte*) main::$0 = (byte*)&bar+OFFSET_STRUCT_FOO_THING1
|
||||
Constant (const byte*) main::$1 = (byte*)&bar+OFFSET_STRUCT_FOO_THING2
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero main::SCREEN in [1] *((const byte*) main::SCREEN + (const byte) main::i#0) ← (const byte) bar_thing1
|
||||
Simplifying expression containing zero (byte*)&bar in
|
||||
Simplifying expression containing zero (byte*)&bar in
|
||||
Simplifying expression containing zero main::SCREEN in [6] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (byte) main::i#2 and assignment [3] (byte) main::i#2 ← ++ (byte) main::i#1
|
||||
Eliminating unused variable (byte) main::i#2 and assignment [5] (byte) main::i#2 ← ++ (byte) main::i#1
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant right-side identified [1] (byte) main::i#1 ← ++ (const byte) main::i#0
|
||||
Constant right-side identified [3] (byte) main::i#1 ← ++ (const byte) main::i#0
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) main::i#1 = ++main::i#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
@ -70,54 +91,61 @@ Inlining constant with different constant siblings (const byte) main::i#0
|
||||
Inlining constant with different constant siblings (const byte) main::i#1
|
||||
Constant inlined main::i#0 = (byte) 0
|
||||
Constant inlined main::i#1 = ++(byte) 0
|
||||
Constant inlined main::$1 = (byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Constant inlined $0 = (byte*)&(struct foo) bar
|
||||
Constant inlined $1 = (byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Constant inlined main::$0 = (byte*)&(struct foo) bar
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(main::SCREEN+++0)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Simplifying constant integer increment ++0
|
||||
Successful SSA optimization Pass2ConstantSimplification
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
Calls in [] to main:3
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
[0] *((byte*)&(struct foo) bar) ← (byte) 'a'
|
||||
[1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b'
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
[4] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1
|
||||
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2
|
||||
[5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar)
|
||||
[6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[6] return
|
||||
[7] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(struct foo) bar loadstore
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(byte) main::i
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable bar to live range equivalence class [ bar ]
|
||||
Complete equivalence classes
|
||||
[ bar ]
|
||||
Allocated mem[2] [ bar ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
@ -129,18 +157,23 @@ Target platform is c64basic / MOS6502X
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const bar_thing1 = 'a'
|
||||
.const bar_thing2 = 'b'
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
|
||||
lda #'a'
|
||||
sta bar
|
||||
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
|
||||
lda #'b'
|
||||
sta bar+OFFSET_STRUCT_FOO_THING2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
// [3] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
@ -148,32 +181,36 @@ __bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
// [4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1 -- _deref_pbuc1=vbuc2
|
||||
lda #bar_thing1
|
||||
// [5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda bar
|
||||
sta SCREEN
|
||||
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2 -- _deref_pbuc1=vbuc2
|
||||
lda #bar_thing2
|
||||
// [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda bar+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
// [7] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar: .byte 0, 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [0] *((byte*)&(struct foo) bar) ← (byte) 'a' [ bar ] ( [ bar ] ) always clobbers reg byte a
|
||||
Statement [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' [ bar ] ( [ bar ] ) always clobbers reg byte a
|
||||
Statement [5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) [ bar ] ( main:3 [ bar ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Potential registers mem[2] [ bar ] : mem[2] ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [foo]
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
Uplift Scope [] 0: mem[2] [ bar ]
|
||||
|
||||
Uplifting [foo] best 33 combination
|
||||
Uplifting [main] best 33 combination
|
||||
Uplifting [] best 33 combination
|
||||
Uplifting [foo] best 49 combination
|
||||
Uplifting [main] best 49 combination
|
||||
Uplifting [] best 49 combination mem[2] [ bar ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -184,18 +221,23 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const bar_thing1 = 'a'
|
||||
.const bar_thing2 = 'b'
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
|
||||
lda #'a'
|
||||
sta bar
|
||||
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
|
||||
lda #'b'
|
||||
sta bar+OFFSET_STRUCT_FOO_THING2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
// [3] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
@ -203,45 +245,42 @@ __bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
// [4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1 -- _deref_pbuc1=vbuc2
|
||||
lda #bar_thing1
|
||||
// [5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda bar
|
||||
sta SCREEN
|
||||
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2 -- _deref_pbuc1=vbuc2
|
||||
lda #bar_thing2
|
||||
// [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda bar+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
// [7] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar: .byte 0, 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1:
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) bar_thing1 = (byte) 'a'
|
||||
(const byte) bar_thing2 = (byte) 'b'
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(struct foo) bar loadstore mem[2]
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
@ -249,42 +288,53 @@ FINAL SYMBOL TABLE
|
||||
(const byte*) main::SCREEN = (byte*) 1024
|
||||
(byte) main::i
|
||||
|
||||
mem[2] [ bar ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 18
|
||||
Score: 46
|
||||
|
||||
// File Comments
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
// Test a memory variable struct value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const bar_thing1 = 'a'
|
||||
.const bar_thing2 = 'b'
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__bbegin:
|
||||
// bar = { 'a', 'b' }
|
||||
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
|
||||
lda #'a'
|
||||
sta bar
|
||||
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
|
||||
lda #'b'
|
||||
sta bar+OFFSET_STRUCT_FOO_THING2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// [3] call main
|
||||
jsr main
|
||||
rts
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
// SCREEN[i++] = bar.thing1
|
||||
// [4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1 -- _deref_pbuc1=vbuc2
|
||||
lda #bar_thing1
|
||||
// [5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda bar
|
||||
sta SCREEN
|
||||
// SCREEN[i++] = bar.thing2
|
||||
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2 -- _deref_pbuc1=vbuc2
|
||||
lda #bar_thing2
|
||||
// [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda bar+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [6] return
|
||||
// [7] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar: .byte 0, 0
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) bar_thing1 = (byte) 'a'
|
||||
(const byte) bar_thing2 = (byte) 'b'
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(struct foo) bar loadstore mem[2]
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
@ -10,3 +10,4 @@
|
||||
(const byte*) main::SCREEN = (byte*) 1024
|
||||
(byte) main::i
|
||||
|
||||
mem[2] [ bar ]
|
||||
|
@ -6,13 +6,13 @@ Converted struct value to member variables (struct Point) main::p
|
||||
Created struct value member variable (struct Point) main::c_center
|
||||
Created struct value member variable (byte) main::c_radius
|
||||
Converted struct value to member variables (struct Circle) main::c
|
||||
Created struct value member variable (byte) main::c_center_x
|
||||
Created struct value member variable (byte) main::c_center_y
|
||||
Converted struct value to member variables (struct Point) main::c_center
|
||||
Adding struct value member variable default initializer (byte) main::p_x ← (byte) 0
|
||||
Adding struct value member variable default initializer (byte) main::p_y ← (byte) 0
|
||||
Adding struct value member variable default initializer (struct Point) main::c_center ← {}
|
||||
Adding struct value member variable default initializer (byte) main::c_radius ← (byte) 0
|
||||
Created struct value member variable (byte) main::c_center_x
|
||||
Created struct value member variable (byte) main::c_center_y
|
||||
Converted struct value to member variables (struct Point) main::c_center
|
||||
Adding struct value member variable default initializer (byte) main::c_center_x ← (byte) 0
|
||||
Adding struct value member variable default initializer (byte) main::c_center_y ← (byte) 0
|
||||
Identified constant variable (byte) main::p_x
|
||||
|
24
src/test/ref/struct-13.asm
Normal file
24
src/test/ref/struct-13.asm
Normal file
@ -0,0 +1,24 @@
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label point = 2
|
||||
__bbegin:
|
||||
lda #0
|
||||
sta.z point
|
||||
sta point+OFFSET_STRUCT_POINT_Y
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
lda #2
|
||||
sta.z point
|
||||
lda #3
|
||||
sta point+OFFSET_STRUCT_POINT_Y
|
||||
lda.z point
|
||||
sta SCREEN
|
||||
lda point+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
21
src/test/ref/struct-13.cfg
Normal file
21
src/test/ref/struct-13.cfg
Normal file
@ -0,0 +1,21 @@
|
||||
@begin: scope:[] from
|
||||
[0] *((byte*)&(struct Point) point) ← (byte) 0
|
||||
[1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[4] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] *((byte*)&(struct Point) point) ← (byte) 2
|
||||
[6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point)
|
||||
[8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[9] return
|
||||
to:@return
|
366
src/test/ref/struct-13.log
Normal file
366
src/test/ref/struct-13.log
Normal file
@ -0,0 +1,366 @@
|
||||
Adding struct value member variable default initializer *((byte*~) $0) ← (byte) 0
|
||||
Adding struct value member variable default initializer *((byte*~) $1) ← (byte) 0
|
||||
Replacing struct member reference (struct Point) point.x with member unwinding reference *((byte*~) main::$0)
|
||||
Replacing struct member reference (struct Point) point.y with member unwinding reference *((byte*~) main::$1)
|
||||
Replacing struct member reference (struct Point) point.x with member unwinding reference *((byte*~) main::$2)
|
||||
Replacing struct member reference (struct Point) point.y with member unwinding reference *((byte*~) main::$3)
|
||||
Adding versioned struct unwinding for (struct Point) point
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte*~) $0 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) $0) ← (byte) 0
|
||||
(byte*~) $1 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) $1) ← (byte) 0
|
||||
(struct Point) point ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
*((byte*~) main::$0) ← (number) 2
|
||||
(byte*~) main::$0 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$1) ← (number) 3
|
||||
(byte*~) main::$1 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
|
||||
(byte*~) main::$2 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
|
||||
(byte*~) main::$3 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(byte*~) $0
|
||||
(byte*~) $1
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(void()) main()
|
||||
(byte*~) main::$0
|
||||
(byte*~) main::$1
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$3
|
||||
(label) main::@return
|
||||
(struct Point) point loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 2 in *((byte*~) main::$0) ← (number) 2
|
||||
Adding number conversion cast (unumber) 3 in *((byte*~) main::$1) ← (number) 3
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast *((byte*~) main::$0) ← (unumber)(number) 2
|
||||
Inlining cast *((byte*~) main::$1) ← (unumber)(number) 3
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 3
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [4] (struct Point) point ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
|
||||
Constant right-side identified [0] (byte*~) $0 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [2] (byte*~) $1 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [6] (byte*~) main::$0 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [8] (byte*~) main::$1 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [10] (byte*~) main::$2 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [12] (byte*~) main::$3 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) $0 = (byte*)&point+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) $1 = (byte*)&point+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$0 = (byte*)&point+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$1 = (byte*)&point+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$2 = (byte*)&point+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$3 = (byte*)&point+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero (byte*)&point in
|
||||
Simplifying expression containing zero (byte*)&point in
|
||||
Simplifying expression containing zero (byte*)&point in
|
||||
Simplifying expression containing zero SCREEN in [9] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$2)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$1 = (byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$2 = (byte*)&(struct Point) point
|
||||
Constant inlined main::$0 = (byte*)&(struct Point) point
|
||||
Constant inlined main::$3 = (byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined $0 = (byte*)&(struct Point) point
|
||||
Constant inlined $1 = (byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] *((byte*)&(struct Point) point) ← (byte) 0
|
||||
[1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[4] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] *((byte*)&(struct Point) point) ← (byte) 2
|
||||
[6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point)
|
||||
[8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[9] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(void()) main()
|
||||
(struct Point) point loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable point to live range equivalence class [ point ]
|
||||
Complete equivalence classes
|
||||
[ point ]
|
||||
Allocated zp[2]:2 [ point ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label point = 2
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((byte*)&(struct Point) point) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z point
|
||||
// [1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta point+OFFSET_STRUCT_POINT_Y
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [3] call main
|
||||
jsr main
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
// [5] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point
|
||||
// [6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point+OFFSET_STRUCT_POINT_Y
|
||||
// [7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point
|
||||
sta SCREEN
|
||||
// [8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [9] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *((byte*)&(struct Point) point) ← (byte) 0 [ point ] ( [ point ] ) always clobbers reg byte a
|
||||
Statement [1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ point ] ( [ point ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)&(struct Point) point) ← (byte) 2 [ point ] ( main:3 [ point ] ) always clobbers reg byte a
|
||||
Statement [6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ point ] ( main:3 [ point ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) [ point ] ( main:3 [ point ] ) always clobbers reg byte a
|
||||
Statement [8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[2]:2 [ point ] : zp[2]:2 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main]
|
||||
Uplift Scope [] 0: zp[2]:2 [ point ]
|
||||
|
||||
Uplifting [Point] best 58 combination
|
||||
Uplifting [main] best 58 combination
|
||||
Uplifting [] best 58 combination zp[2]:2 [ point ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label point = 2
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((byte*)&(struct Point) point) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z point
|
||||
// [1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta point+OFFSET_STRUCT_POINT_Y
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [3] call main
|
||||
jsr main
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
// [5] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point
|
||||
// [6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point+OFFSET_STRUCT_POINT_Y
|
||||
// [7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point
|
||||
sta SCREEN
|
||||
// [8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [9] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1:
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) point loadstore zp[2]:2
|
||||
|
||||
zp[2]:2 [ point ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 53
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label point = 2
|
||||
// @begin
|
||||
__bbegin:
|
||||
// point
|
||||
// [0] *((byte*)&(struct Point) point) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z point
|
||||
// [1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
sta point+OFFSET_STRUCT_POINT_Y
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [3] call main
|
||||
jsr main
|
||||
rts
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// point.x = 2
|
||||
// [5] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point
|
||||
// point.y = 3
|
||||
// [6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = point.x
|
||||
// [7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point
|
||||
sta SCREEN
|
||||
// SCREEN[1] = point.y
|
||||
// [8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [9] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
12
src/test/ref/struct-13.sym
Normal file
12
src/test/ref/struct-13.sym
Normal file
@ -0,0 +1,12 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) point loadstore zp[2]:2
|
||||
|
||||
zp[2]:2 [ point ]
|
18
src/test/ref/struct-14.asm
Normal file
18
src/test/ref/struct-14.asm
Normal file
@ -0,0 +1,18 @@
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
lda #2
|
||||
sta points
|
||||
lda #3
|
||||
sta points+OFFSET_STRUCT_POINT_Y
|
||||
lda points
|
||||
sta SCREEN
|
||||
lda points+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
||||
points: .fill 2*1, 0
|
20
src/test/ref/struct-14.cfg
Normal file
20
src/test/ref/struct-14.cfg
Normal file
@ -0,0 +1,20 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)(const struct Point*) points) ← (byte) 2
|
||||
[5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points)
|
||||
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
377
src/test/ref/struct-14.log
Normal file
377
src/test/ref/struct-14.log
Normal file
@ -0,0 +1,377 @@
|
||||
Fixing pointer array-indexing *((const struct Point*) points + (number) 0)
|
||||
Fixing pointer array-indexing *((const struct Point*) points + (number) 0)
|
||||
Fixing pointer array-indexing *((const struct Point*) points + (number) 0)
|
||||
Fixing pointer array-indexing *((const struct Point*) points + (number) 0)
|
||||
Rewriting struct pointer member access *((const struct Point*) points + (number~) main::$0).x
|
||||
Rewriting struct pointer member access *((const struct Point*) points + (number~) main::$1).y
|
||||
Rewriting struct pointer member access *((const struct Point*) points + (number~) main::$2).x
|
||||
Rewriting struct pointer member access *((const struct Point*) points + (number~) main::$3).y
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(number~) main::$0 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
(byte*~) main::$4 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$4 + (number~) main::$0) ← (number) 2
|
||||
(number~) main::$1 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
(byte*~) main::$5 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$5 + (number~) main::$1) ← (number) 3
|
||||
(number~) main::$2 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
(byte*~) main::$6 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$6 + (number~) main::$2)
|
||||
(number~) main::$3 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
(byte*~) main::$7 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$7 + (number~) main::$3)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
|
||||
(void()) main()
|
||||
(number~) main::$0
|
||||
(number~) main::$1
|
||||
(number~) main::$2
|
||||
(number~) main::$3
|
||||
(byte*~) main::$4
|
||||
(byte*~) main::$5
|
||||
(byte*~) main::$6
|
||||
(byte*~) main::$7
|
||||
(label) main::@return
|
||||
(const struct Point*) points[(number) 1] = { fill( 1, 0) }
|
||||
|
||||
Adding number conversion cast (unumber) 0 in (number~) main::$0 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) main::$0 in (number~) main::$0 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) 2 in *((byte*~) main::$4 + (unumber~) main::$0) ← (number) 2
|
||||
Adding number conversion cast (unumber) 0 in (number~) main::$1 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) main::$1 in (number~) main::$1 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) 3 in *((byte*~) main::$5 + (unumber~) main::$1) ← (number) 3
|
||||
Adding number conversion cast (unumber) 0 in (number~) main::$2 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) main::$2 in (number~) main::$2 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$6 + (unumber~) main::$2)
|
||||
Adding number conversion cast (unumber) 0 in (number~) main::$3 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) main::$3 in (number~) main::$3 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$7 + (unumber~) main::$3)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast *((byte*~) main::$4 + (unumber~) main::$0) ← (unumber)(number) 2
|
||||
Inlining cast *((byte*~) main::$5 + (unumber~) main::$1) ← (unumber)(number) 3
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 3
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Inferred type updated to byte in (unumber~) main::$0 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Inferred type updated to byte in (unumber~) main::$1 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Inferred type updated to byte in (unumber~) main::$2 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Inferred type updated to byte in (unumber~) main::$3 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Constant right-side identified [0] (byte~) main::$0 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Constant right-side identified [1] (byte*~) main::$4 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [3] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Constant right-side identified [4] (byte*~) main::$5 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [6] (byte~) main::$2 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Constant right-side identified [7] (byte*~) main::$6 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [9] (byte~) main::$3 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Constant right-side identified [10] (byte*~) main::$7 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) main::$0 = 0*SIZEOF_STRUCT_POINT
|
||||
Constant (const byte*) main::$4 = (byte*)points+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte) main::$1 = 0*SIZEOF_STRUCT_POINT
|
||||
Constant (const byte*) main::$5 = (byte*)points+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte) main::$2 = 0*SIZEOF_STRUCT_POINT
|
||||
Constant (const byte*) main::$6 = (byte*)points+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte) main::$3 = 0*SIZEOF_STRUCT_POINT
|
||||
Constant (const byte*) main::$7 = (byte*)points+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_POINT in
|
||||
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_POINT in
|
||||
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_POINT in
|
||||
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_POINT in
|
||||
Successful SSA optimization PassNSimplifyConstantZero
|
||||
Simplifying expression containing zero (byte*)points in
|
||||
Simplifying expression containing zero (byte*)points in
|
||||
Simplifying expression containing zero main::$4 in [2] *((const byte*) main::$4 + (const byte) main::$0) ← (byte) 2
|
||||
Simplifying expression containing zero main::$5 in [5] *((const byte*) main::$5 + (const byte) main::$1) ← (byte) 3
|
||||
Simplifying expression containing zero main::$6 in [8] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$6 + (const byte) main::$2)
|
||||
Simplifying expression containing zero SCREEN in [8] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$6)
|
||||
Simplifying expression containing zero main::$7 in [11] *((const byte*) SCREEN + (byte) 1) ← *((const byte*) main::$7 + (const byte) main::$3)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant (const byte) main::$0
|
||||
Eliminating unused constant (const byte) main::$1
|
||||
Eliminating unused constant (const byte) main::$2
|
||||
Eliminating unused constant (const byte) main::$3
|
||||
Eliminating unused constant (const byte) SIZEOF_STRUCT_POINT
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$5 = (byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$6 = (byte*)(const struct Point*) points
|
||||
Constant inlined main::$4 = (byte*)(const struct Point*) points
|
||||
Constant inlined main::$7 = (byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)(const struct Point*) points) ← (byte) 2
|
||||
[5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points)
|
||||
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(void()) main()
|
||||
|
||||
Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
// [4] *((byte*)(const struct Point*) points) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta points
|
||||
// [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta points+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda points
|
||||
sta SCREEN
|
||||
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda points+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
points: .fill 2*1, 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((byte*)(const struct Point*) points) ← (byte) 2 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [Point] best 49 combination
|
||||
Uplifting [main] best 49 combination
|
||||
Uplifting [] best 49 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
// [4] *((byte*)(const struct Point*) points) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta points
|
||||
// [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta points+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda points
|
||||
sta SCREEN
|
||||
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda points+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
points: .fill 2*1, 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const struct Point*) points[(number) 1] = { fill( 1, 0) }
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 34
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// points[0].x = 2
|
||||
// [4] *((byte*)(const struct Point*) points) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta points
|
||||
// points[0].y = 3
|
||||
// [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta points+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = points[0].x
|
||||
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda points
|
||||
sta SCREEN
|
||||
// SCREEN[1] = points[0].y
|
||||
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda points+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
points: .fill 2*1, 0
|
||||
|
11
src/test/ref/struct-14.sym
Normal file
11
src/test/ref/struct-14.sym
Normal file
@ -0,0 +1,11 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const struct Point*) points[(number) 1] = { fill( 1, 0) }
|
||||
|
26
src/test/ref/struct-15.asm
Normal file
26
src/test/ref/struct-15.asm
Normal file
@ -0,0 +1,26 @@
|
||||
// Minimal struct with C-Standard behavior - copying
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
lda #0
|
||||
sta.z point1
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
lda #2
|
||||
sta.z point1
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
lda.z point1
|
||||
sta.z point2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
lda.z point2
|
||||
sta SCREEN
|
||||
lda point2+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
24
src/test/ref/struct-15.cfg
Normal file
24
src/test/ref/struct-15.cfg
Normal file
@ -0,0 +1,24 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::point1) ← (byte) 0
|
||||
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[6] *((byte*)&(struct Point) main::point1) ← (byte) 2
|
||||
[7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1)
|
||||
[9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2)
|
||||
[11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[12] return
|
||||
to:@return
|
433
src/test/ref/struct-15.log
Normal file
433
src/test/ref/struct-15.log
Normal file
@ -0,0 +1,433 @@
|
||||
Adding struct value member variable default initializer *((byte*~) main::$0) ← (byte) 0
|
||||
Adding struct value member variable default initializer *((byte*~) main::$1) ← (byte) 0
|
||||
Adding struct value member variable copy *((byte*~) main::$2) ← *((byte*~) main::$3)
|
||||
Adding struct value member variable copy *((byte*~) main::$4) ← *((byte*~) main::$5)
|
||||
Replacing struct member reference (struct Point) main::point1.x with member unwinding reference *((byte*~) main::$6)
|
||||
Replacing struct member reference (struct Point) main::point1.y with member unwinding reference *((byte*~) main::$7)
|
||||
Replacing struct member reference (struct Point) main::point2.x with member unwinding reference *((byte*~) main::$8)
|
||||
Replacing struct member reference (struct Point) main::point2.y with member unwinding reference *((byte*~) main::$9)
|
||||
Adding versioned struct unwinding for (struct Point) main::point1
|
||||
Adding versioned struct unwinding for (struct Point) main::point2
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$0) ← (byte) 0
|
||||
(byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$1) ← (byte) 0
|
||||
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
*((byte*~) main::$6) ← (number) 2
|
||||
(byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$7) ← (number) 3
|
||||
(byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
(byte*~) main::$2 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
(byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$2) ← *((byte*~) main::$3)
|
||||
(byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
(byte*~) main::$5 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$4) ← *((byte*~) main::$5)
|
||||
(struct Point) main::point2 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$4)}
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$8)
|
||||
(byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$9)
|
||||
(byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(void()) main()
|
||||
(byte*~) main::$0
|
||||
(byte*~) main::$1
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$3
|
||||
(byte*~) main::$4
|
||||
(byte*~) main::$5
|
||||
(byte*~) main::$6
|
||||
(byte*~) main::$7
|
||||
(byte*~) main::$8
|
||||
(byte*~) main::$9
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore
|
||||
(struct Point) main::point2 loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 2 in *((byte*~) main::$6) ← (number) 2
|
||||
Adding number conversion cast (unumber) 3 in *((byte*~) main::$7) ← (number) 3
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$8)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$9)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast *((byte*~) main::$6) ← (unumber)(number) 2
|
||||
Inlining cast *((byte*~) main::$7) ← (unumber)(number) 3
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 3
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [4] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
Removing C-classic struct-unwound assignment [15] (struct Point) main::point2 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$4)}
|
||||
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [6] (byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [8] (byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [9] (byte*~) main::$2 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [10] (byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [12] (byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [13] (byte*~) main::$5 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [17] (byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [19] (byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$0 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$1 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$6 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$7 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$2 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$3 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$4 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$5 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$8 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$9 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero (byte*)&main::point2 in
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero (byte*)&main::point2 in
|
||||
Simplifying expression containing zero SCREEN in [16] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$8)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$1 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$2 = (byte*)&(struct Point) main::point2
|
||||
Constant inlined main::$0 = (byte*)&(struct Point) main::point1
|
||||
Constant inlined main::$5 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$6 = (byte*)&(struct Point) main::point1
|
||||
Constant inlined main::$3 = (byte*)&(struct Point) main::point1
|
||||
Constant inlined main::$4 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$9 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$7 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$8 = (byte*)&(struct Point) main::point2
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::point1) ← (byte) 0
|
||||
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[6] *((byte*)&(struct Point) main::point1) ← (byte) 2
|
||||
[7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1)
|
||||
[9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2)
|
||||
[11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[12] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(void()) main()
|
||||
(struct Point) main::point1 loadstore
|
||||
(struct Point) main::point2 loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::point1 to live range equivalence class [ main::point1 ]
|
||||
Added variable main::point2 to live range equivalence class [ main::point2 ]
|
||||
Complete equivalence classes
|
||||
[ main::point1 ]
|
||||
[ main::point2 ]
|
||||
Allocated zp[2]:2 [ main::point1 ]
|
||||
Allocated zp[2]:4 [ main::point2 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - copying
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point1
|
||||
sta.z point2
|
||||
// [9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point2
|
||||
sta SCREEN
|
||||
// [11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point2+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [12] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((byte*)&(struct Point) main::point1) ← (byte) 0 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Statement [6] *((byte*)&(struct Point) main::point1) ← (byte) 2 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Statement [7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Statement [8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1) [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Statement [9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) [ main::point2 ] ( main:2 [ main::point2 ] ) always clobbers reg byte a
|
||||
Statement [10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2) [ main::point2 ] ( main:2 [ main::point2 ] ) always clobbers reg byte a
|
||||
Statement [11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[2]:2 [ main::point1 ] : zp[2]:2 ,
|
||||
Potential registers zp[2]:4 [ main::point2 ] : zp[2]:4 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main] 0: zp[2]:2 [ main::point1 ] 0: zp[2]:4 [ main::point2 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [Point] best 72 combination
|
||||
Uplifting [main] best 72 combination zp[2]:2 [ main::point1 ] zp[2]:4 [ main::point2 ]
|
||||
Uplifting [] best 72 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - copying
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point1
|
||||
sta.z point2
|
||||
// [9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point2
|
||||
sta SCREEN
|
||||
// [11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point2+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [12] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
(struct Point) main::point2 loadstore zp[2]:4
|
||||
|
||||
zp[2]:2 [ main::point1 ]
|
||||
zp[2]:4 [ main::point2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 55
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - copying
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
// point1
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// point1.x = 2
|
||||
// [6] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// point1.y = 3
|
||||
// [7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// point2 = point1
|
||||
// [8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point1
|
||||
sta.z point2
|
||||
// [9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = point2.x
|
||||
// [10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point2
|
||||
sta SCREEN
|
||||
// SCREEN[1] = point2.y
|
||||
// [11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point2+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [12] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
14
src/test/ref/struct-15.sym
Normal file
14
src/test/ref/struct-15.sym
Normal file
@ -0,0 +1,14 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
(struct Point) main::point2 loadstore zp[2]:4
|
||||
|
||||
zp[2]:2 [ main::point1 ]
|
||||
zp[2]:4 [ main::point2 ]
|
18
src/test/ref/struct-16.asm
Normal file
18
src/test/ref/struct-16.asm
Normal file
@ -0,0 +1,18 @@
|
||||
// Minimal struct with C-Standard behavior - initializer
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label point1 = 2
|
||||
lda #2
|
||||
sta.z point1
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
lda.z point1
|
||||
sta SCREEN
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
20
src/test/ref/struct-16.cfg
Normal file
20
src/test/ref/struct-16.cfg
Normal file
@ -0,0 +1,20 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1)
|
||||
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
323
src/test/ref/struct-16.log
Normal file
323
src/test/ref/struct-16.log
Normal file
@ -0,0 +1,323 @@
|
||||
Adding struct value member variable copy *((byte*~) main::$0) ← (byte)(number) 2
|
||||
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 3
|
||||
Replacing struct member reference (struct Point) main::point1.x with member unwinding reference *((byte*~) main::$2)
|
||||
Replacing struct member reference (struct Point) main::point1.y with member unwinding reference *((byte*~) main::$3)
|
||||
Adding versioned struct unwinding for (struct Point) main::point1
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$0) ← (byte)(number) 2
|
||||
(byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$1) ← (byte)(number) 3
|
||||
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
|
||||
(byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
|
||||
(byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(void()) main()
|
||||
(byte*~) main::$0
|
||||
(byte*~) main::$1
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$3
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [4] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [6] (byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [8] (byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$0 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$1 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$2 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$3 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero SCREEN in [5] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$2)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$3 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$1 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$2 = (byte*)&(struct Point) main::point1
|
||||
Constant inlined main::$0 = (byte*)&(struct Point) main::point1
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1)
|
||||
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(void()) main()
|
||||
(struct Point) main::point1 loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::point1 to live range equivalence class [ main::point1 ]
|
||||
Complete equivalence classes
|
||||
[ main::point1 ]
|
||||
Allocated zp[2]:2 [ main::point1 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - initializer
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point1
|
||||
sta SCREEN
|
||||
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 [ main::point1 ] ( main:2 [ main::point1 ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::point1 ] ( main:2 [ main::point1 ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) [ main::point1 ] ( main:2 [ main::point1 ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[2]:2 [ main::point1 ] : zp[2]:2 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main] 0: zp[2]:2 [ main::point1 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [Point] best 47 combination
|
||||
Uplifting [main] best 47 combination zp[2]:2 [ main::point1 ]
|
||||
Uplifting [] best 47 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - initializer
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point1
|
||||
sta SCREEN
|
||||
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
|
||||
zp[2]:2 [ main::point1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 32
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - initializer
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
// point1 = { 2, 3 }
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = point1.x
|
||||
// [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point1
|
||||
sta SCREEN
|
||||
// SCREEN[1] = point1.y
|
||||
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
12
src/test/ref/struct-16.sym
Normal file
12
src/test/ref/struct-16.sym
Normal file
@ -0,0 +1,12 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
|
||||
zp[2]:2 [ main::point1 ]
|
32
src/test/ref/struct-17.asm
Normal file
32
src/test/ref/struct-17.asm
Normal file
@ -0,0 +1,32 @@
|
||||
// Minimal struct with C-Standard behavior - struct containing struct
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label v = 2
|
||||
lda #0
|
||||
sta.z v
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
lda #2
|
||||
sta.z v
|
||||
lda #3
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
lda #4
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
lda #5
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
rts
|
||||
}
|
28
src/test/ref/struct-17.cfg
Normal file
28
src/test/ref/struct-17.cfg
Normal file
@ -0,0 +1,28 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0
|
||||
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0
|
||||
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2
|
||||
[9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4
|
||||
[11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
|
||||
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
|
||||
[15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[16] return
|
||||
to:@return
|
595
src/test/ref/struct-17.log
Normal file
595
src/test/ref/struct-17.log
Normal file
@ -0,0 +1,595 @@
|
||||
Adding struct value member variable default initializer *((struct Point*~) main::$0) ← {}
|
||||
Adding struct value member variable default initializer *((struct Point*~) main::$1) ← {}
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$2)
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$3)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$4)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$5)
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$6)
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$7)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$8)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$9)
|
||||
Adding struct value member variable copy *((byte*~) main::$10) ← (byte) 0
|
||||
Adding struct value member variable copy *((byte*~) main::$11) ← (byte) 0
|
||||
Adding struct value member variable copy *((byte*~) main::$12) ← (byte) 0
|
||||
Adding struct value member variable copy *((byte*~) main::$13) ← (byte) 0
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$2).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$3).y
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$4).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$5).y
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$6).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$7).y
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$8).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$9).y
|
||||
Adding versioned struct unwinding for (struct Vector) main::v
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$10 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$10) ← (byte) 0
|
||||
(byte*~) main::$11 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$11) ← (byte) 0
|
||||
(struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$12 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$12) ← (byte) 0
|
||||
(byte*~) main::$13 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$13) ← (byte) 0
|
||||
(struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
|
||||
(byte*~) main::$14 ← (byte*)(struct Point*~) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$14) ← (number) 2
|
||||
(struct Point*~) main::$2 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$15 ← (byte*)(struct Point*~) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$15) ← (number) 3
|
||||
(struct Point*~) main::$3 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$16 ← (byte*)(struct Point*~) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$16) ← (number) 4
|
||||
(struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$17 ← (byte*)(struct Point*~) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$17) ← (number) 5
|
||||
(struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$18 ← (byte*)(struct Point*~) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$18)
|
||||
(struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$19 ← (byte*)(struct Point*~) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$19)
|
||||
(struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$20 ← (byte*)(struct Point*~) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$20)
|
||||
(struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$21 ← (byte*)(struct Point*~) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$21)
|
||||
(struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_P = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(struct Point*~) main::$0
|
||||
(struct Point*~) main::$1
|
||||
(byte*~) main::$10
|
||||
(byte*~) main::$11
|
||||
(byte*~) main::$12
|
||||
(byte*~) main::$13
|
||||
(byte*~) main::$14
|
||||
(byte*~) main::$15
|
||||
(byte*~) main::$16
|
||||
(byte*~) main::$17
|
||||
(byte*~) main::$18
|
||||
(byte*~) main::$19
|
||||
(struct Point*~) main::$2
|
||||
(byte*~) main::$20
|
||||
(byte*~) main::$21
|
||||
(struct Point*~) main::$3
|
||||
(struct Point*~) main::$4
|
||||
(struct Point*~) main::$5
|
||||
(struct Point*~) main::$6
|
||||
(struct Point*~) main::$7
|
||||
(struct Point*~) main::$8
|
||||
(struct Point*~) main::$9
|
||||
(label) main::@return
|
||||
(struct Vector) main::v loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 2 in *((byte*~) main::$14) ← (number) 2
|
||||
Adding number conversion cast (unumber) 3 in *((byte*~) main::$15) ← (number) 3
|
||||
Adding number conversion cast (unumber) 4 in *((byte*~) main::$16) ← (number) 4
|
||||
Adding number conversion cast (unumber) 5 in *((byte*~) main::$17) ← (number) 5
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$18)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$19)
|
||||
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$20)
|
||||
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$21)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast *((byte*~) main::$14) ← (unumber)(number) 2
|
||||
Inlining cast *((byte*~) main::$15) ← (unumber)(number) 3
|
||||
Inlining cast *((byte*~) main::$16) ← (unumber)(number) 4
|
||||
Inlining cast *((byte*~) main::$17) ← (unumber)(number) 5
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 5
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 3
|
||||
Finalized unsigned number type (byte) 4
|
||||
Finalized unsigned number type (byte) 5
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 3
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [10] (struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
|
||||
Constant right-side identified [0] (struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [5] (struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [13] (struct Point*~) main::$2 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [16] (struct Point*~) main::$3 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [19] (struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [22] (struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [25] (struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [28] (struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [31] (struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [34] (struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const struct Point*) main::$0 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$1 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const struct Point*) main::$2 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$3 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$4 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const struct Point*) main::$5 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const struct Point*) main::$6 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$7 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$8 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const struct Point*) main::$9 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte*)main::$0 in [1] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$0 in [3] (byte*~) main::$11 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$1 in [6] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$1 in [8] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$2 in [11] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$3 in [14] (byte*~) main::$15 ← (byte*)(const struct Point*) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$4 in [17] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$5 in [20] (byte*~) main::$17 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$6 in [23] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$7 in [26] (byte*~) main::$19 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$8 in [29] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$9 in [32] (byte*~) main::$21 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Converting *(pointer+n) to pointer[n] [2] *((byte*~) main::$10) ← (byte) 0 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [4] *((byte*~) main::$11) ← (byte) 0 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [7] *((byte*~) main::$12) ← (byte) 0 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [9] *((byte*~) main::$13) ← (byte) 0 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [12] *((byte*~) main::$14) ← (byte) 2 -- *((byte*)main::$2 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [15] *((byte*~) main::$15) ← (byte) 3 -- *((byte*)main::$3 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [18] *((byte*~) main::$16) ← (byte) 4 -- *((byte*)main::$4 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [21] *((byte*~) main::$17) ← (byte) 5 -- *((byte*)main::$5 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [24] *((const byte*) SCREEN + (byte) 0) ← *((byte*~) main::$18) -- *((byte*)main::$6 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [27] *((const byte*) SCREEN + (byte) 1) ← *((byte*~) main::$19) -- *((byte*)main::$7 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [30] *((const byte*) SCREEN + (byte) 2) ← *((byte*~) main::$20) -- *((byte*)main::$8 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [33] *((const byte*) SCREEN + (byte) 3) ← *((byte*~) main::$21) -- *((byte*)main::$9 + OFFSET_STRUCT_POINT_Y)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (byte*)main::$0 in [1] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$0 in [2] *((byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 0
|
||||
Simplifying expression containing zero (byte*)main::$1 in [6] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$1 in [7] *((byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 0
|
||||
Simplifying expression containing zero (byte*)main::$2 in [11] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$2 in [12] *((byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
|
||||
Simplifying expression containing zero (byte*)main::$4 in [17] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$4 in [18] *((byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
|
||||
Simplifying expression containing zero (byte*)main::$6 in [23] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$6 in [24] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X)
|
||||
Simplifying expression containing zero SCREEN in [24] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$6)
|
||||
Simplifying expression containing zero (byte*)main::$8 in [29] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$8 in [30] *((const byte*) SCREEN + (byte) 2) ← *((byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (byte*~) main::$10 and assignment [0] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$0
|
||||
Eliminating unused variable (byte*~) main::$11 and assignment [2] (byte*~) main::$11 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$12 and assignment [4] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$1
|
||||
Eliminating unused variable (byte*~) main::$13 and assignment [6] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$14 and assignment [8] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$2
|
||||
Eliminating unused variable (byte*~) main::$15 and assignment [10] (byte*~) main::$15 ← (byte*)(const struct Point*) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$16 and assignment [12] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$4
|
||||
Eliminating unused variable (byte*~) main::$17 and assignment [14] (byte*~) main::$17 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$18 and assignment [16] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6
|
||||
Eliminating unused variable (byte*~) main::$19 and assignment [18] (byte*~) main::$19 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$20 and assignment [20] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8
|
||||
Eliminating unused variable (byte*~) main::$21 and assignment [22] (byte*~) main::$21 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$1 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$2 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$0 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$5 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$6 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$3 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$4 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$9 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$7 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$8 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Consolidated array index constant in *(SCREEN+2)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+3)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0
|
||||
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0
|
||||
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2
|
||||
[9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4
|
||||
[11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
|
||||
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
|
||||
[15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[16] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(struct Vector) main::v loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::v to live range equivalence class [ main::v ]
|
||||
Complete equivalence classes
|
||||
[ main::v ]
|
||||
Allocated zp[4]:2 [ main::v ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label v = 2
|
||||
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z v
|
||||
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z v
|
||||
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[4]:2 [ main::v ] : zp[4]:2 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [Vector]
|
||||
Uplift Scope [main] 0: zp[4]:2 [ main::v ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [Point] best 98 combination
|
||||
Uplifting [Vector] best 98 combination
|
||||
Uplifting [main] best 98 combination zp[4]:2 [ main::v ]
|
||||
Uplifting [] best 98 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label v = 2
|
||||
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z v
|
||||
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z v
|
||||
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #0
|
||||
Removing instruction lda #0
|
||||
Removing instruction lda #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Vector) main::v loadstore zp[4]:2
|
||||
|
||||
zp[4]:2 [ main::v ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 77
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label v = 2
|
||||
// v
|
||||
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z v
|
||||
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// v.p.x = 2
|
||||
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z v
|
||||
// v.p.y = 3
|
||||
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// v.q.x = 4
|
||||
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// v.q.y = 5
|
||||
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = v.p.x
|
||||
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// SCREEN[1] = v.p.y
|
||||
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// SCREEN[2] = v.q.x
|
||||
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// SCREEN[3] = v.q.y
|
||||
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
// main::@return
|
||||
// }
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
15
src/test/ref/struct-17.sym
Normal file
15
src/test/ref/struct-17.sym
Normal file
@ -0,0 +1,15 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Vector) main::v loadstore zp[4]:2
|
||||
|
||||
zp[4]:2 [ main::v ]
|
27
src/test/ref/struct-18.asm
Normal file
27
src/test/ref/struct-18.asm
Normal file
@ -0,0 +1,27 @@
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label v = 2
|
||||
lda #2
|
||||
sta.z v
|
||||
lda #3
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
lda #4
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
lda #5
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
rts
|
||||
}
|
24
src/test/ref/struct-18.cfg
Normal file
24
src/test/ref/struct-18.cfg
Normal file
@ -0,0 +1,24 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2
|
||||
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4
|
||||
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
|
||||
[9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
|
||||
[11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[12] return
|
||||
to:@return
|
473
src/test/ref/struct-18.log
Normal file
473
src/test/ref/struct-18.log
Normal file
@ -0,0 +1,473 @@
|
||||
Adding struct value member variable copy *((struct Point*~) main::$0) ← { x: (byte)(number) 2, y: (byte)(number) 3 }
|
||||
Adding struct value member variable copy *((struct Point*~) main::$1) ← { x: (byte)(number) 4, y: (byte)(number) 5 }
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$2)
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$3)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$4)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$5)
|
||||
Adding struct value member variable copy *((byte*~) main::$6) ← (byte)(number) 2
|
||||
Adding struct value member variable copy *((byte*~) main::$7) ← (byte)(number) 3
|
||||
Adding struct value member variable copy *((byte*~) main::$8) ← (byte)(number) 4
|
||||
Adding struct value member variable copy *((byte*~) main::$9) ← (byte)(number) 5
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$2).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$3).y
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$4).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$5).y
|
||||
Adding versioned struct unwinding for (struct Vector) main::v
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$6 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$6) ← (byte)(number) 2
|
||||
(byte*~) main::$7 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$7) ← (byte)(number) 3
|
||||
(struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$8 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$8) ← (byte)(number) 4
|
||||
(byte*~) main::$9 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$9) ← (byte)(number) 5
|
||||
(struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
|
||||
(byte*~) main::$10 ← (byte*)(struct Point*~) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$10)
|
||||
(struct Point*~) main::$2 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$11 ← (byte*)(struct Point*~) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$11)
|
||||
(struct Point*~) main::$3 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$12 ← (byte*)(struct Point*~) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$12)
|
||||
(struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$13 ← (byte*)(struct Point*~) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$13)
|
||||
(struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_P = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(struct Point*~) main::$0
|
||||
(struct Point*~) main::$1
|
||||
(byte*~) main::$10
|
||||
(byte*~) main::$11
|
||||
(byte*~) main::$12
|
||||
(byte*~) main::$13
|
||||
(struct Point*~) main::$2
|
||||
(struct Point*~) main::$3
|
||||
(struct Point*~) main::$4
|
||||
(struct Point*~) main::$5
|
||||
(byte*~) main::$6
|
||||
(byte*~) main::$7
|
||||
(byte*~) main::$8
|
||||
(byte*~) main::$9
|
||||
(label) main::@return
|
||||
(struct Vector) main::v loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$10)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$11)
|
||||
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$12)
|
||||
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$13)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 5
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 3
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [10] (struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
|
||||
Constant right-side identified [0] (struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [5] (struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [13] (struct Point*~) main::$2 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [16] (struct Point*~) main::$3 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [19] (struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [22] (struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const struct Point*) main::$0 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$1 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const struct Point*) main::$2 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$3 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$4 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const struct Point*) main::$5 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte*)main::$0 in [1] (byte*~) main::$6 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$0 in [3] (byte*~) main::$7 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$1 in [6] (byte*~) main::$8 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$1 in [8] (byte*~) main::$9 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$2 in [11] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$3 in [14] (byte*~) main::$11 ← (byte*)(const struct Point*) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$4 in [17] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$5 in [20] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Converting *(pointer+n) to pointer[n] [2] *((byte*~) main::$6) ← (byte) 2 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [4] *((byte*~) main::$7) ← (byte) 3 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [7] *((byte*~) main::$8) ← (byte) 4 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [9] *((byte*~) main::$9) ← (byte) 5 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [12] *((const byte*) SCREEN + (byte) 0) ← *((byte*~) main::$10) -- *((byte*)main::$2 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [15] *((const byte*) SCREEN + (byte) 1) ← *((byte*~) main::$11) -- *((byte*)main::$3 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [18] *((const byte*) SCREEN + (byte) 2) ← *((byte*~) main::$12) -- *((byte*)main::$4 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [21] *((const byte*) SCREEN + (byte) 3) ← *((byte*~) main::$13) -- *((byte*)main::$5 + OFFSET_STRUCT_POINT_Y)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (byte*)main::$0 in [1] (byte*~) main::$6 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$0 in [2] *((byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
|
||||
Simplifying expression containing zero (byte*)main::$1 in [6] (byte*~) main::$8 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$1 in [7] *((byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
|
||||
Simplifying expression containing zero (byte*)main::$2 in [11] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$2 in [12] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X)
|
||||
Simplifying expression containing zero SCREEN in [12] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$2)
|
||||
Simplifying expression containing zero (byte*)main::$4 in [17] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$4 in [18] *((const byte*) SCREEN + (byte) 2) ← *((byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (byte*~) main::$6 and assignment [0] (byte*~) main::$6 ← (byte*)(const struct Point*) main::$0
|
||||
Eliminating unused variable (byte*~) main::$7 and assignment [2] (byte*~) main::$7 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$8 and assignment [4] (byte*~) main::$8 ← (byte*)(const struct Point*) main::$1
|
||||
Eliminating unused variable (byte*~) main::$9 and assignment [6] (byte*~) main::$9 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$10 and assignment [8] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$2
|
||||
Eliminating unused variable (byte*~) main::$11 and assignment [10] (byte*~) main::$11 ← (byte*)(const struct Point*) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$12 and assignment [12] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4
|
||||
Eliminating unused variable (byte*~) main::$13 and assignment [14] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$1 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$2 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$0 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$5 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$3 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$4 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Consolidated array index constant in *(SCREEN+2)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+3)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2
|
||||
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4
|
||||
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
|
||||
[9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
|
||||
[11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[12] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(struct Vector) main::v loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::v to live range equivalence class [ main::v ]
|
||||
Complete equivalence classes
|
||||
[ main::v ]
|
||||
Allocated zp[4]:2 [ main::v ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label v = 2
|
||||
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z v
|
||||
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// [9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// [11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [12] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[4]:2 [ main::v ] : zp[4]:2 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [Vector]
|
||||
Uplift Scope [main] 0: zp[4]:2 [ main::v ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [Point] best 75 combination
|
||||
Uplifting [Vector] best 75 combination
|
||||
Uplifting [main] best 75 combination zp[4]:2 [ main::v ]
|
||||
Uplifting [] best 75 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label v = 2
|
||||
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z v
|
||||
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// [9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// [11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [12] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Vector) main::v loadstore zp[4]:2
|
||||
|
||||
zp[4]:2 [ main::v ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 60
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label v = 2
|
||||
// v = { {2, 3}, {4, 5} }
|
||||
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z v
|
||||
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = v.p.x
|
||||
// [8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// SCREEN[1] = v.p.y
|
||||
// [9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// SCREEN[2] = v.q.x
|
||||
// [10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// SCREEN[3] = v.q.y
|
||||
// [11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
// main::@return
|
||||
// }
|
||||
// [12] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
15
src/test/ref/struct-18.sym
Normal file
15
src/test/ref/struct-18.sym
Normal file
@ -0,0 +1,15 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Vector) main::v loadstore zp[4]:2
|
||||
|
||||
zp[4]:2 [ main::v ]
|
42
src/test/ref/struct-19.asm
Normal file
42
src/test/ref/struct-19.asm
Normal file
@ -0,0 +1,42 @@
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label v = 2
|
||||
.label p1 = 6
|
||||
.label p2 = 8
|
||||
lda #0
|
||||
sta.z v
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
lda #2
|
||||
sta.z p1
|
||||
lda #3
|
||||
sta p1+OFFSET_STRUCT_POINT_Y
|
||||
lda #4
|
||||
sta.z p2
|
||||
lda #5
|
||||
sta p2+OFFSET_STRUCT_POINT_Y
|
||||
lda.z p1
|
||||
sta.z v
|
||||
lda p1+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
lda.z p2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
lda p2+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
rts
|
||||
}
|
32
src/test/ref/struct-19.cfg
Normal file
32
src/test/ref/struct-19.cfg
Normal file
@ -0,0 +1,32 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0
|
||||
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0
|
||||
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[8] *((byte*)&(struct Point) main::p1) ← (byte) 2
|
||||
[9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[10] *((byte*)&(struct Point) main::p2) ← (byte) 4
|
||||
[11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1)
|
||||
[13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2)
|
||||
[15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
|
||||
[17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
|
||||
[19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[20] return
|
||||
to:@return
|
693
src/test/ref/struct-19.log
Normal file
693
src/test/ref/struct-19.log
Normal file
@ -0,0 +1,693 @@
|
||||
Adding struct value member variable default initializer *((struct Point*~) main::$0) ← {}
|
||||
Adding struct value member variable default initializer *((struct Point*~) main::$1) ← {}
|
||||
Adding struct value member variable copy *((byte*~) main::$2) ← (byte)(number) 2
|
||||
Adding struct value member variable copy *((byte*~) main::$3) ← (byte)(number) 3
|
||||
Adding struct value member variable copy *((byte*~) main::$4) ← (byte)(number) 4
|
||||
Adding struct value member variable copy *((byte*~) main::$5) ← (byte)(number) 5
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$6)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$7)
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$8)
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$9)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$10)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$11)
|
||||
Adding struct value member variable copy *((byte*~) main::$12) ← (byte) 0
|
||||
Adding struct value member variable copy *((byte*~) main::$13) ← (byte) 0
|
||||
Adding struct value member variable copy *((byte*~) main::$14) ← (byte) 0
|
||||
Adding struct value member variable copy *((byte*~) main::$15) ← (byte) 0
|
||||
Adding struct value member variable copy *((byte*~) main::$16) ← *((byte*~) main::$17)
|
||||
Adding struct value member variable copy *((byte*~) main::$18) ← *((byte*~) main::$19)
|
||||
Adding struct value member variable copy *((byte*~) main::$20) ← *((byte*~) main::$21)
|
||||
Adding struct value member variable copy *((byte*~) main::$22) ← *((byte*~) main::$23)
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$8).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$9).y
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$10).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$11).y
|
||||
Adding versioned struct unwinding for (struct Vector) main::v
|
||||
Adding versioned struct unwinding for (struct Point) main::p1
|
||||
Adding versioned struct unwinding for (struct Point) main::p2
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$12 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$12) ← (byte) 0
|
||||
(byte*~) main::$13 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$13) ← (byte) 0
|
||||
(struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$14 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$14) ← (byte) 0
|
||||
(byte*~) main::$15 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$15) ← (byte) 0
|
||||
(struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
|
||||
(byte*~) main::$2 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$2) ← (byte)(number) 2
|
||||
(byte*~) main::$3 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$3) ← (byte)(number) 3
|
||||
(struct Point) main::p1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
|
||||
(byte*~) main::$4 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$4) ← (byte)(number) 4
|
||||
(byte*~) main::$5 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$5) ← (byte)(number) 5
|
||||
(struct Point) main::p2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
|
||||
(byte*~) main::$16 ← (byte*)(struct Point*~) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
(byte*~) main::$17 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$16) ← *((byte*~) main::$17)
|
||||
(byte*~) main::$18 ← (byte*)(struct Point*~) main::$6 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
(byte*~) main::$19 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$18) ← *((byte*~) main::$19)
|
||||
(struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$20 ← (byte*)(struct Point*~) main::$7 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
(byte*~) main::$21 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$20) ← *((byte*~) main::$21)
|
||||
(byte*~) main::$22 ← (byte*)(struct Point*~) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
(byte*~) main::$23 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$22) ← *((byte*~) main::$23)
|
||||
(struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$24 ← (byte*)(struct Point*~) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$24)
|
||||
(struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$25 ← (byte*)(struct Point*~) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$25)
|
||||
(struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$26 ← (byte*)(struct Point*~) main::$10 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$26)
|
||||
(struct Point*~) main::$10 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$27 ← (byte*)(struct Point*~) main::$11 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$27)
|
||||
(struct Point*~) main::$11 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_P = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(struct Point*~) main::$0
|
||||
(struct Point*~) main::$1
|
||||
(struct Point*~) main::$10
|
||||
(struct Point*~) main::$11
|
||||
(byte*~) main::$12
|
||||
(byte*~) main::$13
|
||||
(byte*~) main::$14
|
||||
(byte*~) main::$15
|
||||
(byte*~) main::$16
|
||||
(byte*~) main::$17
|
||||
(byte*~) main::$18
|
||||
(byte*~) main::$19
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$20
|
||||
(byte*~) main::$21
|
||||
(byte*~) main::$22
|
||||
(byte*~) main::$23
|
||||
(byte*~) main::$24
|
||||
(byte*~) main::$25
|
||||
(byte*~) main::$26
|
||||
(byte*~) main::$27
|
||||
(byte*~) main::$3
|
||||
(byte*~) main::$4
|
||||
(byte*~) main::$5
|
||||
(struct Point*~) main::$6
|
||||
(struct Point*~) main::$7
|
||||
(struct Point*~) main::$8
|
||||
(struct Point*~) main::$9
|
||||
(label) main::@return
|
||||
(struct Point) main::p1 loadstore
|
||||
(struct Point) main::p2 loadstore
|
||||
(struct Vector) main::v loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$24)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$25)
|
||||
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$26)
|
||||
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$27)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 5
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 3
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [10] (struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
|
||||
Removing C-classic struct-unwound assignment [15] (struct Point) main::p1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
|
||||
Removing C-classic struct-unwound assignment [20] (struct Point) main::p2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
|
||||
Constant right-side identified [0] (struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [5] (struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [11] (byte*~) main::$2 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [13] (byte*~) main::$3 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [16] (byte*~) main::$4 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [18] (byte*~) main::$5 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [22] (byte*~) main::$17 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [25] (byte*~) main::$19 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [27] (struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [29] (byte*~) main::$21 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [32] (byte*~) main::$23 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [34] (struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [37] (struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [40] (struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [43] (struct Point*~) main::$10 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [46] (struct Point*~) main::$11 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const struct Point*) main::$0 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$1 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const byte*) main::$2 = (byte*)&main::p1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$3 = (byte*)&main::p1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$4 = (byte*)&main::p2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$5 = (byte*)&main::p2+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$17 = (byte*)&main::p1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$19 = (byte*)&main::p1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const struct Point*) main::$6 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const byte*) main::$21 = (byte*)&main::p2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$23 = (byte*)&main::p2+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const struct Point*) main::$7 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const struct Point*) main::$8 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$9 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$10 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const struct Point*) main::$11 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte*)main::$0 in [1] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$0 in [3] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$1 in [6] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$1 in [8] (byte*~) main::$15 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$6 in [21] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$6 in [24] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$7 in [28] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$7 in [31] (byte*~) main::$22 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$8 in [35] (byte*~) main::$24 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$9 in [38] (byte*~) main::$25 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$10 in [41] (byte*~) main::$26 ← (byte*)(const struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$11 in [44] (byte*~) main::$27 ← (byte*)(const struct Point*) main::$11 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Converting *(pointer+n) to pointer[n] [2] *((byte*~) main::$12) ← (byte) 0 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [4] *((byte*~) main::$13) ← (byte) 0 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [7] *((byte*~) main::$14) ← (byte) 0 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [9] *((byte*~) main::$15) ← (byte) 0 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [23] *((byte*~) main::$16) ← *((const byte*) main::$17) -- *((byte*)main::$6 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [26] *((byte*~) main::$18) ← *((const byte*) main::$19) -- *((byte*)main::$6 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [30] *((byte*~) main::$20) ← *((const byte*) main::$21) -- *((byte*)main::$7 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [33] *((byte*~) main::$22) ← *((const byte*) main::$23) -- *((byte*)main::$7 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [36] *((const byte*) SCREEN + (byte) 0) ← *((byte*~) main::$24) -- *((byte*)main::$8 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [39] *((const byte*) SCREEN + (byte) 1) ← *((byte*~) main::$25) -- *((byte*)main::$9 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [42] *((const byte*) SCREEN + (byte) 2) ← *((byte*~) main::$26) -- *((byte*)main::$10 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [45] *((const byte*) SCREEN + (byte) 3) ← *((byte*~) main::$27) -- *((byte*)main::$11 + OFFSET_STRUCT_POINT_Y)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (byte*)&main::p1 in
|
||||
Simplifying expression containing zero (byte*)&main::p2 in
|
||||
Simplifying expression containing zero (byte*)&main::p1 in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (byte*)&main::p2 in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (byte*)main::$0 in [1] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$0 in [2] *((byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 0
|
||||
Simplifying expression containing zero (byte*)main::$1 in [6] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$1 in [7] *((byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 0
|
||||
Simplifying expression containing zero (byte*)main::$6 in [21] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$6 in [23] *((byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X) ← *((const byte*) main::$17)
|
||||
Simplifying expression containing zero (byte*)main::$7 in [28] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$7 in [30] *((byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_X) ← *((const byte*) main::$21)
|
||||
Simplifying expression containing zero (byte*)main::$8 in [35] (byte*~) main::$24 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$8 in [36] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X)
|
||||
Simplifying expression containing zero SCREEN in [36] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$8)
|
||||
Simplifying expression containing zero (byte*)main::$10 in [41] (byte*~) main::$26 ← (byte*)(const struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$10 in [42] *((const byte*) SCREEN + (byte) 2) ← *((byte*)(const struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_X)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (byte*~) main::$12 and assignment [0] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$0
|
||||
Eliminating unused variable (byte*~) main::$13 and assignment [2] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$14 and assignment [4] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$1
|
||||
Eliminating unused variable (byte*~) main::$15 and assignment [6] (byte*~) main::$15 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$16 and assignment [12] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$6
|
||||
Eliminating unused variable (byte*~) main::$18 and assignment [14] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$20 and assignment [16] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$7
|
||||
Eliminating unused variable (byte*~) main::$22 and assignment [18] (byte*~) main::$22 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$24 and assignment [20] (byte*~) main::$24 ← (byte*)(const struct Point*) main::$8
|
||||
Eliminating unused variable (byte*~) main::$25 and assignment [22] (byte*~) main::$25 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$26 and assignment [24] (byte*~) main::$26 ← (byte*)(const struct Point*) main::$10
|
||||
Eliminating unused variable (byte*~) main::$27 and assignment [26] (byte*~) main::$27 ← (byte*)(const struct Point*) main::$11 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$23 = (byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$21 = (byte*)&(struct Point) main::p2
|
||||
Constant inlined main::$10 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$11 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$1 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$2 = (byte*)&(struct Point) main::p1
|
||||
Constant inlined main::$17 = (byte*)&(struct Point) main::p1
|
||||
Constant inlined main::$0 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$19 = (byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$5 = (byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$6 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$3 = (byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$4 = (byte*)&(struct Point) main::p2
|
||||
Constant inlined main::$9 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$7 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$8 = (struct Point*)&(struct Vector) main::v
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Consolidated array index constant in *(SCREEN+2)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+3)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0
|
||||
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0
|
||||
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
|
||||
[8] *((byte*)&(struct Point) main::p1) ← (byte) 2
|
||||
[9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[10] *((byte*)&(struct Point) main::p2) ← (byte) 4
|
||||
[11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1)
|
||||
[13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2)
|
||||
[15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
|
||||
[17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
|
||||
[19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[20] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(struct Point) main::p1 loadstore
|
||||
(struct Point) main::p2 loadstore
|
||||
(struct Vector) main::v loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::v to live range equivalence class [ main::v ]
|
||||
Added variable main::p1 to live range equivalence class [ main::p1 ]
|
||||
Added variable main::p2 to live range equivalence class [ main::p2 ]
|
||||
Complete equivalence classes
|
||||
[ main::v ]
|
||||
[ main::p1 ]
|
||||
[ main::p2 ]
|
||||
Allocated zp[4]:2 [ main::v ]
|
||||
Allocated zp[2]:6 [ main::p1 ]
|
||||
Allocated zp[2]:8 [ main::p2 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label v = 2
|
||||
.label p1 = 6
|
||||
.label p2 = 8
|
||||
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z v
|
||||
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p1
|
||||
// [9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta p1+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z p2
|
||||
// [11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta p2+OFFSET_STRUCT_POINT_Y
|
||||
// [12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p1
|
||||
sta.z v
|
||||
// [13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p1+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p2+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// [17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// [19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [20] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
|
||||
Statement [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
|
||||
Statement [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
|
||||
Statement [8] *((byte*)&(struct Point) main::p1) ← (byte) 2 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
|
||||
Statement [9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
|
||||
Statement [10] *((byte*)&(struct Point) main::p2) ← (byte) 4 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
|
||||
Statement [11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
|
||||
Statement [12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
|
||||
Statement [13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v main::p2 ] ( main:2 [ main::v main::p2 ] ) always clobbers reg byte a
|
||||
Statement [14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) [ main::v main::p2 ] ( main:2 [ main::v main::p2 ] ) always clobbers reg byte a
|
||||
Statement [15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[4]:2 [ main::v ] : zp[4]:2 ,
|
||||
Potential registers zp[2]:6 [ main::p1 ] : zp[2]:6 ,
|
||||
Potential registers zp[2]:8 [ main::p2 ] : zp[2]:8 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [Vector]
|
||||
Uplift Scope [main] 0: zp[4]:2 [ main::v ] 0: zp[2]:6 [ main::p1 ] 0: zp[2]:8 [ main::p2 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [Point] best 126 combination
|
||||
Uplifting [Vector] best 126 combination
|
||||
Uplifting [main] best 126 combination zp[4]:2 [ main::v ] zp[2]:6 [ main::p1 ] zp[2]:8 [ main::p2 ]
|
||||
Uplifting [] best 126 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label v = 2
|
||||
.label p1 = 6
|
||||
.label p2 = 8
|
||||
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z v
|
||||
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p1
|
||||
// [9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta p1+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z p2
|
||||
// [11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta p2+OFFSET_STRUCT_POINT_Y
|
||||
// [12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p1
|
||||
sta.z v
|
||||
// [13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p1+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p2+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// [17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// [19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [20] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #0
|
||||
Removing instruction lda #0
|
||||
Removing instruction lda #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::p1 loadstore zp[2]:6
|
||||
(struct Point) main::p2 loadstore zp[2]:8
|
||||
(struct Vector) main::v loadstore zp[4]:2
|
||||
|
||||
zp[4]:2 [ main::v ]
|
||||
zp[2]:6 [ main::p1 ]
|
||||
zp[2]:8 [ main::p2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 105
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label v = 2
|
||||
.label p1 = 6
|
||||
.label p2 = 8
|
||||
// v
|
||||
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta.z v
|
||||
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// p1 = { 2, 3 }
|
||||
// [8] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p1
|
||||
// [9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta p1+OFFSET_STRUCT_POINT_Y
|
||||
// p2 = { 4, 5 }
|
||||
// [10] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z p2
|
||||
// [11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta p2+OFFSET_STRUCT_POINT_Y
|
||||
// v.p = p1
|
||||
// [12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p1
|
||||
sta.z v
|
||||
// [13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p1+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// v.q = p2
|
||||
// [14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p2+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = v.p.x
|
||||
// [16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// SCREEN[1] = v.p.y
|
||||
// [17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// SCREEN[2] = v.q.x
|
||||
// [18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// SCREEN[3] = v.q.y
|
||||
// [19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
// main::@return
|
||||
// }
|
||||
// [20] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
19
src/test/ref/struct-19.sym
Normal file
19
src/test/ref/struct-19.sym
Normal file
@ -0,0 +1,19 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::p1 loadstore zp[2]:6
|
||||
(struct Point) main::p2 loadstore zp[2]:8
|
||||
(struct Vector) main::v loadstore zp[4]:2
|
||||
|
||||
zp[4]:2 [ main::v ]
|
||||
zp[2]:6 [ main::p1 ]
|
||||
zp[2]:8 [ main::p2 ]
|
37
src/test/ref/struct-20.asm
Normal file
37
src/test/ref/struct-20.asm
Normal file
@ -0,0 +1,37 @@
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
main: {
|
||||
.label p1 = 2
|
||||
.label p2 = 4
|
||||
.label v = 6
|
||||
lda #2
|
||||
sta.z p1
|
||||
lda #3
|
||||
sta p1+OFFSET_STRUCT_POINT_Y
|
||||
lda #4
|
||||
sta.z p2
|
||||
lda #5
|
||||
sta p2+OFFSET_STRUCT_POINT_Y
|
||||
lda.z p1
|
||||
sta.z v
|
||||
lda p1+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
lda.z p2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
lda p2+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
rts
|
||||
}
|
28
src/test/ref/struct-20.cfg
Normal file
28
src/test/ref/struct-20.cfg
Normal file
@ -0,0 +1,28 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::p1) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((byte*)&(struct Point) main::p2) ← (byte) 4
|
||||
[7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1)
|
||||
[9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2)
|
||||
[11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
|
||||
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
|
||||
[15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[16] return
|
||||
to:@return
|
599
src/test/ref/struct-20.log
Normal file
599
src/test/ref/struct-20.log
Normal file
@ -0,0 +1,599 @@
|
||||
Adding struct value member variable copy *((byte*~) main::$0) ← (byte)(number) 2
|
||||
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 3
|
||||
Adding struct value member variable copy *((byte*~) main::$2) ← (byte)(number) 4
|
||||
Adding struct value member variable copy *((byte*~) main::$3) ← (byte)(number) 5
|
||||
Adding struct value list initializer *((struct Point*~) main::$4) ← (struct Point) main::p1
|
||||
Adding struct value list initializer *((struct Point*~) main::$5) ← (struct Point) main::p2
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$6)
|
||||
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$7)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$8)
|
||||
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$9)
|
||||
Adding struct value member variable copy *((byte*~) main::$10) ← *((byte*~) main::$11)
|
||||
Adding struct value member variable copy *((byte*~) main::$12) ← *((byte*~) main::$13)
|
||||
Adding struct value member variable copy *((byte*~) main::$14) ← *((byte*~) main::$15)
|
||||
Adding struct value member variable copy *((byte*~) main::$16) ← *((byte*~) main::$17)
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$6).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$7).y
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$8).x
|
||||
Rewriting struct pointer member access *((struct Point*~) main::$9).y
|
||||
Adding versioned struct unwinding for (struct Point) main::p1
|
||||
Adding versioned struct unwinding for (struct Point) main::p2
|
||||
Adding versioned struct unwinding for (struct Vector) main::v
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(byte*~) main::$0 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$0) ← (byte)(number) 2
|
||||
(byte*~) main::$1 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$1) ← (byte)(number) 3
|
||||
(struct Point) main::p1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
(byte*~) main::$2 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$2) ← (byte)(number) 4
|
||||
(byte*~) main::$3 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$3) ← (byte)(number) 5
|
||||
(struct Point) main::p2 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
|
||||
(struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$10 ← (byte*)(struct Point*~) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
(byte*~) main::$11 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$10) ← *((byte*~) main::$11)
|
||||
(byte*~) main::$12 ← (byte*)(struct Point*~) main::$4 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
(byte*~) main::$13 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$12) ← *((byte*~) main::$13)
|
||||
(struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$14 ← (byte*)(struct Point*~) main::$5 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
(byte*~) main::$15 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$14) ← *((byte*~) main::$15)
|
||||
(byte*~) main::$16 ← (byte*)(struct Point*~) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
(byte*~) main::$17 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$16) ← *((byte*~) main::$17)
|
||||
(struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$4), *((struct Point*~) main::$5)}
|
||||
(byte*~) main::$18 ← (byte*)(struct Point*~) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$18)
|
||||
(struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$19 ← (byte*)(struct Point*~) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$19)
|
||||
(struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
(byte*~) main::$20 ← (byte*)(struct Point*~) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$20)
|
||||
(struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
(byte*~) main::$21 ← (byte*)(struct Point*~) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$21)
|
||||
(struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_P = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(byte*~) main::$0
|
||||
(byte*~) main::$1
|
||||
(byte*~) main::$10
|
||||
(byte*~) main::$11
|
||||
(byte*~) main::$12
|
||||
(byte*~) main::$13
|
||||
(byte*~) main::$14
|
||||
(byte*~) main::$15
|
||||
(byte*~) main::$16
|
||||
(byte*~) main::$17
|
||||
(byte*~) main::$18
|
||||
(byte*~) main::$19
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$20
|
||||
(byte*~) main::$21
|
||||
(byte*~) main::$3
|
||||
(struct Point*~) main::$4
|
||||
(struct Point*~) main::$5
|
||||
(struct Point*~) main::$6
|
||||
(struct Point*~) main::$7
|
||||
(struct Point*~) main::$8
|
||||
(struct Point*~) main::$9
|
||||
(label) main::@return
|
||||
(struct Point) main::p1 loadstore
|
||||
(struct Point) main::p2 loadstore
|
||||
(struct Vector) main::v loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$18)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$19)
|
||||
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$20)
|
||||
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$21)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 5
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 3
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [4] (struct Point) main::p1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
Removing C-classic struct-unwound assignment [9] (struct Point) main::p2 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
|
||||
Removing C-classic struct-unwound assignment [24] (struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$4), *((struct Point*~) main::$5)}
|
||||
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [5] (byte*~) main::$2 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [7] (byte*~) main::$3 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [10] (struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [12] (byte*~) main::$11 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [15] (byte*~) main::$13 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [17] (struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [19] (byte*~) main::$15 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [22] (byte*~) main::$17 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [27] (struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [30] (struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Constant right-side identified [33] (struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant right-side identified [36] (struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$0 = (byte*)&main::p1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$1 = (byte*)&main::p1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$2 = (byte*)&main::p2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$3 = (byte*)&main::p2+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const struct Point*) main::$4 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const byte*) main::$11 = (byte*)&main::p1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$13 = (byte*)&main::p1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const struct Point*) main::$5 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const byte*) main::$15 = (byte*)&main::p2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$17 = (byte*)&main::p2+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const struct Point*) main::$6 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$7 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
|
||||
Constant (const struct Point*) main::$8 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Constant (const struct Point*) main::$9 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte*)main::$4 in [11] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$4 in [14] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$5 in [18] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$5 in [21] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$6 in [25] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$7 in [28] (byte*~) main::$19 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)main::$8 in [31] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)main::$9 in [34] (byte*~) main::$21 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Converting *(pointer+n) to pointer[n] [13] *((byte*~) main::$10) ← *((const byte*) main::$11) -- *((byte*)main::$4 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [16] *((byte*~) main::$12) ← *((const byte*) main::$13) -- *((byte*)main::$4 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [20] *((byte*~) main::$14) ← *((const byte*) main::$15) -- *((byte*)main::$5 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [23] *((byte*~) main::$16) ← *((const byte*) main::$17) -- *((byte*)main::$5 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [26] *((const byte*) SCREEN + (byte) 0) ← *((byte*~) main::$18) -- *((byte*)main::$6 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [29] *((const byte*) SCREEN + (byte) 1) ← *((byte*~) main::$19) -- *((byte*)main::$7 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [32] *((const byte*) SCREEN + (byte) 2) ← *((byte*~) main::$20) -- *((byte*)main::$8 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [35] *((const byte*) SCREEN + (byte) 3) ← *((byte*~) main::$21) -- *((byte*)main::$9 + OFFSET_STRUCT_POINT_Y)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying expression containing zero (byte*)&main::p1 in
|
||||
Simplifying expression containing zero (byte*)&main::p2 in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (byte*)&main::p1 in
|
||||
Simplifying expression containing zero (byte*)&main::p2 in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (struct Point*)&main::v in
|
||||
Simplifying expression containing zero (byte*)main::$4 in [11] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$4 in [13] *((byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X) ← *((const byte*) main::$11)
|
||||
Simplifying expression containing zero (byte*)main::$5 in [18] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$5 in [20] *((byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_X) ← *((const byte*) main::$15)
|
||||
Simplifying expression containing zero (byte*)main::$6 in [25] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$6 in [26] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X)
|
||||
Simplifying expression containing zero SCREEN in [26] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$6)
|
||||
Simplifying expression containing zero (byte*)main::$8 in [31] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)main::$8 in [32] *((const byte*) SCREEN + (byte) 2) ← *((byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (byte*~) main::$10 and assignment [4] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$4
|
||||
Eliminating unused variable (byte*~) main::$12 and assignment [6] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$14 and assignment [8] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$5
|
||||
Eliminating unused variable (byte*~) main::$16 and assignment [10] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$18 and assignment [12] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6
|
||||
Eliminating unused variable (byte*~) main::$19 and assignment [14] (byte*~) main::$19 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) main::$20 and assignment [16] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8
|
||||
Eliminating unused variable (byte*~) main::$21 and assignment [18] (byte*~) main::$21 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$13 = (byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$15 = (byte*)&(struct Point) main::p2
|
||||
Constant inlined main::$11 = (byte*)&(struct Point) main::p1
|
||||
Constant inlined main::$1 = (byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$2 = (byte*)&(struct Point) main::p2
|
||||
Constant inlined main::$17 = (byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$0 = (byte*)&(struct Point) main::p1
|
||||
Constant inlined main::$5 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$6 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$3 = (byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$4 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$9 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Constant inlined main::$7 = (struct Point*)&(struct Vector) main::v
|
||||
Constant inlined main::$8 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Consolidated array index constant in *(SCREEN+2)
|
||||
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+3)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::p1) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((byte*)&(struct Point) main::p2) ← (byte) 4
|
||||
[7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1)
|
||||
[9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2)
|
||||
[11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
|
||||
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
|
||||
[15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[16] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(struct Point) main::p1 loadstore
|
||||
(struct Point) main::p2 loadstore
|
||||
(struct Vector) main::v loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::p1 to live range equivalence class [ main::p1 ]
|
||||
Added variable main::p2 to live range equivalence class [ main::p2 ]
|
||||
Added variable main::v to live range equivalence class [ main::v ]
|
||||
Complete equivalence classes
|
||||
[ main::p1 ]
|
||||
[ main::p2 ]
|
||||
[ main::v ]
|
||||
Allocated zp[2]:2 [ main::p1 ]
|
||||
Allocated zp[2]:4 [ main::p2 ]
|
||||
Allocated zp[4]:6 [ main::v ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label p1 = 2
|
||||
.label p2 = 4
|
||||
.label v = 6
|
||||
// [4] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p1
|
||||
// [5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta p1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z p2
|
||||
// [7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta p2+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p1
|
||||
sta.z v
|
||||
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p1+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p2+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((byte*)&(struct Point) main::p1) ← (byte) 2 [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
|
||||
Statement [6] *((byte*)&(struct Point) main::p2) ← (byte) 4 [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
|
||||
Statement [7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
|
||||
Statement [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
|
||||
Statement [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) [ main::p2 main::v ] ( main:2 [ main::p2 main::v ] ) always clobbers reg byte a
|
||||
Statement [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) [ main::p2 main::v ] ( main:2 [ main::p2 main::v ] ) always clobbers reg byte a
|
||||
Statement [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
|
||||
Statement [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[2]:2 [ main::p1 ] : zp[2]:2 ,
|
||||
Potential registers zp[2]:4 [ main::p2 ] : zp[2]:4 ,
|
||||
Potential registers zp[4]:6 [ main::v ] : zp[4]:6 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [Vector]
|
||||
Uplift Scope [main] 0: zp[2]:2 [ main::p1 ] 0: zp[2]:4 [ main::p2 ] 0: zp[4]:6 [ main::v ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [Point] best 103 combination
|
||||
Uplifting [Vector] best 103 combination
|
||||
Uplifting [main] best 103 combination zp[2]:2 [ main::p1 ] zp[2]:4 [ main::p2 ] zp[4]:6 [ main::v ]
|
||||
Uplifting [] best 103 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label p1 = 2
|
||||
.label p2 = 4
|
||||
.label v = 6
|
||||
// [4] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p1
|
||||
// [5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta p1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z p2
|
||||
// [7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta p2+OFFSET_STRUCT_POINT_Y
|
||||
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p1
|
||||
sta.z v
|
||||
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p1+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p2+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::p1 loadstore zp[2]:2
|
||||
(struct Point) main::p2 loadstore zp[2]:4
|
||||
(struct Vector) main::v loadstore zp[4]:6
|
||||
|
||||
zp[2]:2 [ main::p1 ]
|
||||
zp[2]:4 [ main::p2 ]
|
||||
zp[4]:6 [ main::v ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 88
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.const OFFSET_STRUCT_VECTOR_Q = 2
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label p1 = 2
|
||||
.label p2 = 4
|
||||
.label v = 6
|
||||
// p1 = { 2, 3 }
|
||||
// [4] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p1
|
||||
// [5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta p1+OFFSET_STRUCT_POINT_Y
|
||||
// p2 = { 4, 5 }
|
||||
// [6] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z p2
|
||||
// [7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta p2+OFFSET_STRUCT_POINT_Y
|
||||
// v = { p1, p2 }
|
||||
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p1
|
||||
sta.z v
|
||||
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p1+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z p2
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q
|
||||
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda p2+OFFSET_STRUCT_POINT_Y
|
||||
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = v.p.x
|
||||
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z v
|
||||
sta SCREEN
|
||||
// SCREEN[1] = v.p.y
|
||||
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// SCREEN[2] = v.q.x
|
||||
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q
|
||||
sta SCREEN+2
|
||||
// SCREEN[3] = v.q.y
|
||||
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
// main::@return
|
||||
// }
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
19
src/test/ref/struct-20.sym
Normal file
19
src/test/ref/struct-20.sym
Normal file
@ -0,0 +1,19 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point) Vector::p
|
||||
(struct Point) Vector::q
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::p1 loadstore zp[2]:2
|
||||
(struct Point) main::p2 loadstore zp[2]:4
|
||||
(struct Vector) main::v loadstore zp[4]:6
|
||||
|
||||
zp[2]:2 [ main::p1 ]
|
||||
zp[2]:4 [ main::p2 ]
|
||||
zp[4]:6 [ main::v ]
|
19
src/test/ref/struct-21.asm
Normal file
19
src/test/ref/struct-21.asm
Normal file
@ -0,0 +1,19 @@
|
||||
// Minimal struct with C-Standard behavior - address-of
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label ptr = point1
|
||||
.label point1 = 2
|
||||
lda #2
|
||||
sta.z point1
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
lda.z ptr
|
||||
sta SCREEN
|
||||
lda ptr+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
20
src/test/ref/struct-21.cfg
Normal file
20
src/test/ref/struct-21.cfg
Normal file
@ -0,0 +1,20 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr)
|
||||
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
330
src/test/ref/struct-21.log
Normal file
330
src/test/ref/struct-21.log
Normal file
@ -0,0 +1,330 @@
|
||||
Setting inferred volatile on symbol affected by address-of (struct Point*) main::ptr ← &(struct Point) main::point1
|
||||
Adding struct value member variable copy *((byte*~) main::$0) ← (byte)(number) 2
|
||||
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 3
|
||||
Rewriting struct pointer member access *((struct Point*) main::ptr).x
|
||||
Rewriting struct pointer member access *((struct Point*) main::ptr).y
|
||||
Identified constant variable (struct Point*) main::ptr
|
||||
Adding versioned struct unwinding for (struct Point) main::point1
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$0) ← (byte)(number) 2
|
||||
(byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$1) ← (byte)(number) 3
|
||||
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
(byte*~) main::$2 ← (byte*)(const struct Point*) main::ptr + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
|
||||
(byte*~) main::$3 ← (byte*)(const struct Point*) main::ptr + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(void()) main()
|
||||
(byte*~) main::$0
|
||||
(byte*~) main::$1
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$3
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore
|
||||
(const struct Point*) main::ptr = &(struct Point) main::point1
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [4] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [5] (byte*~) main::$2 ← (byte*)(const struct Point*) main::ptr + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [7] (byte*~) main::$3 ← (byte*)(const struct Point*) main::ptr + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$0 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$1 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$2 = (byte*)main::ptr+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$3 = (byte*)main::ptr+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero (byte*)main::ptr in
|
||||
Simplifying expression containing zero SCREEN in [6] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$2)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$3 = (byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$1 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$2 = (byte*)(const struct Point*) main::ptr
|
||||
Constant inlined main::$0 = (byte*)&(struct Point) main::point1
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr)
|
||||
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(void()) main()
|
||||
(struct Point) main::point1 loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::point1 to live range equivalence class [ main::point1 ]
|
||||
Complete equivalence classes
|
||||
[ main::point1 ]
|
||||
Allocated zp[2]:2 [ main::point1 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - address-of
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label ptr = point1
|
||||
.label point1 = 2
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z ptr
|
||||
sta SCREEN
|
||||
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda ptr+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 [ main::point1 ] ( main:2 [ main::point1 ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[2]:2 [ main::point1 ] : zp[2]:2 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main] 0: zp[2]:2 [ main::point1 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [Point] best 47 combination
|
||||
Uplifting [main] best 47 combination zp[2]:2 [ main::point1 ]
|
||||
Uplifting [] best 47 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - address-of
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label ptr = point1
|
||||
.label point1 = 2
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z ptr
|
||||
sta SCREEN
|
||||
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda ptr+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
(const struct Point*) main::ptr = &(struct Point) main::point1
|
||||
|
||||
zp[2]:2 [ main::point1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 32
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - address-of
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label ptr = point1
|
||||
.label point1 = 2
|
||||
// point1 = { 2, 3 }
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = ptr->x
|
||||
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z ptr
|
||||
sta SCREEN
|
||||
// SCREEN[1] = ptr->y
|
||||
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda ptr+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
13
src/test/ref/struct-21.sym
Normal file
13
src/test/ref/struct-21.sym
Normal file
@ -0,0 +1,13 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
(const struct Point*) main::ptr = &(struct Point) main::point1
|
||||
|
||||
zp[2]:2 [ main::point1 ]
|
31
src/test/ref/struct-22.asm
Normal file
31
src/test/ref/struct-22.asm
Normal file
@ -0,0 +1,31 @@
|
||||
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
lda #2
|
||||
sta.z point1
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
lda #4
|
||||
sta.z point2
|
||||
lda #5
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
lda.z point1
|
||||
ldx point1+OFFSET_STRUCT_POINT_Y
|
||||
jsr print
|
||||
lda.z point2
|
||||
ldx point2+OFFSET_STRUCT_POINT_Y
|
||||
jsr print
|
||||
rts
|
||||
}
|
||||
// print(byte register(A) p_x, byte register(X) p_y)
|
||||
print: {
|
||||
sta SCREEN
|
||||
stx SCREEN+1
|
||||
rts
|
||||
}
|
39
src/test/ref/struct-22.cfg
Normal file
39
src/test/ref/struct-22.cfg
Normal file
@ -0,0 +1,39 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((byte*)&(struct Point) main::point2) ← (byte) 4
|
||||
[7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1)
|
||||
[9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[10] call print
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2)
|
||||
[12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[13] call print
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[14] return
|
||||
to:@return
|
||||
|
||||
(void()) print((byte) print::p_x , (byte) print::p_y)
|
||||
print: scope:[print] from main main::@1
|
||||
[15] (byte) print::p_y#2 ← phi( main/(byte) print::p_y#0 main::@1/(byte) print::p_y#1 )
|
||||
[15] (byte) print::p_x#2 ← phi( main/(byte) print::p_x#0 main::@1/(byte) print::p_x#1 )
|
||||
[16] *((const byte*) SCREEN) ← (byte) print::p_x#2
|
||||
[17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[18] return
|
||||
to:@return
|
587
src/test/ref/struct-22.log
Normal file
587
src/test/ref/struct-22.log
Normal file
@ -0,0 +1,587 @@
|
||||
Created struct value member variable (byte) print::p_x
|
||||
Created struct value member variable (byte) print::p_y
|
||||
Converted struct value to member variables (struct Point) print::p
|
||||
Converted procedure struct value parameter to member unwinding (void()) print((byte) print::p_x , (byte) print::p_y)
|
||||
Adding struct value member variable copy *((byte*~) main::$2) ← (byte)(number) 2
|
||||
Adding struct value member variable copy *((byte*~) main::$3) ← (byte)(number) 3
|
||||
Adding struct value member variable copy *((byte*~) main::$4) ← (byte)(number) 4
|
||||
Adding struct value member variable copy *((byte*~) main::$5) ← (byte)(number) 5
|
||||
Converted procedure struct value parameter to member unwinding in call (void~) main::$0 ← call print *((byte*~) main::$6) *((byte*~) main::$7)
|
||||
Converted procedure struct value parameter to member unwinding in call (void~) main::$1 ← call print *((byte*~) main::$8) *((byte*~) main::$9)
|
||||
Replacing struct member reference (struct Point) print::p.x with member unwinding reference (byte) print::p_x
|
||||
Replacing struct member reference (struct Point) print::p.y with member unwinding reference (byte) print::p_y
|
||||
Culled Empty Block (label) @1
|
||||
Adding versioned struct unwinding for (struct Point) main::point1
|
||||
Adding versioned struct unwinding for (struct Point) main::point2
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@2
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @2
|
||||
(byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$2) ← (byte)(number) 2
|
||||
(byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$3) ← (byte)(number) 3
|
||||
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
|
||||
(byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$4) ← (byte)(number) 4
|
||||
(byte*~) main::$5 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$5) ← (byte)(number) 5
|
||||
(struct Point) main::point2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
|
||||
(byte) print::p_x#0 ← *((byte*~) main::$6)
|
||||
(byte) print::p_y#0 ← *((byte*~) main::$7)
|
||||
call print
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
(byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
(byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
(byte) print::p_x#1 ← *((byte*~) main::$8)
|
||||
(byte) print::p_y#1 ← *((byte*~) main::$9)
|
||||
call print
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
(byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
return
|
||||
to:@return
|
||||
|
||||
(void()) print((byte) print::p_x , (byte) print::p_y)
|
||||
print: scope:[print] from main main::@1
|
||||
(byte) print::p_y#2 ← phi( main/(byte) print::p_y#0 main::@1/(byte) print::p_y#1 )
|
||||
(byte) print::p_x#2 ← phi( main/(byte) print::p_x#0 main::@1/(byte) print::p_x#1 )
|
||||
*((const byte*) SCREEN + (number) 0) ← (byte) print::p_x#2
|
||||
*((const byte*) SCREEN + (number) 1) ← (byte) print::p_y#2
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @begin
|
||||
call main
|
||||
to:@3
|
||||
@3: scope:[] from @2
|
||||
to:@end
|
||||
@end: scope:[] from @3
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(void()) main()
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$3
|
||||
(byte*~) main::$4
|
||||
(byte*~) main::$5
|
||||
(byte*~) main::$6
|
||||
(byte*~) main::$7
|
||||
(byte*~) main::$8
|
||||
(byte*~) main::$9
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore
|
||||
(struct Point) main::point2 loadstore
|
||||
(void()) print((byte) print::p_x , (byte) print::p_y)
|
||||
(label) print::@return
|
||||
(struct Point) print::p
|
||||
(byte) print::p_x
|
||||
(byte) print::p_x#0
|
||||
(byte) print::p_x#1
|
||||
(byte) print::p_x#2
|
||||
(byte) print::p_y
|
||||
(byte) print::p_y#0
|
||||
(byte) print::p_y#1
|
||||
(byte) print::p_y#2
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← (byte) print::p_x#2
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← (byte) print::p_y#2
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 5
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [4] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
|
||||
Removing C-classic struct-unwound assignment [9] (struct Point) main::point2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
|
||||
Constant right-side identified [0] (byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [2] (byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [5] (byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [7] (byte*~) main::$5 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [13] (byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [14] (byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [18] (byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [19] (byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$2 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$3 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$4 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$5 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$6 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$7 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$8 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$9 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero (byte*)&main::point2 in
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero (byte*)&main::point2 in
|
||||
Simplifying expression containing zero SCREEN in [22] *((const byte*) SCREEN + (byte) 0) ← (byte) print::p_x#2
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$2 = (byte*)&(struct Point) main::point1
|
||||
Constant inlined main::$5 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$6 = (byte*)&(struct Point) main::point1
|
||||
Constant inlined main::$3 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$4 = (byte*)&(struct Point) main::point2
|
||||
Constant inlined main::$9 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$7 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$8 = (byte*)&(struct Point) main::point2
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main::@2
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
Calls in [main] to print:13 print:18
|
||||
|
||||
Created 2 initial phi equivalence classes
|
||||
Coalesced [11] print::p_x#3 ← print::p_x#0
|
||||
Coalesced [12] print::p_y#3 ← print::p_y#0
|
||||
Coalesced [16] print::p_x#4 ← print::p_x#1
|
||||
Coalesced [17] print::p_y#4 ← print::p_y#1
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Culled Empty Block (label) @3
|
||||
Culled Empty Block (label) main::@2
|
||||
Renumbering block @2 to @1
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((byte*)&(struct Point) main::point2) ← (byte) 4
|
||||
[7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
|
||||
[8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1)
|
||||
[9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[10] call print
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2)
|
||||
[12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[13] call print
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[14] return
|
||||
to:@return
|
||||
|
||||
(void()) print((byte) print::p_x , (byte) print::p_y)
|
||||
print: scope:[print] from main main::@1
|
||||
[15] (byte) print::p_y#2 ← phi( main/(byte) print::p_y#0 main::@1/(byte) print::p_y#1 )
|
||||
[15] (byte) print::p_x#2 ← phi( main/(byte) print::p_x#0 main::@1/(byte) print::p_x#1 )
|
||||
[16] *((const byte*) SCREEN) ← (byte) print::p_x#2
|
||||
[17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[18] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(void()) main()
|
||||
(struct Point) main::point1 loadstore
|
||||
(struct Point) main::point2 loadstore
|
||||
(void()) print((byte) print::p_x , (byte) print::p_y)
|
||||
(struct Point) print::p
|
||||
(byte) print::p_x
|
||||
(byte) print::p_x#0 2.0
|
||||
(byte) print::p_x#1 2.0
|
||||
(byte) print::p_x#2 6.0
|
||||
(byte) print::p_y
|
||||
(byte) print::p_y#0 4.0
|
||||
(byte) print::p_y#1 4.0
|
||||
(byte) print::p_y#2 3.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ print::p_x#2 print::p_x#0 print::p_x#1 ]
|
||||
[ print::p_y#2 print::p_y#0 print::p_y#1 ]
|
||||
Added variable main::point1 to live range equivalence class [ main::point1 ]
|
||||
Added variable main::point2 to live range equivalence class [ main::point2 ]
|
||||
Complete equivalence classes
|
||||
[ print::p_x#2 print::p_x#0 print::p_x#1 ]
|
||||
[ print::p_y#2 print::p_y#0 print::p_y#1 ]
|
||||
[ main::point1 ]
|
||||
[ main::point2 ]
|
||||
Allocated zp[1]:2 [ print::p_x#2 print::p_x#0 print::p_x#1 ]
|
||||
Allocated zp[1]:3 [ print::p_y#2 print::p_y#0 print::p_y#1 ]
|
||||
Allocated zp[2]:4 [ main::point1 ]
|
||||
Allocated zp[2]:6 [ main::point2 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 4
|
||||
.label point2 = 6
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)&(struct Point) main::point2) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z point2
|
||||
// [7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
// [8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1) -- vbuz1=_deref_pbuc1
|
||||
lda.z point1
|
||||
sta.z print.p_x
|
||||
// [9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta.z print.p_y
|
||||
// [10] call print
|
||||
// [15] phi from main to print [phi:main->print]
|
||||
print_from_main:
|
||||
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#0 [phi:main->print#0] -- register_copy
|
||||
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#0 [phi:main->print#1] -- register_copy
|
||||
jsr print
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2) -- vbuz1=_deref_pbuc1
|
||||
lda.z point2
|
||||
sta.z print.p_x
|
||||
// [12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1
|
||||
lda point2+OFFSET_STRUCT_POINT_Y
|
||||
sta.z print.p_y
|
||||
// [13] call print
|
||||
// [15] phi from main::@1 to print [phi:main::@1->print]
|
||||
print_from___b1:
|
||||
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#1 [phi:main::@1->print#0] -- register_copy
|
||||
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#1 [phi:main::@1->print#1] -- register_copy
|
||||
jsr print
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [14] return
|
||||
rts
|
||||
}
|
||||
// print
|
||||
// print(byte zp(2) p_x, byte zp(3) p_y)
|
||||
print: {
|
||||
.label p_x = 2
|
||||
.label p_y = 3
|
||||
// [16] *((const byte*) SCREEN) ← (byte) print::p_x#2 -- _deref_pbuc1=vbuz1
|
||||
lda.z p_x
|
||||
sta SCREEN
|
||||
// [17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2 -- _deref_pbuc1=vbuz1
|
||||
lda.z p_y
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// print::@return
|
||||
__breturn:
|
||||
// [18] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Statement [6] *((byte*)&(struct Point) main::point2) ← (byte) 4 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Statement [7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ print::p_x#2 print::p_x#0 print::p_x#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:3 [ print::p_y#2 print::p_y#0 print::p_y#1 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[2]:4 [ main::point1 ] : zp[2]:4 ,
|
||||
Potential registers zp[2]:6 [ main::point2 ] : zp[2]:6 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [print] 11: zp[1]:3 [ print::p_y#2 print::p_y#0 print::p_y#1 ] 10: zp[1]:2 [ print::p_x#2 print::p_x#0 print::p_x#1 ]
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main] 0: zp[2]:4 [ main::point1 ] 0: zp[2]:6 [ main::point2 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [print] best 89 combination reg byte x [ print::p_y#2 print::p_y#0 print::p_y#1 ] reg byte a [ print::p_x#2 print::p_x#0 print::p_x#1 ]
|
||||
Uplifting [Point] best 89 combination
|
||||
Uplifting [main] best 89 combination zp[2]:4 [ main::point1 ] zp[2]:6 [ main::point2 ]
|
||||
Uplifting [] best 89 combination
|
||||
Allocated (was zp[2]:4) zp[2]:2 [ main::point1 ]
|
||||
Allocated (was zp[2]:6) zp[2]:4 [ main::point2 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)&(struct Point) main::point2) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z point2
|
||||
// [7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
// [8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1) -- vbuaa=_deref_pbuc1
|
||||
lda.z point1
|
||||
// [9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
|
||||
ldx point1+OFFSET_STRUCT_POINT_Y
|
||||
// [10] call print
|
||||
// [15] phi from main to print [phi:main->print]
|
||||
print_from_main:
|
||||
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#0 [phi:main->print#0] -- register_copy
|
||||
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#0 [phi:main->print#1] -- register_copy
|
||||
jsr print
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2) -- vbuaa=_deref_pbuc1
|
||||
lda.z point2
|
||||
// [12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
|
||||
ldx point2+OFFSET_STRUCT_POINT_Y
|
||||
// [13] call print
|
||||
// [15] phi from main::@1 to print [phi:main::@1->print]
|
||||
print_from___b1:
|
||||
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#1 [phi:main::@1->print#0] -- register_copy
|
||||
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#1 [phi:main::@1->print#1] -- register_copy
|
||||
jsr print
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [14] return
|
||||
rts
|
||||
}
|
||||
// print
|
||||
// print(byte register(A) p_x, byte register(X) p_y)
|
||||
print: {
|
||||
// [16] *((const byte*) SCREEN) ← (byte) print::p_x#2 -- _deref_pbuc1=vbuaa
|
||||
sta SCREEN
|
||||
// [17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2 -- _deref_pbuc1=vbuxx
|
||||
stx SCREEN+1
|
||||
jmp __breturn
|
||||
// print::@return
|
||||
__breturn:
|
||||
// [18] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __breturn
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction print_from_main:
|
||||
Removing instruction __b1:
|
||||
Removing instruction print_from___b1:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
(struct Point) main::point2 loadstore zp[2]:4
|
||||
(void()) print((byte) print::p_x , (byte) print::p_y)
|
||||
(label) print::@return
|
||||
(struct Point) print::p
|
||||
(byte) print::p_x
|
||||
(byte) print::p_x#0 reg byte a 2.0
|
||||
(byte) print::p_x#1 reg byte a 2.0
|
||||
(byte) print::p_x#2 reg byte a 6.0
|
||||
(byte) print::p_y
|
||||
(byte) print::p_y#0 reg byte x 4.0
|
||||
(byte) print::p_y#1 reg byte x 4.0
|
||||
(byte) print::p_y#2 reg byte x 3.0
|
||||
|
||||
reg byte a [ print::p_x#2 print::p_x#0 print::p_x#1 ]
|
||||
reg byte x [ print::p_y#2 print::p_y#0 print::p_y#1 ]
|
||||
zp[2]:2 [ main::point1 ]
|
||||
zp[2]:4 [ main::point2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 68
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
// point1 = { 2, 3 }
|
||||
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z point1
|
||||
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// point2 = { 4, 5 }
|
||||
// [6] *((byte*)&(struct Point) main::point2) ← (byte) 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z point2
|
||||
// [7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
|
||||
lda #5
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
// print(point1)
|
||||
// [8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1) -- vbuaa=_deref_pbuc1
|
||||
lda.z point1
|
||||
// [9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
|
||||
ldx point1+OFFSET_STRUCT_POINT_Y
|
||||
// [10] call print
|
||||
// [15] phi from main to print [phi:main->print]
|
||||
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#0 [phi:main->print#0] -- register_copy
|
||||
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#0 [phi:main->print#1] -- register_copy
|
||||
jsr print
|
||||
// main::@1
|
||||
// print(point2)
|
||||
// [11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2) -- vbuaa=_deref_pbuc1
|
||||
lda.z point2
|
||||
// [12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
|
||||
ldx point2+OFFSET_STRUCT_POINT_Y
|
||||
// [13] call print
|
||||
// [15] phi from main::@1 to print [phi:main::@1->print]
|
||||
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#1 [phi:main::@1->print#0] -- register_copy
|
||||
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#1 [phi:main::@1->print#1] -- register_copy
|
||||
jsr print
|
||||
// main::@return
|
||||
// }
|
||||
// [14] return
|
||||
rts
|
||||
}
|
||||
// print
|
||||
// print(byte register(A) p_x, byte register(X) p_y)
|
||||
print: {
|
||||
// SCREEN[0] = p.x
|
||||
// [16] *((const byte*) SCREEN) ← (byte) print::p_x#2 -- _deref_pbuc1=vbuaa
|
||||
sta SCREEN
|
||||
// SCREEN[1] = p.y
|
||||
// [17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2 -- _deref_pbuc1=vbuxx
|
||||
stx SCREEN+1
|
||||
// print::@return
|
||||
// }
|
||||
// [18] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
28
src/test/ref/struct-22.sym
Normal file
28
src/test/ref/struct-22.sym
Normal file
@ -0,0 +1,28 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
(struct Point) main::point2 loadstore zp[2]:4
|
||||
(void()) print((byte) print::p_x , (byte) print::p_y)
|
||||
(label) print::@return
|
||||
(struct Point) print::p
|
||||
(byte) print::p_x
|
||||
(byte) print::p_x#0 reg byte a 2.0
|
||||
(byte) print::p_x#1 reg byte a 2.0
|
||||
(byte) print::p_x#2 reg byte a 6.0
|
||||
(byte) print::p_y
|
||||
(byte) print::p_y#0 reg byte x 4.0
|
||||
(byte) print::p_y#1 reg byte x 4.0
|
||||
(byte) print::p_y#2 reg byte x 3.0
|
||||
|
||||
reg byte a [ print::p_x#2 print::p_x#0 print::p_x#1 ]
|
||||
reg byte x [ print::p_y#2 print::p_y#0 print::p_y#1 ]
|
||||
zp[2]:2 [ main::point1 ]
|
||||
zp[2]:4 [ main::point2 ]
|
32
src/test/ref/struct-23.asm
Normal file
32
src/test/ref/struct-23.asm
Normal file
@ -0,0 +1,32 @@
|
||||
// Minimal struct with C-Standard behavior - call return value (not supported yet)
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
lda #3
|
||||
ldx #2
|
||||
jsr getPoint
|
||||
stx.z point1
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
txa
|
||||
sta SCREEN
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
lda #5
|
||||
ldx #4
|
||||
jsr getPoint
|
||||
stx.z point2
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
txa
|
||||
sta SCREEN+2
|
||||
lda point2+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
rts
|
||||
}
|
||||
getPoint: {
|
||||
rts
|
||||
}
|
48
src/test/ref/struct-23.cfg
Normal file
48
src/test/ref/struct-23.cfg
Normal file
@ -0,0 +1,48 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
[5] call getPoint
|
||||
[6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2
|
||||
[7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[8] (byte~) main::$0_x ← (byte) getPoint::return_x#0
|
||||
[9] (byte~) main::$0_y ← (byte) getPoint::return_y#0
|
||||
[10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x
|
||||
[11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y
|
||||
[12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1)
|
||||
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[14] call getPoint
|
||||
[15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2
|
||||
[16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[17] (byte~) main::$1_x ← (byte) getPoint::return_x#1
|
||||
[18] (byte~) main::$1_y ← (byte) getPoint::return_y#1
|
||||
[19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x
|
||||
[20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
|
||||
[21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2)
|
||||
[22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[23] return
|
||||
to:@return
|
||||
|
||||
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
|
||||
getPoint: scope:[getPoint] from main main::@1
|
||||
[24] (byte) getPoint::return_y#2 ← phi( main/(byte) 3 main::@1/(byte) 5 )
|
||||
[24] (byte) getPoint::return_x#2 ← phi( main/(byte) 2 main::@1/(byte) 4 )
|
||||
to:getPoint::@return
|
||||
getPoint::@return: scope:[getPoint] from getPoint
|
||||
[25] return
|
||||
to:@return
|
848
src/test/ref/struct-23.log
Normal file
848
src/test/ref/struct-23.log
Normal file
@ -0,0 +1,848 @@
|
||||
Created struct value member variable (byte~) main::$0_x
|
||||
Created struct value member variable (byte~) main::$0_y
|
||||
Converted struct value to member variables (struct Point~) main::$0
|
||||
Created struct value member variable (byte~) main::$1_x
|
||||
Created struct value member variable (byte~) main::$1_y
|
||||
Converted struct value to member variables (struct Point~) main::$1
|
||||
Created struct value member variable (byte) getPoint::return_x
|
||||
Created struct value member variable (byte) getPoint::return_y
|
||||
Converted struct value to member variables (struct Point) getPoint::return
|
||||
Created struct value member variable (byte) getPoint::p_x
|
||||
Created struct value member variable (byte) getPoint::p_y
|
||||
Converted struct value to member variables (struct Point) getPoint::p
|
||||
Converted procedure call LValue to member unwinding { (byte~) main::$0_x, (byte~) main::$0_y } ← call getPoint (number) 2 (number) 3
|
||||
Adding struct value member variable copy *((byte*~) main::$2) ← (byte~) main::$0_x
|
||||
Adding struct value member variable copy *((byte*~) main::$3) ← (byte~) main::$0_y
|
||||
Converted procedure call LValue to member unwinding { (byte~) main::$1_x, (byte~) main::$1_y } ← call getPoint (number) 4 (number) 5
|
||||
Adding struct value member variable copy *((byte*~) main::$4) ← (byte~) main::$1_x
|
||||
Adding struct value member variable copy *((byte*~) main::$5) ← (byte~) main::$1_y
|
||||
Adding struct value list initializer (byte) getPoint::p_x ← (byte) getPoint::x
|
||||
Adding struct value list initializer (byte) getPoint::p_y ← (byte) getPoint::y
|
||||
Adding struct value member variable copy (byte) getPoint::return_x ← (byte) getPoint::p_x
|
||||
Adding struct value member variable copy (byte) getPoint::return_y ← (byte) getPoint::p_y
|
||||
Adding struct value member variable copy (byte) getPoint::return_x ← (byte) getPoint::return_x
|
||||
Adding struct value member variable copy (byte) getPoint::return_y ← (byte) getPoint::return_y
|
||||
Converted procedure struct return value to member unwinding return { (byte) getPoint::return_x, (byte) getPoint::return_y }
|
||||
Replacing struct member reference (struct Point) main::point1.x with member unwinding reference *((byte*~) main::$6)
|
||||
Replacing struct member reference (struct Point) main::point1.y with member unwinding reference *((byte*~) main::$7)
|
||||
Replacing struct member reference (struct Point) main::point2.x with member unwinding reference *((byte*~) main::$8)
|
||||
Replacing struct member reference (struct Point) main::point2.y with member unwinding reference *((byte*~) main::$9)
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) getPoint::@1
|
||||
Unwinding list assignment { (byte~) main::$0_x, (byte~) main::$0_y } ← { (byte) getPoint::return_x, (byte) getPoint::return_y }
|
||||
Unwinding list assignment { (byte~) main::$1_x, (byte~) main::$1_y } ← { (byte) getPoint::return_x, (byte) getPoint::return_y }
|
||||
Unwinding list assignment { (byte) getPoint::return_x#0, (byte) getPoint::return_y#0 } ← { (byte) getPoint::return_x#3, (byte) getPoint::return_y#3 }
|
||||
Unwinding list assignment { (byte) getPoint::return_x#1, (byte) getPoint::return_y#1 } ← { (byte) getPoint::return_x#3, (byte) getPoint::return_y#3 }
|
||||
Adding versioned struct unwinding for (struct Point) main::point1
|
||||
Adding versioned struct unwinding for (struct Point) main::point2
|
||||
Adding versioned struct unwinding for (struct Point) getPoint::return#0
|
||||
Adding versioned struct unwinding for (struct Point) getPoint::return#1
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@2
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @2
|
||||
(byte) getPoint::x#0 ← (number) 2
|
||||
(byte) getPoint::y#0 ← (number) 3
|
||||
call getPoint
|
||||
(byte) getPoint::return_x#0 ← (byte) getPoint::return_x#3
|
||||
(byte) getPoint::return_y#0 ← (byte) getPoint::return_y#3
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
(byte) getPoint::return_y#4 ← phi( main/(byte) getPoint::return_y#0 )
|
||||
(byte) getPoint::return_x#4 ← phi( main/(byte) getPoint::return_x#0 )
|
||||
(byte~) main::$0_x ← (byte) getPoint::return_x#4
|
||||
(byte~) main::$0_y ← (byte) getPoint::return_y#4
|
||||
(byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$2) ← (byte~) main::$0_x
|
||||
(byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$3) ← (byte~) main::$0_y
|
||||
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$6)
|
||||
(byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$7)
|
||||
(byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
(byte) getPoint::x#1 ← (number) 4
|
||||
(byte) getPoint::y#1 ← (number) 5
|
||||
call getPoint
|
||||
(byte) getPoint::return_x#1 ← (byte) getPoint::return_x#3
|
||||
(byte) getPoint::return_y#1 ← (byte) getPoint::return_y#3
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte) getPoint::return_y#5 ← phi( main::@1/(byte) getPoint::return_y#1 )
|
||||
(byte) getPoint::return_x#5 ← phi( main::@1/(byte) getPoint::return_x#1 )
|
||||
(byte~) main::$1_x ← (byte) getPoint::return_x#5
|
||||
(byte~) main::$1_y ← (byte) getPoint::return_y#5
|
||||
(byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$4) ← (byte~) main::$1_x
|
||||
(byte*~) main::$5 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$5) ← (byte~) main::$1_y
|
||||
(struct Point) main::point2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
|
||||
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$8)
|
||||
(byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$9)
|
||||
(byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
return
|
||||
to:@return
|
||||
|
||||
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
|
||||
getPoint: scope:[getPoint] from main main::@1
|
||||
(byte) getPoint::y#2 ← phi( main/(byte) getPoint::y#0 main::@1/(byte) getPoint::y#1 )
|
||||
(byte) getPoint::x#2 ← phi( main/(byte) getPoint::x#0 main::@1/(byte) getPoint::x#1 )
|
||||
(byte) getPoint::p_x#0 ← (byte) getPoint::x#2
|
||||
(byte) getPoint::p_y#0 ← (byte) getPoint::y#2
|
||||
(byte) getPoint::return_x#2 ← (byte) getPoint::p_x#0
|
||||
(byte) getPoint::return_y#2 ← (byte) getPoint::p_y#0
|
||||
(struct Point) getPoint::return#0 ← struct-unwound {(byte) getPoint::return_x#2, (byte) getPoint::return_y#2}
|
||||
to:getPoint::@return
|
||||
getPoint::@return: scope:[getPoint] from getPoint
|
||||
(byte) getPoint::return_y#6 ← phi( getPoint/(byte) getPoint::return_y#2 )
|
||||
(byte) getPoint::return_x#6 ← phi( getPoint/(byte) getPoint::return_x#2 )
|
||||
(byte) getPoint::return_x#3 ← (byte) getPoint::return_x#6
|
||||
(byte) getPoint::return_y#3 ← (byte) getPoint::return_y#6
|
||||
(struct Point) getPoint::return#1 ← struct-unwound {(byte) getPoint::return_x#3, (byte) getPoint::return_y#3}
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @begin
|
||||
call main
|
||||
to:@3
|
||||
@3: scope:[] from @2
|
||||
to:@end
|
||||
@end: scope:[] from @3
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
|
||||
(label) getPoint::@return
|
||||
(byte) getPoint::p_x
|
||||
(byte) getPoint::p_x#0
|
||||
(byte) getPoint::p_y
|
||||
(byte) getPoint::p_y#0
|
||||
(struct Point) getPoint::return
|
||||
(struct Point) getPoint::return#0
|
||||
(struct Point) getPoint::return#1
|
||||
(byte) getPoint::return_x
|
||||
(byte) getPoint::return_x#0
|
||||
(byte) getPoint::return_x#1
|
||||
(byte) getPoint::return_x#2
|
||||
(byte) getPoint::return_x#3
|
||||
(byte) getPoint::return_x#4
|
||||
(byte) getPoint::return_x#5
|
||||
(byte) getPoint::return_x#6
|
||||
(byte) getPoint::return_y
|
||||
(byte) getPoint::return_y#0
|
||||
(byte) getPoint::return_y#1
|
||||
(byte) getPoint::return_y#2
|
||||
(byte) getPoint::return_y#3
|
||||
(byte) getPoint::return_y#4
|
||||
(byte) getPoint::return_y#5
|
||||
(byte) getPoint::return_y#6
|
||||
(byte) getPoint::x
|
||||
(byte) getPoint::x#0
|
||||
(byte) getPoint::x#1
|
||||
(byte) getPoint::x#2
|
||||
(byte) getPoint::y
|
||||
(byte) getPoint::y#0
|
||||
(byte) getPoint::y#1
|
||||
(byte) getPoint::y#2
|
||||
(void()) main()
|
||||
(struct Point~) main::$0
|
||||
(byte~) main::$0_x
|
||||
(byte~) main::$0_y
|
||||
(struct Point~) main::$1
|
||||
(byte~) main::$1_x
|
||||
(byte~) main::$1_y
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$3
|
||||
(byte*~) main::$4
|
||||
(byte*~) main::$5
|
||||
(byte*~) main::$6
|
||||
(byte*~) main::$7
|
||||
(byte*~) main::$8
|
||||
(byte*~) main::$9
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore
|
||||
(struct Point) main::point2 loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 2 in (byte) getPoint::x#0 ← (number) 2
|
||||
Adding number conversion cast (unumber) 3 in (byte) getPoint::y#0 ← (number) 3
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$6)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$7)
|
||||
Adding number conversion cast (unumber) 4 in (byte) getPoint::x#1 ← (number) 4
|
||||
Adding number conversion cast (unumber) 5 in (byte) getPoint::y#1 ← (number) 5
|
||||
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$8)
|
||||
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$9)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte) getPoint::x#0 ← (unumber)(number) 2
|
||||
Inlining cast (byte) getPoint::y#0 ← (unumber)(number) 3
|
||||
Inlining cast (byte) getPoint::x#1 ← (unumber)(number) 4
|
||||
Inlining cast (byte) getPoint::y#1 ← (unumber)(number) 5
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 5
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 3
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Finalized unsigned number type (byte) 4
|
||||
Finalized unsigned number type (byte) 5
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 3
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (byte) getPoint::return_x#0 = (byte) getPoint::return_x#4
|
||||
Alias (byte) getPoint::return_y#0 = (byte) getPoint::return_y#4
|
||||
Alias (byte) getPoint::return_x#1 = (byte) getPoint::return_x#5
|
||||
Alias (byte) getPoint::return_y#1 = (byte) getPoint::return_y#5
|
||||
Alias (byte) getPoint::return_x#2 = (byte) getPoint::p_x#0 (byte) getPoint::x#2 (byte) getPoint::return_x#6 (byte) getPoint::return_x#3
|
||||
Alias (byte) getPoint::return_y#2 = (byte) getPoint::p_y#0 (byte) getPoint::y#2 (byte) getPoint::return_y#6 (byte) getPoint::return_y#3
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Removing C-classic struct-unwound assignment [12] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
|
||||
Removing C-classic struct-unwound assignment [29] (struct Point) main::point2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
|
||||
Constant right-side identified [8] (byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [10] (byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [14] (byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [16] (byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [25] (byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [27] (byte*~) main::$5 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [31] (byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [33] (byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) getPoint::x#0 = 2
|
||||
Constant (const byte) getPoint::y#0 = 3
|
||||
Constant (const byte*) main::$2 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$3 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$6 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$7 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte) getPoint::x#1 = 4
|
||||
Constant (const byte) getPoint::y#1 = 5
|
||||
Constant (const byte*) main::$4 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$5 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$8 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$9 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero (byte*)&main::point1 in
|
||||
Simplifying expression containing zero (byte*)&main::point2 in
|
||||
Simplifying expression containing zero (byte*)&main::point2 in
|
||||
Simplifying expression containing zero SCREEN in [13] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$6)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (struct Point) getPoint::return#0 and assignment [20] (struct Point) getPoint::return#0 ← struct-unwound {(byte) getPoint::return_x#2, (byte) getPoint::return_y#2}
|
||||
Eliminating unused variable (struct Point) getPoint::return#1 and assignment [21] (struct Point) getPoint::return#1 ← struct-unwound {(byte) getPoint::return_x#2, (byte) getPoint::return_y#2}
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Inlining constant with different constant siblings (const byte) getPoint::x#0
|
||||
Inlining constant with different constant siblings (const byte) getPoint::y#0
|
||||
Inlining constant with different constant siblings (const byte) getPoint::x#1
|
||||
Inlining constant with different constant siblings (const byte) getPoint::y#1
|
||||
Constant inlined main::$2 = (byte*)&(struct Point) main::point1
|
||||
Constant inlined main::$5 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$6 = (byte*)&(struct Point) main::point1
|
||||
Constant inlined main::$3 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined getPoint::y#0 = (byte) 3
|
||||
Constant inlined getPoint::x#1 = (byte) 4
|
||||
Constant inlined main::$4 = (byte*)&(struct Point) main::point2
|
||||
Constant inlined getPoint::y#1 = (byte) 5
|
||||
Constant inlined main::$9 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined getPoint::x#0 = (byte) 2
|
||||
Constant inlined main::$7 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$8 = (byte*)&(struct Point) main::point2
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Consolidated array index constant in *(SCREEN+2)
|
||||
Consolidated array index constant in *(SCREEN+3)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
Calls in [main] to getPoint:6 getPoint:15
|
||||
|
||||
Created 2 initial phi equivalence classes
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Culled Empty Block (label) @3
|
||||
Renumbering block @2 to @1
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
[5] call getPoint
|
||||
[6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2
|
||||
[7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[8] (byte~) main::$0_x ← (byte) getPoint::return_x#0
|
||||
[9] (byte~) main::$0_y ← (byte) getPoint::return_y#0
|
||||
[10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x
|
||||
[11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y
|
||||
[12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1)
|
||||
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
[14] call getPoint
|
||||
[15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2
|
||||
[16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[17] (byte~) main::$1_x ← (byte) getPoint::return_x#1
|
||||
[18] (byte~) main::$1_y ← (byte) getPoint::return_y#1
|
||||
[19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x
|
||||
[20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
|
||||
[21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2)
|
||||
[22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[23] return
|
||||
to:@return
|
||||
|
||||
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
|
||||
getPoint: scope:[getPoint] from main main::@1
|
||||
[24] (byte) getPoint::return_y#2 ← phi( main/(byte) 3 main::@1/(byte) 5 )
|
||||
[24] (byte) getPoint::return_x#2 ← phi( main/(byte) 2 main::@1/(byte) 4 )
|
||||
to:getPoint::@return
|
||||
getPoint::@return: scope:[getPoint] from getPoint
|
||||
[25] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
|
||||
(byte) getPoint::p_x
|
||||
(byte) getPoint::p_y
|
||||
(struct Point) getPoint::return
|
||||
(byte) getPoint::return_x
|
||||
(byte) getPoint::return_x#0 2.0
|
||||
(byte) getPoint::return_x#1 2.0
|
||||
(byte) getPoint::return_x#2 1.0
|
||||
(byte) getPoint::return_y
|
||||
(byte) getPoint::return_y#0 2.0
|
||||
(byte) getPoint::return_y#1 2.0
|
||||
(byte) getPoint::return_y#2 0.6666666666666666
|
||||
(byte) getPoint::x
|
||||
(byte) getPoint::y
|
||||
(void()) main()
|
||||
(struct Point~) main::$0
|
||||
(byte~) main::$0_x 2.0
|
||||
(byte~) main::$0_y 2.0
|
||||
(struct Point~) main::$1
|
||||
(byte~) main::$1_x 2.0
|
||||
(byte~) main::$1_y 2.0
|
||||
(struct Point) main::point1 loadstore
|
||||
(struct Point) main::point2 loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ getPoint::return_x#2 ]
|
||||
[ getPoint::return_y#2 ]
|
||||
Added variable getPoint::return_x#0 to live range equivalence class [ getPoint::return_x#0 ]
|
||||
Added variable getPoint::return_y#0 to live range equivalence class [ getPoint::return_y#0 ]
|
||||
Added variable main::$0_x to live range equivalence class [ main::$0_x ]
|
||||
Added variable main::$0_y to live range equivalence class [ main::$0_y ]
|
||||
Added variable getPoint::return_x#1 to live range equivalence class [ getPoint::return_x#1 ]
|
||||
Added variable getPoint::return_y#1 to live range equivalence class [ getPoint::return_y#1 ]
|
||||
Added variable main::$1_x to live range equivalence class [ main::$1_x ]
|
||||
Added variable main::$1_y to live range equivalence class [ main::$1_y ]
|
||||
Added variable main::point1 to live range equivalence class [ main::point1 ]
|
||||
Added variable main::point2 to live range equivalence class [ main::point2 ]
|
||||
Complete equivalence classes
|
||||
[ getPoint::return_x#2 ]
|
||||
[ getPoint::return_y#2 ]
|
||||
[ getPoint::return_x#0 ]
|
||||
[ getPoint::return_y#0 ]
|
||||
[ main::$0_x ]
|
||||
[ main::$0_y ]
|
||||
[ getPoint::return_x#1 ]
|
||||
[ getPoint::return_y#1 ]
|
||||
[ main::$1_x ]
|
||||
[ main::$1_y ]
|
||||
[ main::point1 ]
|
||||
[ main::point2 ]
|
||||
Allocated zp[1]:2 [ getPoint::return_x#2 ]
|
||||
Allocated zp[1]:3 [ getPoint::return_y#2 ]
|
||||
Allocated zp[1]:4 [ getPoint::return_x#0 ]
|
||||
Allocated zp[1]:5 [ getPoint::return_y#0 ]
|
||||
Allocated zp[1]:6 [ main::$0_x ]
|
||||
Allocated zp[1]:7 [ main::$0_y ]
|
||||
Allocated zp[1]:8 [ getPoint::return_x#1 ]
|
||||
Allocated zp[1]:9 [ getPoint::return_y#1 ]
|
||||
Allocated zp[1]:10 [ main::$1_x ]
|
||||
Allocated zp[1]:11 [ main::$1_y ]
|
||||
Allocated zp[2]:12 [ main::point1 ]
|
||||
Allocated zp[2]:14 [ main::point2 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - call return value (not supported yet)
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from___b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label point1 = $c
|
||||
.label point2 = $e
|
||||
.label __0_x = 6
|
||||
.label __0_y = 7
|
||||
.label __1_x = $a
|
||||
.label __1_y = $b
|
||||
// [5] call getPoint
|
||||
// [24] phi from main to getPoint [phi:main->getPoint]
|
||||
getPoint_from_main:
|
||||
// [24] phi (byte) getPoint::return_y#2 = (byte) 3 [phi:main->getPoint#0] -- vbuz1=vbuc1
|
||||
lda #3
|
||||
sta.z getPoint.return_y_2
|
||||
// [24] phi (byte) getPoint::return_x#2 = (byte) 2 [phi:main->getPoint#1] -- vbuz1=vbuc1
|
||||
lda #2
|
||||
sta.z getPoint.return_x_2
|
||||
jsr getPoint
|
||||
// [6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2 -- vbuz1=vbuz2
|
||||
lda.z getPoint.return_x_2
|
||||
sta.z getPoint.return_x
|
||||
// [7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2 -- vbuz1=vbuz2
|
||||
lda.z getPoint.return_y_2
|
||||
sta.z getPoint.return_y
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [8] (byte~) main::$0_x ← (byte) getPoint::return_x#0 -- vbuz1=vbuz2
|
||||
lda.z getPoint.return_x
|
||||
sta.z __0_x
|
||||
// [9] (byte~) main::$0_y ← (byte) getPoint::return_y#0 -- vbuz1=vbuz2
|
||||
lda.z getPoint.return_y
|
||||
sta.z __0_y
|
||||
// [10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x -- _deref_pbuc1=vbuz1
|
||||
lda.z __0_x
|
||||
sta.z point1
|
||||
// [11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y -- _deref_pbuc1=vbuz1
|
||||
lda.z __0_y
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point1
|
||||
sta SCREEN
|
||||
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [14] call getPoint
|
||||
// [24] phi from main::@1 to getPoint [phi:main::@1->getPoint]
|
||||
getPoint_from___b1:
|
||||
// [24] phi (byte) getPoint::return_y#2 = (byte) 5 [phi:main::@1->getPoint#0] -- vbuz1=vbuc1
|
||||
lda #5
|
||||
sta.z getPoint.return_y_2
|
||||
// [24] phi (byte) getPoint::return_x#2 = (byte) 4 [phi:main::@1->getPoint#1] -- vbuz1=vbuc1
|
||||
lda #4
|
||||
sta.z getPoint.return_x_2
|
||||
jsr getPoint
|
||||
// [15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2 -- vbuz1=vbuz2
|
||||
lda.z getPoint.return_x_2
|
||||
sta.z getPoint.return_x_1
|
||||
// [16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2 -- vbuz1=vbuz2
|
||||
lda.z getPoint.return_y_2
|
||||
sta.z getPoint.return_y_1
|
||||
jmp __b2
|
||||
// main::@2
|
||||
__b2:
|
||||
// [17] (byte~) main::$1_x ← (byte) getPoint::return_x#1 -- vbuz1=vbuz2
|
||||
lda.z getPoint.return_x_1
|
||||
sta.z __1_x
|
||||
// [18] (byte~) main::$1_y ← (byte) getPoint::return_y#1 -- vbuz1=vbuz2
|
||||
lda.z getPoint.return_y_1
|
||||
sta.z __1_y
|
||||
// [19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1
|
||||
lda.z __1_x
|
||||
sta.z point2
|
||||
// [20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1
|
||||
lda.z __1_y
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
// [21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point2
|
||||
sta SCREEN+2
|
||||
// [22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point2+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [23] return
|
||||
rts
|
||||
}
|
||||
// getPoint
|
||||
getPoint: {
|
||||
.label return_x = 4
|
||||
.label return_y = 5
|
||||
.label return_x_1 = 8
|
||||
.label return_y_1 = 9
|
||||
.label return_x_2 = 2
|
||||
.label return_y_2 = 3
|
||||
jmp __breturn
|
||||
// getPoint::@return
|
||||
__breturn:
|
||||
// [25] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
|
||||
Statement [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) [ main::point2 ] ( main:2 [ main::point2 ] ) always clobbers reg byte a
|
||||
Statement [21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2) [ main::point2 ] ( main:2 [ main::point2 ] ) always clobbers reg byte a
|
||||
Statement [22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ getPoint::return_x#2 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:3 [ getPoint::return_y#2 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:4 [ getPoint::return_x#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:5 [ getPoint::return_y#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:6 [ main::$0_x ] : zp[1]:6 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:7 [ main::$0_y ] : zp[1]:7 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:8 [ getPoint::return_x#1 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:9 [ getPoint::return_y#1 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:10 [ main::$1_x ] : zp[1]:10 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:11 [ main::$1_y ] : zp[1]:11 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[2]:12 [ main::point1 ] : zp[2]:12 ,
|
||||
Potential registers zp[2]:14 [ main::point2 ] : zp[2]:14 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [getPoint] 2: zp[1]:4 [ getPoint::return_x#0 ] 2: zp[1]:5 [ getPoint::return_y#0 ] 2: zp[1]:8 [ getPoint::return_x#1 ] 2: zp[1]:9 [ getPoint::return_y#1 ] 1: zp[1]:2 [ getPoint::return_x#2 ] 0.67: zp[1]:3 [ getPoint::return_y#2 ]
|
||||
Uplift Scope [main] 2: zp[1]:6 [ main::$0_x ] 2: zp[1]:7 [ main::$0_y ] 2: zp[1]:10 [ main::$1_x ] 2: zp[1]:11 [ main::$1_y ] 0: zp[2]:12 [ main::point1 ] 0: zp[2]:14 [ main::point2 ]
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [getPoint] best 181 combination reg byte x [ getPoint::return_x#0 ] reg byte a [ getPoint::return_y#0 ] reg byte x [ getPoint::return_x#1 ] zp[1]:9 [ getPoint::return_y#1 ] zp[1]:2 [ getPoint::return_x#2 ] zp[1]:3 [ getPoint::return_y#2 ]
|
||||
Limited combination testing to 100 combinations of 4096 possible.
|
||||
Uplifting [main] best 163 combination reg byte x [ main::$0_x ] reg byte a [ main::$0_y ] reg byte x [ main::$1_x ] zp[1]:11 [ main::$1_y ] zp[2]:12 [ main::point1 ] zp[2]:14 [ main::point2 ]
|
||||
Limited combination testing to 100 combinations of 256 possible.
|
||||
Uplifting [Point] best 163 combination
|
||||
Uplifting [] best 163 combination
|
||||
Attempting to uplift remaining variables inzp[1]:9 [ getPoint::return_y#1 ]
|
||||
Uplifting [getPoint] best 157 combination reg byte a [ getPoint::return_y#1 ]
|
||||
Attempting to uplift remaining variables inzp[1]:11 [ main::$1_y ]
|
||||
Uplifting [main] best 151 combination reg byte a [ main::$1_y ]
|
||||
Attempting to uplift remaining variables inzp[1]:2 [ getPoint::return_x#2 ]
|
||||
Uplifting [getPoint] best 139 combination reg byte x [ getPoint::return_x#2 ]
|
||||
Attempting to uplift remaining variables inzp[1]:3 [ getPoint::return_y#2 ]
|
||||
Uplifting [getPoint] best 127 combination reg byte a [ getPoint::return_y#2 ]
|
||||
Allocated (was zp[2]:12) zp[2]:2 [ main::point1 ]
|
||||
Allocated (was zp[2]:14) zp[2]:4 [ main::point2 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - call return value (not supported yet)
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from___b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
// [5] call getPoint
|
||||
// [24] phi from main to getPoint [phi:main->getPoint]
|
||||
getPoint_from_main:
|
||||
// [24] phi (byte) getPoint::return_y#2 = (byte) 3 [phi:main->getPoint#0] -- vbuaa=vbuc1
|
||||
lda #3
|
||||
// [24] phi (byte) getPoint::return_x#2 = (byte) 2 [phi:main->getPoint#1] -- vbuxx=vbuc1
|
||||
ldx #2
|
||||
jsr getPoint
|
||||
// [6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2
|
||||
// [7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [8] (byte~) main::$0_x ← (byte) getPoint::return_x#0
|
||||
// [9] (byte~) main::$0_y ← (byte) getPoint::return_y#0
|
||||
// [10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x -- _deref_pbuc1=vbuxx
|
||||
stx.z point1
|
||||
// [11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y -- _deref_pbuc1=vbuaa
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// [12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point1
|
||||
sta SCREEN
|
||||
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// [14] call getPoint
|
||||
// [24] phi from main::@1 to getPoint [phi:main::@1->getPoint]
|
||||
getPoint_from___b1:
|
||||
// [24] phi (byte) getPoint::return_y#2 = (byte) 5 [phi:main::@1->getPoint#0] -- vbuaa=vbuc1
|
||||
lda #5
|
||||
// [24] phi (byte) getPoint::return_x#2 = (byte) 4 [phi:main::@1->getPoint#1] -- vbuxx=vbuc1
|
||||
ldx #4
|
||||
jsr getPoint
|
||||
// [15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2
|
||||
// [16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2
|
||||
jmp __b2
|
||||
// main::@2
|
||||
__b2:
|
||||
// [17] (byte~) main::$1_x ← (byte) getPoint::return_x#1
|
||||
// [18] (byte~) main::$1_y ← (byte) getPoint::return_y#1
|
||||
// [19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx
|
||||
stx.z point2
|
||||
// [20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
// [21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z point2
|
||||
sta SCREEN+2
|
||||
// [22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point2+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [23] return
|
||||
rts
|
||||
}
|
||||
// getPoint
|
||||
getPoint: {
|
||||
jmp __breturn
|
||||
// getPoint::@return
|
||||
__breturn:
|
||||
// [25] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __b2
|
||||
Removing instruction jmp __breturn
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing instruction lda.z point1 with TXA
|
||||
Replacing instruction lda.z point2 with TXA
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction main_from___b1:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction getPoint_from_main:
|
||||
Removing instruction __b1:
|
||||
Removing instruction getPoint_from___b1:
|
||||
Removing instruction __b2:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
|
||||
(label) getPoint::@return
|
||||
(byte) getPoint::p_x
|
||||
(byte) getPoint::p_y
|
||||
(struct Point) getPoint::return
|
||||
(byte) getPoint::return_x
|
||||
(byte) getPoint::return_x#0 reg byte x 2.0
|
||||
(byte) getPoint::return_x#1 reg byte x 2.0
|
||||
(byte) getPoint::return_x#2 reg byte x 1.0
|
||||
(byte) getPoint::return_y
|
||||
(byte) getPoint::return_y#0 reg byte a 2.0
|
||||
(byte) getPoint::return_y#1 reg byte a 2.0
|
||||
(byte) getPoint::return_y#2 reg byte a 0.6666666666666666
|
||||
(byte) getPoint::x
|
||||
(byte) getPoint::y
|
||||
(void()) main()
|
||||
(struct Point~) main::$0
|
||||
(byte~) main::$0_x reg byte x 2.0
|
||||
(byte~) main::$0_y reg byte a 2.0
|
||||
(struct Point~) main::$1
|
||||
(byte~) main::$1_x reg byte x 2.0
|
||||
(byte~) main::$1_y reg byte a 2.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
(struct Point) main::point2 loadstore zp[2]:4
|
||||
|
||||
reg byte x [ getPoint::return_x#2 ]
|
||||
reg byte a [ getPoint::return_y#2 ]
|
||||
reg byte x [ getPoint::return_x#0 ]
|
||||
reg byte a [ getPoint::return_y#0 ]
|
||||
reg byte x [ main::$0_x ]
|
||||
reg byte a [ main::$0_y ]
|
||||
reg byte x [ getPoint::return_x#1 ]
|
||||
reg byte a [ getPoint::return_y#1 ]
|
||||
reg byte x [ main::$1_x ]
|
||||
reg byte a [ main::$1_y ]
|
||||
zp[2]:2 [ main::point1 ]
|
||||
zp[2]:4 [ main::point2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 74
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - call return value (not supported yet)
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label point1 = 2
|
||||
.label point2 = 4
|
||||
// getPoint(2, 3)
|
||||
// [5] call getPoint
|
||||
// [24] phi from main to getPoint [phi:main->getPoint]
|
||||
// [24] phi (byte) getPoint::return_y#2 = (byte) 3 [phi:main->getPoint#0] -- vbuaa=vbuc1
|
||||
lda #3
|
||||
// [24] phi (byte) getPoint::return_x#2 = (byte) 2 [phi:main->getPoint#1] -- vbuxx=vbuc1
|
||||
ldx #2
|
||||
jsr getPoint
|
||||
// getPoint(2, 3)
|
||||
// [6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2
|
||||
// [7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2
|
||||
// main::@1
|
||||
// [8] (byte~) main::$0_x ← (byte) getPoint::return_x#0
|
||||
// [9] (byte~) main::$0_y ← (byte) getPoint::return_y#0
|
||||
// point1 = getPoint(2, 3)
|
||||
// [10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x -- _deref_pbuc1=vbuxx
|
||||
stx.z point1
|
||||
// [11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y -- _deref_pbuc1=vbuaa
|
||||
sta point1+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = point1.x
|
||||
// [12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
txa
|
||||
sta SCREEN
|
||||
// SCREEN[1] = point1.y
|
||||
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+1
|
||||
// getPoint(4, 5)
|
||||
// [14] call getPoint
|
||||
// [24] phi from main::@1 to getPoint [phi:main::@1->getPoint]
|
||||
// [24] phi (byte) getPoint::return_y#2 = (byte) 5 [phi:main::@1->getPoint#0] -- vbuaa=vbuc1
|
||||
lda #5
|
||||
// [24] phi (byte) getPoint::return_x#2 = (byte) 4 [phi:main::@1->getPoint#1] -- vbuxx=vbuc1
|
||||
ldx #4
|
||||
jsr getPoint
|
||||
// getPoint(4, 5)
|
||||
// [15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2
|
||||
// [16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2
|
||||
// main::@2
|
||||
// [17] (byte~) main::$1_x ← (byte) getPoint::return_x#1
|
||||
// [18] (byte~) main::$1_y ← (byte) getPoint::return_y#1
|
||||
// point2 = getPoint(4, 5)
|
||||
// [19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx
|
||||
stx.z point2
|
||||
// [20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa
|
||||
sta point2+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[2] = point2.x
|
||||
// [21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
|
||||
txa
|
||||
sta SCREEN+2
|
||||
// SCREEN[3] = point2.y
|
||||
// [22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point2+OFFSET_STRUCT_POINT_Y
|
||||
sta SCREEN+3
|
||||
// main::@return
|
||||
// }
|
||||
// [23] return
|
||||
rts
|
||||
}
|
||||
// getPoint
|
||||
getPoint: {
|
||||
// getPoint::@return
|
||||
// [25] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
47
src/test/ref/struct-23.sym
Normal file
47
src/test/ref/struct-23.sym
Normal file
@ -0,0 +1,47 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
|
||||
(label) getPoint::@return
|
||||
(byte) getPoint::p_x
|
||||
(byte) getPoint::p_y
|
||||
(struct Point) getPoint::return
|
||||
(byte) getPoint::return_x
|
||||
(byte) getPoint::return_x#0 reg byte x 2.0
|
||||
(byte) getPoint::return_x#1 reg byte x 2.0
|
||||
(byte) getPoint::return_x#2 reg byte x 1.0
|
||||
(byte) getPoint::return_y
|
||||
(byte) getPoint::return_y#0 reg byte a 2.0
|
||||
(byte) getPoint::return_y#1 reg byte a 2.0
|
||||
(byte) getPoint::return_y#2 reg byte a 0.6666666666666666
|
||||
(byte) getPoint::x
|
||||
(byte) getPoint::y
|
||||
(void()) main()
|
||||
(struct Point~) main::$0
|
||||
(byte~) main::$0_x reg byte x 2.0
|
||||
(byte~) main::$0_y reg byte a 2.0
|
||||
(struct Point~) main::$1
|
||||
(byte~) main::$1_x reg byte x 2.0
|
||||
(byte~) main::$1_y reg byte a 2.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(struct Point) main::point1 loadstore zp[2]:2
|
||||
(struct Point) main::point2 loadstore zp[2]:4
|
||||
|
||||
reg byte x [ getPoint::return_x#2 ]
|
||||
reg byte a [ getPoint::return_y#2 ]
|
||||
reg byte x [ getPoint::return_x#0 ]
|
||||
reg byte a [ getPoint::return_y#0 ]
|
||||
reg byte x [ main::$0_x ]
|
||||
reg byte a [ main::$0_y ]
|
||||
reg byte x [ getPoint::return_x#1 ]
|
||||
reg byte a [ getPoint::return_y#1 ]
|
||||
reg byte x [ main::$1_x ]
|
||||
reg byte a [ main::$1_y ]
|
||||
zp[2]:2 [ main::point1 ]
|
||||
zp[2]:4 [ main::point2 ]
|
@ -4,6 +4,9 @@ Converted struct value to member variables (struct Point) main::p
|
||||
Created struct value member variable (struct Point) main::c_center
|
||||
Created struct value member variable (byte) main::c_radius
|
||||
Converted struct value to member variables (struct Circle) main::c
|
||||
Created struct value member variable (byte) main::c_center_x
|
||||
Created struct value member variable (byte) main::c_center_y
|
||||
Converted struct value to member variables (struct Point) main::c_center
|
||||
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) $a
|
||||
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) $a
|
||||
Adding struct value list initializer (struct Point) main::c_center ← (struct Point) main::p
|
||||
@ -11,9 +14,6 @@ Adding struct value list initializer (byte) main::c_radius ← (byte)(number) 5
|
||||
Replacing struct member reference (struct Circle) main::c.center with member unwinding reference (struct Point) main::c_center
|
||||
Replacing struct member reference (struct Circle) main::c.center with member unwinding reference (struct Point) main::c_center
|
||||
Replacing struct member reference (struct Circle) main::c.radius with member unwinding reference (byte) main::c_radius
|
||||
Created struct value member variable (byte) main::c_center_x
|
||||
Created struct value member variable (byte) main::c_center_y
|
||||
Converted struct value to member variables (struct Point) main::c_center
|
||||
Adding struct value member variable copy (byte) main::c_center_x ← (byte) main::p_x
|
||||
Adding struct value member variable copy (byte) main::c_center_y ← (byte) main::p_y
|
||||
Replacing struct member reference (struct Point) main::c_center.x with member unwinding reference (byte) main::c_center_x
|
||||
|
@ -1,6 +1,18 @@
|
||||
Created struct value member variable (struct Circle) main::t_c1
|
||||
Created struct value member variable (struct Circle) main::t_c2
|
||||
Converted struct value to member variables (struct TwoCircles) main::t
|
||||
Created struct value member variable (struct Point) main::t_c1_center
|
||||
Created struct value member variable (byte) main::t_c1_radius
|
||||
Converted struct value to member variables (struct Circle) main::t_c1
|
||||
Created struct value member variable (struct Point) main::t_c2_center
|
||||
Created struct value member variable (byte) main::t_c2_radius
|
||||
Converted struct value to member variables (struct Circle) main::t_c2
|
||||
Created struct value member variable (byte) main::t_c1_center_x
|
||||
Created struct value member variable (byte) main::t_c1_center_y
|
||||
Converted struct value to member variables (struct Point) main::t_c1_center
|
||||
Created struct value member variable (byte) main::t_c2_center_x
|
||||
Created struct value member variable (byte) main::t_c2_center_y
|
||||
Converted struct value to member variables (struct Point) main::t_c2_center
|
||||
Adding struct value member variable copy (struct Circle) main::t_c1 ← { center: { x: (byte)(number) 1, y: (byte)(number) 2 }, radius: (byte)(number) 3 }
|
||||
Adding struct value member variable copy (struct Circle) main::t_c2 ← { center: { x: (byte)(number) 4, y: (byte)(number) 5 }, radius: (byte)(number) 6 }
|
||||
Replacing struct member reference (struct TwoCircles) main::t.c1 with member unwinding reference (struct Circle) main::t_c1
|
||||
@ -9,12 +21,6 @@ Replacing struct member reference (struct TwoCircles) main::t.c1 with member unw
|
||||
Replacing struct member reference (struct TwoCircles) main::t.c2 with member unwinding reference (struct Circle) main::t_c2
|
||||
Replacing struct member reference (struct TwoCircles) main::t.c2 with member unwinding reference (struct Circle) main::t_c2
|
||||
Replacing struct member reference (struct TwoCircles) main::t.c2 with member unwinding reference (struct Circle) main::t_c2
|
||||
Created struct value member variable (struct Point) main::t_c1_center
|
||||
Created struct value member variable (byte) main::t_c1_radius
|
||||
Converted struct value to member variables (struct Circle) main::t_c1
|
||||
Created struct value member variable (struct Point) main::t_c2_center
|
||||
Created struct value member variable (byte) main::t_c2_radius
|
||||
Converted struct value to member variables (struct Circle) main::t_c2
|
||||
Adding struct value member variable copy (struct Point) main::t_c1_center ← { x: (byte)(number) 1, y: (byte)(number) 2 }
|
||||
Adding struct value member variable copy (byte) main::t_c1_radius ← (byte)(number) 3
|
||||
Adding struct value member variable copy (struct Point) main::t_c2_center ← { x: (byte)(number) 4, y: (byte)(number) 5 }
|
||||
@ -25,12 +31,6 @@ Replacing struct member reference (struct Circle) main::t_c1.radius with member
|
||||
Replacing struct member reference (struct Circle) main::t_c2.center with member unwinding reference (struct Point) main::t_c2_center
|
||||
Replacing struct member reference (struct Circle) main::t_c2.center with member unwinding reference (struct Point) main::t_c2_center
|
||||
Replacing struct member reference (struct Circle) main::t_c2.radius with member unwinding reference (byte) main::t_c2_radius
|
||||
Created struct value member variable (byte) main::t_c1_center_x
|
||||
Created struct value member variable (byte) main::t_c1_center_y
|
||||
Converted struct value to member variables (struct Point) main::t_c1_center
|
||||
Created struct value member variable (byte) main::t_c2_center_x
|
||||
Created struct value member variable (byte) main::t_c2_center_y
|
||||
Converted struct value to member variables (struct Point) main::t_c2_center
|
||||
Adding struct value member variable copy (byte) main::t_c1_center_x ← (byte)(number) 1
|
||||
Adding struct value member variable copy (byte) main::t_c1_center_y ← (byte)(number) 2
|
||||
Adding struct value member variable copy (byte) main::t_c2_center_x ← (byte)(number) 4
|
||||
|
@ -7,6 +7,9 @@ Converted struct value to member variables (struct Circle) main::c
|
||||
Created struct value member variable (byte) main::point_x
|
||||
Created struct value member variable (byte) main::point_y
|
||||
Converted struct value to member variables (struct Point) main::point
|
||||
Created struct value member variable (byte) main::c_center_x
|
||||
Created struct value member variable (byte) main::c_center_y
|
||||
Converted struct value to member variables (struct Point) main::c_center
|
||||
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) $a
|
||||
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) $a
|
||||
Adding struct value list initializer (struct Point) main::c_center ← (struct Point) main::p
|
||||
@ -15,9 +18,6 @@ Replacing struct member reference (struct Circle) main::c.center with member unw
|
||||
Replacing struct member reference (struct Point) main::point.x with member unwinding reference (byte) main::point_x
|
||||
Replacing struct member reference (struct Point) main::point.y with member unwinding reference (byte) main::point_y
|
||||
Replacing struct member reference (struct Circle) main::c.radius with member unwinding reference (byte) main::c_radius
|
||||
Created struct value member variable (byte) main::c_center_x
|
||||
Created struct value member variable (byte) main::c_center_y
|
||||
Converted struct value to member variables (struct Point) main::c_center
|
||||
Adding struct value member variable copy (byte) main::c_center_x ← (byte) main::p_x
|
||||
Adding struct value member variable copy (byte) main::c_center_y ← (byte) main::p_y
|
||||
Adding struct value member variable copy (byte) main::point_x ← (byte) main::c_center_x
|
||||
|
@ -4,6 +4,9 @@ Converted struct value to member variables (struct Point) main::p
|
||||
Created struct value member variable (struct Point) main::c_center
|
||||
Created struct value member variable (byte) main::c_radius
|
||||
Converted struct value to member variables (struct Circle) main::c
|
||||
Created struct value member variable (byte) main::c_center_x
|
||||
Created struct value member variable (byte) main::c_center_y
|
||||
Converted struct value to member variables (struct Point) main::c_center
|
||||
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) $a
|
||||
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) $a
|
||||
Adding struct value member variable default initializer (struct Point) main::c_center ← {}
|
||||
@ -13,9 +16,6 @@ Replacing struct member reference (struct Circle) main::c.radius with member unw
|
||||
Replacing struct member reference (struct Circle) main::c.center with member unwinding reference (struct Point) main::c_center
|
||||
Replacing struct member reference (struct Circle) main::c.center with member unwinding reference (struct Point) main::c_center
|
||||
Replacing struct member reference (struct Circle) main::c.radius with member unwinding reference (byte) main::c_radius
|
||||
Created struct value member variable (byte) main::c_center_x
|
||||
Created struct value member variable (byte) main::c_center_y
|
||||
Converted struct value to member variables (struct Point) main::c_center
|
||||
Adding struct value member variable default initializer (byte) main::c_center_x ← (byte) 0
|
||||
Adding struct value member variable default initializer (byte) main::c_center_y ← (byte) 0
|
||||
Adding struct value member variable copy (byte) main::c_center_x ← (byte) main::p_x
|
||||
|
@ -5,13 +5,12 @@
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label q = p_x
|
||||
.label p_x = 2
|
||||
.label p_y = 3
|
||||
.label q = p
|
||||
.label p = 2
|
||||
lda #2
|
||||
sta.z p_x
|
||||
sta.z p
|
||||
lda #3
|
||||
sta.z p_y
|
||||
sta p+OFFSET_STRUCT_POINT_Y
|
||||
lda.z q
|
||||
sta SCREEN
|
||||
lda q+OFFSET_STRUCT_POINT_Y
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] (byte) main::p_x ← (byte) 2
|
||||
[5] (byte) main::p_y ← (byte) 3
|
||||
[4] *((byte*)&(struct Point) main::p) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q)
|
||||
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
|
@ -1,12 +1,10 @@
|
||||
Setting inferred volatile on symbol affected by address-of (struct Point*) main::q ← &(struct Point) main::p
|
||||
Created struct value member variable (byte) main::p_x
|
||||
Created struct value member variable (byte) main::p_y
|
||||
Converted struct value to member variables (struct Point) main::p
|
||||
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) 2
|
||||
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) 3
|
||||
Adding struct value member variable copy *((byte*~) main::$0) ← (byte)(number) 2
|
||||
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 3
|
||||
Rewriting struct pointer member access *((struct Point*) main::q).x
|
||||
Rewriting struct pointer member access *((struct Point*) main::q).y
|
||||
Identified constant variable (struct Point*) main::q
|
||||
Adding versioned struct unwinding for (struct Point) main::p
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
@ -14,13 +12,15 @@ CONTROL FLOW GRAPH SSA
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(byte) main::p_x ← (byte)(number) 2
|
||||
(byte) main::p_y ← (byte)(number) 3
|
||||
(struct Point) main::p ← struct-unwound {(byte) main::p_x, (byte) main::p_y}
|
||||
(byte*~) main::$0 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$0)
|
||||
(byte*~) main::$1 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$1)
|
||||
(byte*~) main::$0 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$0) ← (byte)(number) 2
|
||||
(byte*~) main::$1 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$1) ← (byte)(number) 3
|
||||
(struct Point) main::p ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
(byte*~) main::$2 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$2)
|
||||
(byte*~) main::$3 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$3)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
@ -44,15 +44,15 @@ SYMBOL TABLE SSA
|
||||
(void()) main()
|
||||
(byte*~) main::$0
|
||||
(byte*~) main::$1
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$3
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*)(number) $400
|
||||
(struct Point) main::p loadstore
|
||||
(byte) main::p_x loadstore
|
||||
(byte) main::p_y loadstore
|
||||
(const struct Point*) main::q = &(struct Point) main::p
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$0)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$1)
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$2)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$3)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 2
|
||||
@ -63,22 +63,27 @@ Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Rewriting struct address-of to first member &(struct Point) main::p
|
||||
Successful SSA optimization PassNStructAddressOfRewriting
|
||||
Constant right-side identified [3] (byte*~) main::$0 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [5] (byte*~) main::$1 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Removing C-classic struct-unwound assignment [4] (struct Point) main::p ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
|
||||
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [5] (byte*~) main::$2 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [7] (byte*~) main::$3 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$0 = (byte*)main::q+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$1 = (byte*)main::q+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$0 = (byte*)&main::p+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$1 = (byte*)&main::p+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$2 = (byte*)main::q+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$3 = (byte*)main::q+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero (byte*)&main::p in
|
||||
Simplifying expression containing zero (byte*)main::q in
|
||||
Simplifying expression containing zero main::SCREEN in [4] *((const byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$0)
|
||||
Simplifying expression containing zero main::SCREEN in [6] *((const byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$2)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (struct Point) main::p and assignment [2] (struct Point) main::p ← struct-unwound {(byte) main::p_x, (byte) main::p_y}
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined main::$1 = (byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$0 = (byte*)(const struct Point*) main::q
|
||||
Constant inlined main::$3 = (byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$1 = (byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$2 = (byte*)(const struct Point*) main::q
|
||||
Constant inlined main::$0 = (byte*)&(struct Point) main::p
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(main::SCREEN+1)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
@ -109,8 +114,8 @@ FINAL CONTROL FLOW GRAPH
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] (byte) main::p_x ← (byte) 2
|
||||
[5] (byte) main::p_y ← (byte) 3
|
||||
[4] *((byte*)&(struct Point) main::p) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q)
|
||||
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y)
|
||||
to:main::@return
|
||||
@ -123,17 +128,13 @@ VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(void()) main()
|
||||
(byte) main::p_x loadstore 20.0
|
||||
(byte) main::p_y loadstore 20.0
|
||||
(struct Point) main::p loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::p_x to live range equivalence class [ main::p_x ]
|
||||
Added variable main::p_y to live range equivalence class [ main::p_y ]
|
||||
Added variable main::p to live range equivalence class [ main::p ]
|
||||
Complete equivalence classes
|
||||
[ main::p_x ]
|
||||
[ main::p_y ]
|
||||
Allocated zp[1]:2 [ main::p_x ]
|
||||
Allocated zp[1]:3 [ main::p_y ]
|
||||
[ main::p ]
|
||||
Allocated zp[2]:2 [ main::p ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
@ -162,15 +163,14 @@ __bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label q = p_x
|
||||
.label p_x = 2
|
||||
.label p_y = 3
|
||||
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
|
||||
.label q = p
|
||||
.label p = 2
|
||||
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p_x
|
||||
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
|
||||
sta.z p
|
||||
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta.z p_y
|
||||
sta p+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z q
|
||||
sta SCREEN
|
||||
@ -186,25 +186,20 @@ main: {
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] (byte) main::p_x ← (byte) 2 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [5] (byte) main::p_y ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [4] *((byte*)&(struct Point) main::p) ← (byte) 2 [ main::p ] ( main:2 [ main::p ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ main::p_x ] : zp[1]:2 ,
|
||||
Potential registers zp[1]:3 [ main::p_y ] : zp[1]:3 ,
|
||||
Potential registers zp[2]:2 [ main::p ] : zp[2]:2 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 20: zp[1]:2 [ main::p_x ] 20: zp[1]:3 [ main::p_y ]
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main] 0: zp[2]:2 [ main::p ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 46 combination zp[1]:2 [ main::p_x ] zp[1]:3 [ main::p_y ]
|
||||
Uplifting [Point] best 46 combination
|
||||
Uplifting [] best 46 combination
|
||||
Attempting to uplift remaining variables inzp[1]:2 [ main::p_x ]
|
||||
Uplifting [main] best 46 combination zp[1]:2 [ main::p_x ]
|
||||
Attempting to uplift remaining variables inzp[1]:3 [ main::p_y ]
|
||||
Uplifting [main] best 46 combination zp[1]:3 [ main::p_y ]
|
||||
Uplifting [Point] best 47 combination
|
||||
Uplifting [main] best 47 combination zp[2]:2 [ main::p ]
|
||||
Uplifting [] best 47 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -232,15 +227,14 @@ __bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label q = p_x
|
||||
.label p_x = 2
|
||||
.label p_y = 3
|
||||
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
|
||||
.label q = p
|
||||
.label p = 2
|
||||
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p_x
|
||||
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
|
||||
sta.z p
|
||||
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta.z p_y
|
||||
sta p+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z q
|
||||
sta SCREEN
|
||||
@ -284,16 +278,14 @@ FINAL SYMBOL TABLE
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*) 1024
|
||||
(byte) main::p_x loadstore zp[1]:2 20.0
|
||||
(byte) main::p_y loadstore zp[1]:3 20.0
|
||||
(const struct Point*) main::q = (struct Point*)&(byte) main::p_x
|
||||
(struct Point) main::p loadstore zp[2]:2
|
||||
(const struct Point*) main::q = &(struct Point) main::p
|
||||
|
||||
zp[1]:2 [ main::p_x ]
|
||||
zp[1]:3 [ main::p_y ]
|
||||
zp[2]:2 [ main::p ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 31
|
||||
Score: 32
|
||||
|
||||
// File Comments
|
||||
// Minimal struct - using address-of
|
||||
@ -312,16 +304,15 @@ Score: 31
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label q = p_x
|
||||
.label p_x = 2
|
||||
.label p_y = 3
|
||||
.label q = p
|
||||
.label p = 2
|
||||
// p = { 2, 3 }
|
||||
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
|
||||
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p_x
|
||||
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
|
||||
sta.z p
|
||||
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta.z p_y
|
||||
sta p+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[0] = q->x
|
||||
// [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda.z q
|
||||
|
@ -7,9 +7,7 @@
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*) 1024
|
||||
(byte) main::p_x loadstore zp[1]:2 20.0
|
||||
(byte) main::p_y loadstore zp[1]:3 20.0
|
||||
(const struct Point*) main::q = (struct Point*)&(byte) main::p_x
|
||||
(struct Point) main::p loadstore zp[2]:2
|
||||
(const struct Point*) main::q = &(struct Point) main::p
|
||||
|
||||
zp[1]:2 [ main::p_x ]
|
||||
zp[1]:3 [ main::p_y ]
|
||||
zp[2]:2 [ main::p ]
|
||||
|
@ -5,13 +5,12 @@
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label q = p_x
|
||||
.label p_x = 2
|
||||
.label p_y = 3
|
||||
.label q = p
|
||||
.label p = 2
|
||||
lda #2
|
||||
sta.z p_x
|
||||
sta.z p
|
||||
lda #3
|
||||
sta.z p_y
|
||||
sta p+OFFSET_STRUCT_POINT_Y
|
||||
jsr set
|
||||
lda.z q
|
||||
sta SCREEN
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] (byte) main::p_x ← (byte) 2
|
||||
[5] (byte) main::p_y ← (byte) 3
|
||||
[4] *((byte*)&(struct Point) main::p) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] call set
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
|
@ -1,15 +1,13 @@
|
||||
Setting inferred volatile on symbol affected by address-of (struct Point*) main::q ← &(struct Point) main::p
|
||||
Created struct value member variable (byte) main::p_x
|
||||
Created struct value member variable (byte) main::p_y
|
||||
Converted struct value to member variables (struct Point) main::p
|
||||
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) 2
|
||||
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) 3
|
||||
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 2
|
||||
Adding struct value member variable copy *((byte*~) main::$2) ← (byte)(number) 3
|
||||
Rewriting struct pointer member access *((struct Point*) main::q).x
|
||||
Rewriting struct pointer member access *((struct Point*) main::q).y
|
||||
Rewriting struct pointer member access *((struct Point*) set::ptr).x
|
||||
Rewriting struct pointer member access *((struct Point*) set::ptr).y
|
||||
Identified constant variable (struct Point*) main::q
|
||||
Culled Empty Block (label) @1
|
||||
Adding versioned struct unwinding for (struct Point) main::p
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
@ -17,17 +15,19 @@ CONTROL FLOW GRAPH SSA
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @2
|
||||
(byte) main::p_x ← (byte)(number) 2
|
||||
(byte) main::p_y ← (byte)(number) 3
|
||||
(struct Point) main::p ← struct-unwound {(byte) main::p_x, (byte) main::p_y}
|
||||
(byte*~) main::$1 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((byte*~) main::$1) ← (byte)(number) 2
|
||||
(byte*~) main::$2 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((byte*~) main::$2) ← (byte)(number) 3
|
||||
(struct Point) main::p ← struct-unwound {*((byte*~) main::$1), *((byte*~) main::$2)}
|
||||
(struct Point*) set::ptr#0 ← (const struct Point*) main::q
|
||||
call set
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
(byte*~) main::$1 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$1)
|
||||
(byte*~) main::$2 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$2)
|
||||
(byte*~) main::$3 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
|
||||
*((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$3)
|
||||
(byte*~) main::$4 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
*((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$4)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
@ -63,12 +63,12 @@ SYMBOL TABLE SSA
|
||||
(void()) main()
|
||||
(byte*~) main::$1
|
||||
(byte*~) main::$2
|
||||
(byte*~) main::$3
|
||||
(byte*~) main::$4
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*)(number) $400
|
||||
(struct Point) main::p loadstore
|
||||
(byte) main::p_x loadstore
|
||||
(byte) main::p_y loadstore
|
||||
(const struct Point*) main::q = &(struct Point) main::p
|
||||
(void()) set((struct Point*) set::ptr)
|
||||
(byte*~) set::$0
|
||||
@ -78,8 +78,8 @@ SYMBOL TABLE SSA
|
||||
(struct Point*) set::ptr#0
|
||||
(struct Point*) set::ptr#1
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$1)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$2)
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$3)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$4)
|
||||
Adding number conversion cast (unumber) 4 in *((byte*~) set::$0) ← (number) 4
|
||||
Adding number conversion cast (unumber) 5 in *((byte*~) set::$1) ← (number) 5
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
@ -101,34 +101,39 @@ Finalized unsigned number type (byte) 5
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Identical Phi Values (struct Point*) set::ptr#1 (struct Point*) set::ptr#0
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Rewriting struct address-of to first member &(struct Point) main::p
|
||||
Successful SSA optimization PassNStructAddressOfRewriting
|
||||
Constant right-side identified [5] (byte*~) main::$1 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [7] (byte*~) main::$2 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Removing C-classic struct-unwound assignment [4] (struct Point) main::p ← struct-unwound {*((byte*~) main::$1), *((byte*~) main::$2)}
|
||||
Constant right-side identified [0] (byte*~) main::$1 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [2] (byte*~) main::$2 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant right-side identified [7] (byte*~) main::$3 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant right-side identified [9] (byte*~) main::$4 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$1 = (byte*)&main::p+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$2 = (byte*)&main::p+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const struct Point*) set::ptr#0 = main::q
|
||||
Constant (const byte*) main::$1 = (byte*)main::q+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$2 = (byte*)main::q+OFFSET_STRUCT_POINT_Y
|
||||
Constant (const byte*) main::$3 = (byte*)main::q+OFFSET_STRUCT_POINT_X
|
||||
Constant (const byte*) main::$4 = (byte*)main::q+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte*)set::ptr#0 in [11] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)set::ptr#0 in [13] (byte*~) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant value identified (byte*)set::ptr#0 in [13] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (byte*)set::ptr#0 in [15] (byte*~) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Converting *(pointer+n) to pointer[n] [12] *((byte*~) set::$0) ← (byte) 4 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [14] *((byte*~) set::$1) ← (byte) 5 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_Y)
|
||||
Converting *(pointer+n) to pointer[n] [14] *((byte*~) set::$0) ← (byte) 4 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_X)
|
||||
Converting *(pointer+n) to pointer[n] [16] *((byte*~) set::$1) ← (byte) 5 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_Y)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying expression containing zero (byte*)&main::p in
|
||||
Simplifying expression containing zero (byte*)main::q in
|
||||
Simplifying expression containing zero main::SCREEN in [6] *((const byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$1)
|
||||
Simplifying expression containing zero (byte*)set::ptr#0 in [11] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)set::ptr#0 in [12] *((byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
|
||||
Simplifying expression containing zero main::SCREEN in [8] *((const byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$3)
|
||||
Simplifying expression containing zero (byte*)set::ptr#0 in [13] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Simplifying expression containing zero (byte*)set::ptr#0 in [14] *((byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (struct Point) main::p and assignment [2] (struct Point) main::p ← struct-unwound {(byte) main::p_x, (byte) main::p_y}
|
||||
Eliminating unused variable (byte*~) set::$0 and assignment [7] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0
|
||||
Eliminating unused variable (byte*~) set::$1 and assignment [9] (byte*~) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused variable (byte*~) set::$0 and assignment [6] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0
|
||||
Eliminating unused variable (byte*~) set::$1 and assignment [8] (byte*~) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant inlined set::ptr#0 = (const struct Point*) main::q
|
||||
Constant inlined main::$1 = (byte*)(const struct Point*) main::q
|
||||
Constant inlined main::$2 = (byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$3 = (byte*)(const struct Point*) main::q
|
||||
Constant inlined main::$4 = (byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined main::$1 = (byte*)&(struct Point) main::p
|
||||
Constant inlined main::$2 = (byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(main::SCREEN+1)
|
||||
Consolidated array index constant in *((byte*)main::q+OFFSET_STRUCT_POINT_Y)
|
||||
@ -162,8 +167,8 @@ FINAL CONTROL FLOW GRAPH
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] (byte) main::p_x ← (byte) 2
|
||||
[5] (byte) main::p_y ← (byte) 3
|
||||
[4] *((byte*)&(struct Point) main::p) ← (byte) 2
|
||||
[5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
|
||||
[6] call set
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
@ -188,19 +193,15 @@ VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(byte) Point::y
|
||||
(void()) main()
|
||||
(byte) main::p_x loadstore 20.0
|
||||
(byte) main::p_y loadstore 20.0
|
||||
(struct Point) main::p loadstore
|
||||
(void()) set((struct Point*) set::ptr)
|
||||
(struct Point*) set::ptr
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::p_x to live range equivalence class [ main::p_x ]
|
||||
Added variable main::p_y to live range equivalence class [ main::p_y ]
|
||||
Added variable main::p to live range equivalence class [ main::p ]
|
||||
Complete equivalence classes
|
||||
[ main::p_x ]
|
||||
[ main::p_y ]
|
||||
Allocated zp[1]:2 [ main::p_x ]
|
||||
Allocated zp[1]:3 [ main::p_y ]
|
||||
[ main::p ]
|
||||
Allocated zp[2]:2 [ main::p ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
@ -229,15 +230,14 @@ __bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label q = p_x
|
||||
.label p_x = 2
|
||||
.label p_y = 3
|
||||
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
|
||||
.label q = p
|
||||
.label p = 2
|
||||
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p_x
|
||||
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
|
||||
sta.z p
|
||||
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta.z p_y
|
||||
sta p+OFFSET_STRUCT_POINT_Y
|
||||
// [6] call set
|
||||
jsr set
|
||||
jmp __b1
|
||||
@ -272,29 +272,24 @@ set: {
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] (byte) main::p_x ← (byte) 2 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [5] (byte) main::p_y ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [4] *((byte*)&(struct Point) main::p) ← (byte) 2 [ main::p ] ( main:2 [ main::p ] ) always clobbers reg byte a
|
||||
Statement [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [8] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [10] *((byte*)(const struct Point*) main::q) ← (byte) 4 [ ] ( main:2::set:6 [ ] ) always clobbers reg byte a
|
||||
Statement [11] *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ ] ( main:2::set:6 [ ] ) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ main::p_x ] : zp[1]:2 ,
|
||||
Potential registers zp[1]:3 [ main::p_y ] : zp[1]:3 ,
|
||||
Potential registers zp[2]:2 [ main::p ] : zp[2]:2 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 20: zp[1]:2 [ main::p_x ] 20: zp[1]:3 [ main::p_y ]
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main] 0: zp[2]:2 [ main::p ]
|
||||
Uplift Scope [set]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 75 combination zp[1]:2 [ main::p_x ] zp[1]:3 [ main::p_y ]
|
||||
Uplifting [Point] best 75 combination
|
||||
Uplifting [set] best 75 combination
|
||||
Uplifting [] best 75 combination
|
||||
Attempting to uplift remaining variables inzp[1]:2 [ main::p_x ]
|
||||
Uplifting [main] best 75 combination zp[1]:2 [ main::p_x ]
|
||||
Attempting to uplift remaining variables inzp[1]:3 [ main::p_y ]
|
||||
Uplifting [main] best 75 combination zp[1]:3 [ main::p_y ]
|
||||
Uplifting [Point] best 76 combination
|
||||
Uplifting [main] best 76 combination zp[2]:2 [ main::p ]
|
||||
Uplifting [set] best 76 combination
|
||||
Uplifting [] best 76 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -322,15 +317,14 @@ __bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label q = p_x
|
||||
.label p_x = 2
|
||||
.label p_y = 3
|
||||
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
|
||||
.label q = p
|
||||
.label p = 2
|
||||
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p_x
|
||||
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
|
||||
sta.z p
|
||||
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta.z p_y
|
||||
sta p+OFFSET_STRUCT_POINT_Y
|
||||
// [6] call set
|
||||
jsr set
|
||||
jmp __b1
|
||||
@ -398,19 +392,17 @@ FINAL SYMBOL TABLE
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*) 1024
|
||||
(byte) main::p_x loadstore zp[1]:2 20.0
|
||||
(byte) main::p_y loadstore zp[1]:3 20.0
|
||||
(const struct Point*) main::q = (struct Point*)&(byte) main::p_x
|
||||
(struct Point) main::p loadstore zp[2]:2
|
||||
(const struct Point*) main::q = &(struct Point) main::p
|
||||
(void()) set((struct Point*) set::ptr)
|
||||
(label) set::@return
|
||||
(struct Point*) set::ptr
|
||||
|
||||
zp[1]:2 [ main::p_x ]
|
||||
zp[1]:3 [ main::p_y ]
|
||||
zp[2]:2 [ main::p ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 54
|
||||
Score: 55
|
||||
|
||||
// File Comments
|
||||
// Minimal struct - using address-of and passing it to a function
|
||||
@ -429,16 +421,15 @@ Score: 54
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
.label q = p_x
|
||||
.label p_x = 2
|
||||
.label p_y = 3
|
||||
.label q = p
|
||||
.label p = 2
|
||||
// p = { 2, 3 }
|
||||
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
|
||||
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta.z p_x
|
||||
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
|
||||
sta.z p
|
||||
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
|
||||
lda #3
|
||||
sta.z p_y
|
||||
sta p+OFFSET_STRUCT_POINT_Y
|
||||
// set(q)
|
||||
// [6] call set
|
||||
jsr set
|
||||
|
@ -8,12 +8,10 @@
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN = (byte*) 1024
|
||||
(byte) main::p_x loadstore zp[1]:2 20.0
|
||||
(byte) main::p_y loadstore zp[1]:3 20.0
|
||||
(const struct Point*) main::q = (struct Point*)&(byte) main::p_x
|
||||
(struct Point) main::p loadstore zp[2]:2
|
||||
(const struct Point*) main::q = &(struct Point) main::p
|
||||
(void()) set((struct Point*) set::ptr)
|
||||
(label) set::@return
|
||||
(struct Point*) set::ptr
|
||||
|
||||
zp[1]:2 [ main::p_x ]
|
||||
zp[1]:3 [ main::p_y ]
|
||||
zp[2]:2 [ main::p ]
|
||||
|
Loading…
x
Reference in New Issue
Block a user