1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-03-24 15:32:58 +00:00

Working on new ValueSource based unwinding!

This commit is contained in:
jespergravgaard 2020-02-03 08:30:17 +01:00
parent ae79e813a2
commit a50b295c45
9 changed files with 457 additions and 31 deletions

@ -199,6 +199,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
LValue lValue = assignment.getlValue();
SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
if(lValueType instanceof SymbolTypeStruct && assignment.getOperator() == null) {
// Assignment to a struct
SymbolTypeStruct lValueStructType = (SymbolTypeStruct) lValueType;
RValue rValue = assignment.getrValue2();
@ -209,6 +210,19 @@ public class Pass1UnwindStructValues extends Pass1Base {
if(assignment.getrValue2() instanceof MemcpyValue || assignment.getrValue2() instanceof MemsetValue)
return false;
ValueSource lValueSource = getValueSource(lValue, assignment, stmtIt, currentBlock);
ValueSource rValueSource = getValueSource(rValue, assignment, stmtIt, currentBlock);
List<RValue> lValueUnwoundList = new ArrayList<>();
if(copyValues(lValueSource, rValueSource, lValueUnwoundList, initialAssignment, assignment, currentBlock, stmtIt)) {
if(lValue instanceof VariableRef) {
StructUnwoundPlaceholder unwoundPlaceholder = new StructUnwoundPlaceholder(lValueStructType, lValueUnwoundList);
assignment.setrValue2(unwoundPlaceholder);
} else {
stmtIt.remove();
}
return true;
}
// Check for bulk assignable values
if(isBulkAssignable(lValue) && isBulkAssignable(rValue)) {
RValueUnwinding lValueUnwinding = getValueUnwinding(lValue, assignment, stmtIt, currentBlock);
@ -253,6 +267,67 @@ public class Pass1UnwindStructValues extends Pass1Base {
return false;
}
private boolean copyValues(ValueSource lValueSource, ValueSource rValueSource, List<RValue> lValueUnwoundList, boolean initialAssignment, Statement currentStmt, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt) {
if(lValueSource==null || rValueSource==null)
return false;
if(lValueSource.isSimple() && rValueSource.isSimple()) {
stmtIt.previous();
LValue lValueRef = (LValue) lValueSource.getSimpleValue(getScope());
RValue rValueRef = rValueSource.getSimpleValue(getScope());
if(lValueUnwoundList != null)
lValueUnwoundList.add(lValueRef);
Statement copyStmt = new StatementAssignment(lValueRef, rValueRef, initialAssignment, currentStmt.getSource(), Comment.NO_COMMENTS);
stmtIt.add(copyStmt);
stmtIt.next();
getLog().append("Adding value simple copy " + copyStmt.toString(getProgram(), false));
return true;
} else if(lValueSource.isBulkCopyable() && rValueSource.isBulkCopyable()) {
// Use bulk unwinding for a struct member that is an array
stmtIt.previous();
if(lValueSource.getArraySpec() != null)
if(rValueSource.getArraySpec() == null || !lValueSource.getArraySpec().equals(rValueSource.getArraySpec()))
throw new RuntimeException("ArraySpec mismatch!");
LValue lValueMemberVarRef = lValueSource.getBulkLValue(getScope());
RValue rValueBulkUnwinding = rValueSource.getBulkRValue(getScope());
if(lValueUnwoundList != null)
lValueUnwoundList.add(lValueMemberVarRef);
Statement copyStmt = new StatementAssignment(lValueMemberVarRef, rValueBulkUnwinding, initialAssignment, currentStmt.getSource(), Comment.NO_COMMENTS);
stmtIt.add(copyStmt);
stmtIt.next();
getLog().append("Adding value bulk copy " + copyStmt.toString(getProgram(), false));
return true;
} else if(lValueSource.isUnwindable() && rValueSource.isUnwindable()) {
getLog().append("Unwinding value copy " + currentStmt.toString(getProgram(), false));
for(String memberName : lValueSource.getMemberNames(getScope())) {
ValueSource lValueSubSource = lValueSource.getMemberUnwinding(memberName, getScope(), currentStmt, currentBlock, stmtIt);
ValueSource rValueSubSource = rValueSource.getMemberUnwinding(memberName, getScope(), currentStmt, currentBlock, stmtIt);
boolean success = copyValues(lValueSubSource, rValueSubSource, lValueUnwoundList, initialAssignment, currentStmt, currentBlock, stmtIt);
if(!success)
throw new InternalError("Error during value unwinding copy! ", currentStmt);
}
return true;
}
return false;
}
/**
* Get a value source for copying a value
* @param value The value being copied
* @param currentStmt The current statement
* @param stmtIt The statement iterator
* @param currentBlock The current block
* @return The vaule source for copying. null if no value source can be created.
*/
private ValueSource getValueSource(Value value, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
if(value instanceof VariableRef) {
Variable variable = getScope().getVariable((VariableRef) value);
if(variable.isStructClassic()) {
return new ValueSourceStructVariable(variable);
}
}
return null;
}
/**
* Unwind assignment from an RValue to an LValue
*

@ -0,0 +1,91 @@
package dk.camelot64.kickc.passes.unwinding;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.symbols.ArraySpec;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.RValue;
import java.util.List;
import java.util.ListIterator;
/**
* A value that is either the source or destination of a copy operation.
* Handles unwinding of struct copying when needed. Supports bulk copying.
*/
public interface ValueSource {
/**
* Determine if the value can be simple copied
* @return true if the value is a simple value (not an array or a struct value
*/
boolean isSimple();
/**
* Determine if the value can be bulk memory copied
* @return true if the value can be bulk memory copied (from or to).
*/
boolean isBulkCopyable();
/**
* Determine if the value can be unwound to sub-values
* @return true if the value is a struct value
*/
boolean isUnwindable();
/**
* Get the type of the value
* @return The type of the value
*/
SymbolType getSymbolType();
/**
* Get the array nature of the value
* @return The array nature of the value
*/
ArraySpec getArraySpec();
/**
* Get the simple value to use when performing a simple copy
*
* @param programScope The program scope
* @return The unwinding of the member
*/
RValue getSimpleValue(ProgramScope programScope);
/**
* Get Lvalue to use when for copying/setting a bulk value at once. Must returns a byte* type.
* @param scope The program scope
* @return The value to use as RValue
*/
LValue getBulkLValue(ProgramScope scope);
/**
* Get Rvalue to use when for copying/setting a bulk value at once. Typically returns a memset/memcpy command.
* @param scope The program scope
* @return The value to use as RValue
*/
RValue getBulkRValue(ProgramScope scope);
/**
* Get the names of the members of the struct (if the value is an unwindable struct)
*
* @return the names
*/
List<String> getMemberNames(ProgramScope scope);
/**
* Get a sub value source for one member to use for copying that member.
*
* @param memberName The member name
* @param programScope The program scope
* @param currentStmt
* @param currentBlock
* @param stmtIt
* @return The unwinding of the member
*/
ValueSource getMemberUnwinding(String memberName, ProgramScope programScope, Statement currentStmt, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt);
}

@ -0,0 +1,135 @@
package dk.camelot64.kickc.passes.unwinding;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.operators.OperatorSizeOf;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.PassNStructPointerRewriting;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
/** Value Source for a pointer dereference. */
public class ValueSourcePointerDereferenceSimple implements ValueSource {
/** The pointer dereference. */
private final PointerDereferenceSimple pointerDereference;
/** The type of the value. */
private SymbolType valueType;
/** The array spec of the value. */
private final ArraySpec valueArraySpec;
public ValueSourcePointerDereferenceSimple(PointerDereferenceSimple pointerDereference, SymbolType valueType, ArraySpec valueArraySpec) {
this.pointerDereference = pointerDereference;
this.valueType = valueType;
this.valueArraySpec = valueArraySpec;
}
@Override
public SymbolType getSymbolType() {
return valueType;
}
@Override
public ArraySpec getArraySpec() {
return valueArraySpec;
}
@Override
public boolean isSimple() {
return getArraySpec() == null && !(getSymbolType() instanceof SymbolTypeStruct);
}
@Override
public RValue getSimpleValue(ProgramScope programScope) {
if(getArraySpec() != null) {
// For arrays return the pointer to the array - not the deref
return pointerDereference.getPointer();
} else {
return pointerDereference;
}
}
@Override
public boolean isBulkCopyable() {
return getArraySpec() != null || getSymbolType() instanceof SymbolTypeStruct;
}
@Override
public LValue getBulkLValue(ProgramScope scope) {
RValue memberArrayPointer = pointerDereference.getPointer();
return new PointerDereferenceSimple(memberArrayPointer);
}
private ConstantValue getByteSize(ProgramScope scope) {
return getArraySpec() != null ? getArraySpec().getArraySize() : OperatorSizeOf.getSizeOfConstantVar(scope, getSymbolType());
}
@Override
public RValue getBulkRValue(ProgramScope scope) {
RValue memberArrayPointer = pointerDereference.getPointer();
return new MemcpyValue(new PointerDereferenceSimple(memberArrayPointer), getByteSize(scope), getSymbolType());
}
@Override
public boolean isUnwindable() {
return getSymbolType() instanceof SymbolTypeStruct;
}
@Override
public List<String> getMemberNames(ProgramScope scope) {
if(getSymbolType() instanceof SymbolTypeStruct) {
StructDefinition structDefinition = ((SymbolTypeStruct) getSymbolType()).getStructDefinition(scope);
Collection<Variable> structMemberVars = structDefinition.getAllVars(false);
ArrayList<String> memberNames = new ArrayList<>();
for(Variable structMemberVar : structMemberVars) {
memberNames.add(structMemberVar.getLocalName());
}
return memberNames;
} else {
return null;
}
}
@Override
public ValueSource getMemberUnwinding(String memberName, ProgramScope programScope, Statement currentStmt, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt) {
if(getSymbolType() instanceof SymbolTypeStruct) {
StructDefinition structDefinition = ((SymbolTypeStruct) getSymbolType()).getStructDefinition(programScope);
final SymbolType memberType = structDefinition.getMember(memberName).getType();
final ArraySpec memberArraySpec = structDefinition.getMember(memberName).getArraySpec();
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
// Simple member value - unwind to value of member *((type*)&struct + OFFSET_MEMBER)
final RValue structPointer = pointerDereference.getPointer();
if(structPointer instanceof ConstantValue) {
// Pointer to member type
ConstantCastValue structTypedPointer = new ConstantCastValue(new SymbolTypePointer(memberType), (ConstantValue) structPointer);
// Calculate member address (type*)&struct + OFFSET_MEMBER
ConstantBinary memberPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
// Unwind to *((type*)&struct + OFFSET_MEMBER)
PointerDereferenceSimple memberDeref = new PointerDereferenceSimple(memberPointer);
return new ValueSourcePointerDereferenceSimple(memberDeref, memberType, memberArraySpec);
} else {
Scope scope = programScope.getScope(currentBlock.getScope());
Variable memberAddress = scope.addVariableIntermediate();
memberAddress.setType(new SymbolTypePointer(memberType));
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(memberType), structPointer);
// Add statement $1 = (memberType*)ptr_struct + OFFSET_MEMBER
stmtIt.add(new StatementAssignment((LValue) memberAddress.getRef(), structTypedPointer, Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
// Unwind to *((memberType*)ptr_struct+OFFSET_MEMBER)
PointerDereferenceSimple memberDeref = new PointerDereferenceSimple(memberAddress.getRef());
return new ValueSourcePointerDereferenceSimple(memberDeref, memberType, memberArraySpec);
}
} else {
return null;
}
}
}

@ -0,0 +1,115 @@
package dk.camelot64.kickc.passes.unwinding;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.operators.OperatorSizeOf;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.symbols.ArraySpec;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.StructDefinition;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.PassNStructPointerRewriting;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
/** Value Source for a variable */
public class ValueSourceStructVariable implements ValueSource {
/** The variable. */
private final Variable variable;
public ValueSourceStructVariable(Variable variable) {
this.variable = variable;
}
@Override
public SymbolType getSymbolType() {
return variable.getType();
}
@Override
public ArraySpec getArraySpec() {
return variable.getArraySpec();
}
@Override
public boolean isSimple() {
return getArraySpec() == null && !(getSymbolType() instanceof SymbolTypeStruct);
}
@Override
public RValue getSimpleValue(ProgramScope programScope) {
return new ConstantSymbolPointer(variable.getRef());
}
@Override
public boolean isBulkCopyable() {
return getArraySpec() != null || variable.isStructClassic();
}
@Override
public LValue getBulkLValue(ProgramScope scope) {
ConstantSymbolPointer pointer = new ConstantSymbolPointer(variable.getRef());
return new PointerDereferenceSimple(pointer);
}
private ConstantValue getByteSize(ProgramScope scope) {
return getArraySpec() != null ? getArraySpec().getArraySize() : OperatorSizeOf.getSizeOfConstantVar(scope, getSymbolType());
}
@Override
public RValue getBulkRValue(ProgramScope scope) {
ConstantSymbolPointer pointer = new ConstantSymbolPointer(variable.getRef());
LValue pointerDeref = new PointerDereferenceSimple(pointer);
return new MemcpyValue(pointerDeref, getByteSize(scope), getSymbolType());
}
@Override
public boolean isUnwindable() {
return getSymbolType() instanceof SymbolTypeStruct;
}
@Override
public List<String> getMemberNames(ProgramScope scope) {
if(getSymbolType() instanceof SymbolTypeStruct) {
StructDefinition structDefinition = ((SymbolTypeStruct) getSymbolType()).getStructDefinition(scope);
Collection<Variable> structMemberVars = structDefinition.getAllVars(false);
ArrayList<String> memberNames = new ArrayList<>();
for(Variable structMemberVar : structMemberVars) {
memberNames.add(structMemberVar.getLocalName());
}
return memberNames;
} else {
return null;
}
}
@Override
public ValueSource getMemberUnwinding(String memberName, ProgramScope programScope, Statement currentStmt, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt) {
if(getSymbolType() instanceof SymbolTypeStruct) {
StructDefinition structDefinition = ((SymbolTypeStruct) getSymbolType()).getStructDefinition(programScope);
final SymbolType memberType = structDefinition.getMember(memberName).getType();
final ArraySpec memberArraySpec = structDefinition.getMember(memberName).getArraySpec();
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
// Simple member value - unwind to value of member *((type*)&struct + OFFSET_MEMBER)
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(variable.getRef());
// Pointer to member type
ConstantCastValue structTypedPointer = new ConstantCastValue(new SymbolTypePointer(memberType), structPointer);
// Calculate member address (type*)&struct + OFFSET_MEMBER
ConstantBinary memberPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
// Unwind to *((type*)&struct + OFFSET_MEMBER)
PointerDereferenceSimple memberDeref = new PointerDereferenceSimple(memberPointer);
return new ValueSourcePointerDereferenceSimple(memberDeref, memberType, memberArraySpec);
} else {
return null;
}
}
}

@ -1,5 +1,5 @@
Adding struct value member variable copy *(&(struct Point) main::point1) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT)
Adding struct value member variable copy *(&(struct Point) main::point2) ← memcpy(*(&(struct Point) main::point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Adding value bulk copy *(&(struct Point) main::point2) ← memcpy(*(&(struct Point) main::point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Replacing struct member reference (struct Point) main::point1.x with member unwinding reference *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) main::point1.y with member unwinding reference *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) main::point2.x with member unwinding reference *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
@ -15,6 +15,7 @@ main: scope:[main] from @1
*((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
*((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
*(&(struct Point) main::point2) ← memcpy(*(&(struct Point) main::point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
(struct Point) main::point2 ← struct-unwound {*(&(struct Point) main::point2)}
*((const byte*) SCREEN + (number) 0) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
*((const byte*) SCREEN + (number) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
@ -63,9 +64,10 @@ 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::point2 ← struct-unwound {*(&(struct Point) main::point2)}
Simplifying expression containing zero (byte*)&main::point1 in [1] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)&main::point2 in [4] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [4] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2)
Simplifying expression containing zero (byte*)&main::point2 in [5] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [5] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars

@ -1,4 +1,4 @@
Adding struct value member variable copy *(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Adding value bulk copy *(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Replacing struct member reference (struct Point) point1.x with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point1.y with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) point2.x with member unwinding reference *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
@ -16,6 +16,7 @@ main: scope:[main] from @1
*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
*(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
(struct Point) point2 ← struct-unwound {*(&(struct Point) point2)}
*((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 4
*((const byte*) main::SCREEN + (number) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
*((const byte*) main::SCREEN + (number) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
@ -77,11 +78,12 @@ 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 [3] (struct Point) point2 ← struct-unwound {*(&(struct Point) point2)}
Simplifying expression containing zero (byte*)&point1 in [0] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)&point2 in [3] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
Simplifying expression containing zero (byte*)&point1 in [4] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero main::SCREEN in [4] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1)
Simplifying expression containing zero (byte*)&point2 in [6] *((const byte*) main::SCREEN + (byte) 2) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero (byte*)&point2 in [4] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
Simplifying expression containing zero (byte*)&point1 in [5] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero main::SCREEN in [5] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1)
Simplifying expression containing zero (byte*)&point2 in [7] *((const byte*) main::SCREEN + (byte) 2) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars

@ -3,7 +3,7 @@ Fixing struct type size struct Point to 3
Fixing struct type SIZE_OF struct Point to 3
Fixing struct type SIZE_OF struct Point to 3
Adding struct value member variable copy *(&(struct Point) main::point1) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT)
Adding struct value member variable copy *(&(struct Point) main::point2) ← memcpy(*(&(struct Point) main::point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Adding value bulk copy *(&(struct Point) main::point2) ← memcpy(*(&(struct Point) main::point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Replacing struct member reference (struct Point) main::point1.x with member unwinding reference *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) main::point1.initials with member unwinding reference (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_INITIALS
Replacing struct member reference (struct Point) main::point1.initials with member unwinding reference (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_INITIALS
@ -22,6 +22,7 @@ main: scope:[main] from @1
*((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (number) 0) ← (byte) 'j'
*((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (number) 1) ← (byte) 'g'
*(&(struct Point) main::point2) ← memcpy(*(&(struct Point) main::point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
(struct Point) main::point2 ← struct-unwound {*(&(struct Point) main::point2)}
*((const byte*) SCREEN + (number) 0) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
*((const byte*) SCREEN + (number) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_INITIALS + (number) 0)
*((const byte*) SCREEN + (number) 2) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_INITIALS + (number) 1)
@ -82,11 +83,12 @@ Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 2
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [5] (struct Point) main::point2 ← struct-unwound {*(&(struct Point) main::point2)}
Simplifying expression containing zero (byte*)&main::point1 in [1] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)&main::point1+OFFSET_STRUCT_POINT_INITIALS in [2] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (byte) 0) ← (byte) 'j'
Simplifying expression containing zero (byte*)&main::point2 in [5] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [5] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2)
Simplifying expression containing zero (byte*)&main::point2+OFFSET_STRUCT_POINT_INITIALS in [6] *((const byte*) SCREEN + (byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_INITIALS + (byte) 0)
Simplifying expression containing zero (byte*)&main::point2 in [6] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [6] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2)
Simplifying expression containing zero (byte*)&main::point2+OFFSET_STRUCT_POINT_INITIALS in [7] *((const byte*) SCREEN + (byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_INITIALS + (byte) 0)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars

@ -1,5 +1,5 @@
Adding struct value member variable copy *(&(struct Point) main::point1) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT)
Adding struct value member variable copy *(&(struct Point) main::point2) ← memcpy(*(&(struct Point) main::point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Adding value bulk copy *(&(struct Point) main::point2) ← memcpy(*(&(struct Point) main::point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Replacing struct member reference (struct Point) main::point1.x with member unwinding reference *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) main::point1.y with member unwinding reference *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) main::point2.x with member unwinding reference *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
@ -15,6 +15,7 @@ main: scope:[main] from @1
*((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
*((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
*(&(struct Point) main::point2) ← memcpy(*(&(struct Point) main::point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
(struct Point) main::point2 ← struct-unwound {*(&(struct Point) main::point2)}
*((const byte*) SCREEN + (number) 0) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
*((const byte*) SCREEN + (number) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
@ -63,9 +64,10 @@ 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::point2 ← struct-unwound {*(&(struct Point) main::point2)}
Simplifying expression containing zero (byte*)&main::point1 in [1] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)&main::point2 in [4] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [4] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2)
Simplifying expression containing zero (byte*)&main::point2 in [5] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [5] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) main::point2)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars

@ -22,7 +22,7 @@ Adding struct value member variable copy *((struct Point*)&(struct Vector) main:
Adding struct value member variable copy *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (struct Point) main::v1_q
Adding struct value member variable copy *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) ← (struct Vector) main::v2.p
Adding struct value member variable copy *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← { x: (byte) 6, y: (byte) 7 }
Adding struct value member variable copy *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR)
Adding value bulk copy *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR)
Adding struct value member variable copy (struct Point) main::v5_p ← (struct Point){ (struct Vector) main::v4.p.x, (struct Vector) main::v4.p.y }
Adding struct value member variable copy (struct Point) main::v5_q ← { x: (byte) 8, y: (byte) 9 }
Replacing struct member reference (struct Vector) main::v2.p with member unwinding reference *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P)
@ -111,6 +111,7 @@ main: scope:[main] from @1
*((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT)
(struct Vector) main::v3 ← struct-unwound {*((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P), *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q)}
*(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR)
(struct Vector) main::v4 ← struct-unwound {*(&(struct Vector) main::v4)}
(byte*~) main::$4 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
(byte) main::v5_p_x#0 ← *((byte*~) main::$4)
(byte*~) main::$5 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
@ -255,24 +256,25 @@ Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification
Removing C-classic struct-unwound assignment [9] (struct Vector) main::v2 ← struct-unwound {*((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P), *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q)}
Removing C-classic struct-unwound assignment [12] (struct Vector) main::v3 ← struct-unwound {*((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P), *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q)}
Removing C-classic struct-unwound assignment [14] (struct Vector) main::v4 ← struct-unwound {*(&(struct Vector) main::v4)}
Constant right-side identified [1] (byte*~) main::$0 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [3] (byte*~) main::$1 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [5] (byte*~) main::$2 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [7] (byte*~) main::$3 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [14] (byte*~) main::$4 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [16] (byte*~) main::$5 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [26] (byte*~) main::$6 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [29] (byte*~) main::$7 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [32] (byte*~) main::$8 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [35] (byte*~) main::$9 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [38] (byte*~) main::$10 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [41] (byte*~) main::$11 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [44] (byte*~) main::$12 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [47] (byte*~) main::$13 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [50] (byte*~) main::$14 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [53] (byte*~) main::$15 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [56] (byte*~) main::$16 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [59] (byte*~) main::$17 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [15] (byte*~) main::$4 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [17] (byte*~) main::$5 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [27] (byte*~) main::$6 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [30] (byte*~) main::$7 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [33] (byte*~) main::$8 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [36] (byte*~) main::$9 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [39] (byte*~) main::$10 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [42] (byte*~) main::$11 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [45] (byte*~) main::$12 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [48] (byte*~) main::$13 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [51] (byte*~) main::$14 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [54] (byte*~) main::$15 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [57] (byte*~) main::$16 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [60] (byte*~) main::$17 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::idx#0 = 0
Constant (const byte*) main::$0 = (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_X
@ -315,7 +317,7 @@ Simplifying expression containing zero (struct Point*)&main::v4 in
Simplifying expression containing zero (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_Q in
Simplifying expression containing zero (struct Point*)&main::v2 in [10] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) ← memcpy(*((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Simplifying expression containing zero (struct Point*)&main::v3 in [10] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) ← memcpy(*((struct Point*)&(struct Vector) main::v2), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Simplifying expression containing zero SCREEN in [18] *((const byte*) SCREEN + (const byte) main::idx#0) ← (const byte) main::v1_p_x
Simplifying expression containing zero SCREEN in [19] *((const byte*) SCREEN + (const byte) main::idx#0) ← (const byte) main::v1_p_x
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte) main::idx#20 and assignment [48] (byte) main::idx#20 ← ++ (byte) main::idx#19
Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P