mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-08 14:37:40 +00:00
Working on improvements regarding global initializers and unnecessary unwinding of constant structs. Introduced RValueUnwinding for handling a single value.
This commit is contained in:
parent
db595d0b53
commit
6a9f59cda1
src
main/java/dk/camelot64/kickc
model
passes
test
@ -66,23 +66,29 @@ public class StructUnwinding {
|
||||
return new ArrayList<>(memberUnwinding.keySet());
|
||||
}
|
||||
|
||||
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
return this.memberUnwinding.get(memberName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
return new RValueUnwinding() {
|
||||
@Override
|
||||
public SymbolType getType() {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySpec getArraySpec(String memberName) {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
@Override
|
||||
public ArraySpec getArraySpec() {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberArrayUnwinding(String memberName, ProgramScope scope, ConstantValue arraySize) {
|
||||
throw new RuntimeException("TODO: Implement!");
|
||||
@Override
|
||||
public RValue getUnwinding(ProgramScope programScope) {
|
||||
return memberUnwinding.get(memberName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getArrayUnwinding(ProgramScope scope, ConstantValue arraySize) {
|
||||
throw new RuntimeException("TODO: Implement!");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -98,36 +104,48 @@ public class StructUnwinding {
|
||||
List<String> getMemberNames();
|
||||
|
||||
/**
|
||||
* Get the RValue that a specific member was unwound to
|
||||
* Get the RValue unwinding to use for copying a single member of the struct
|
||||
*
|
||||
* @param memberName The member name
|
||||
* @return The unwinding of the member
|
||||
*/
|
||||
RValueUnwinding getMemberUnwinding(String memberName);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwinding value used for copying a value from one variable to another.
|
||||
*/
|
||||
public interface RValueUnwinding {
|
||||
|
||||
/**
|
||||
* Get the type of the value
|
||||
* @return The type of the value
|
||||
*/
|
||||
SymbolType getType();
|
||||
|
||||
/**
|
||||
* Get the array nature of the value
|
||||
* @return The array nature of the value
|
||||
*/
|
||||
ArraySpec getArraySpec();
|
||||
|
||||
/**
|
||||
* Get the RValue to use in the assignment as LValue - and as RValue if the member is a not an array value
|
||||
*
|
||||
* @param programScope The program scope
|
||||
* @return The unwinding of the member
|
||||
*/
|
||||
RValue getMemberUnwinding(String memberName, ProgramScope programScope);
|
||||
RValue getUnwinding(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);
|
||||
|
||||
/**
|
||||
* Get the array nature of a specific member
|
||||
* @param memberName The member name
|
||||
* @return The array nature of the member
|
||||
*/
|
||||
ArraySpec getArraySpec(String memberName);
|
||||
|
||||
/**
|
||||
* Get unwinding value to use as RValue when for copying/setting an array member value
|
||||
* @param memberName The name of the member
|
||||
* Get Rvalue to use when for copying/setting an array value. Typically returns memset/memcpy commands.
|
||||
* @param scope The program scope
|
||||
* @param arraySize The declared size of the array
|
||||
* @return The value to use as RValue
|
||||
*/
|
||||
RValue getMemberArrayUnwinding(String memberName, ProgramScope scope, ConstantValue arraySize);
|
||||
RValue getArrayUnwinding(ProgramScope scope, ConstantValue arraySize);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
package dk.camelot64.kickc.model.values;
|
||||
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||
|
||||
/**
|
||||
* An zero-filled struct.
|
||||
*/
|
||||
public class StructZero implements RValue {
|
||||
public class StructZero implements ConstantValue {
|
||||
|
||||
private SymbolTypeStruct typeStruct;
|
||||
|
||||
@ -18,6 +21,16 @@ public class StructZero implements RValue {
|
||||
return typeStruct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getType(ProgramScope scope) {
|
||||
return typeStruct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantLiteral calculateLiteral(ProgramScope scope) {
|
||||
throw new ConstantNotLiteral("Cannot calculate literal struct.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Program program) {
|
||||
return "{}";
|
||||
|
@ -80,7 +80,8 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
||||
if(returnVarUnwinding!=null) {
|
||||
ArrayList<RValue> unwoundReturnVars = new ArrayList<>();
|
||||
for(String memberName : returnVarUnwinding.getMemberNames()) {
|
||||
unwoundReturnVars.add(returnVarUnwinding.getMemberUnwinding(memberName, getScope()));
|
||||
StructUnwinding.RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName);
|
||||
unwoundReturnVars.add(memberUnwinding.getUnwinding(getScope()));
|
||||
}
|
||||
procReturnVarRef = new ValueList(unwoundReturnVars);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.operators.OperatorSizeOf;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
@ -73,7 +74,9 @@ 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(), getScope());
|
||||
//RValue structMemberVariable = memberVariables.getMemberUnwinding(structMemberRef.getMemberName(), getScope());
|
||||
StructUnwinding.RValueUnwinding memberUnwinding = memberVariables.getMemberUnwinding(structMemberRef.getMemberName());
|
||||
RValue structMemberVariable = memberUnwinding.getUnwinding(getScope());
|
||||
getLog().append("Replacing struct member reference " + structMemberRef.toString(getProgram()) + " with member unwinding reference " + structMemberVariable.toString(getProgram()));
|
||||
programValue.set(structMemberVariable);
|
||||
modified.set(true);
|
||||
@ -96,7 +99,8 @@ 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, getScope()));
|
||||
StructUnwinding.RValueUnwinding memberUnwinding = lValueUnwinding.getMemberUnwinding(memberName);
|
||||
unwoundMembers.add(memberUnwinding.getUnwinding(getScope()));
|
||||
}
|
||||
ValueList unwoundLValue = new ValueList(unwoundMembers);
|
||||
call.setlValue(unwoundLValue);
|
||||
@ -113,7 +117,8 @@ 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, getScope()));
|
||||
StructUnwinding.RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName);
|
||||
unwoundParameters.add(memberUnwinding.getUnwinding(getScope()));
|
||||
}
|
||||
unwound = true;
|
||||
anyParameterUnwound = true;
|
||||
@ -143,7 +148,8 @@ 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, getScope()));
|
||||
StructUnwinding.RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName);
|
||||
unwoundMembers.add(memberUnwinding.getUnwinding(getScope()));
|
||||
}
|
||||
ValueList unwoundReturnValue = new ValueList(unwoundMembers);
|
||||
statementReturn.setValue(unwoundReturnValue);
|
||||
@ -168,8 +174,9 @@ 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, getScope());
|
||||
unwoundParameterNames.add(memberUnwinding.getLocalName());
|
||||
StructUnwinding.RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName);
|
||||
SymbolVariableRef memberUnwindingRef = (SymbolVariableRef) memberUnwinding.getUnwinding(getScope());
|
||||
unwoundParameterNames.add(memberUnwindingRef.getLocalName());
|
||||
procedureUnwound = true;
|
||||
}
|
||||
} else {
|
||||
@ -194,22 +201,54 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
*/
|
||||
private boolean unwindAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
LValue lValue = assignment.getlValue();
|
||||
StructUnwinding.StructMemberUnwinding lValueUnwinding = getStructMemberUnwinding(lValue, assignment, stmtIt, currentBlock);
|
||||
|
||||
if(lValueUnwinding == null) {
|
||||
return false;
|
||||
} else if(lValueUnwinding == POSTPONE_UNWINDING) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(assignment.getOperator() == null) {
|
||||
SymbolTypeStruct lValueStructType = (SymbolTypeStruct) SymbolTypeInference.inferType(getScope(), lValue);
|
||||
SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
|
||||
if(assignment.getOperator() == null && lValueType instanceof SymbolTypeStruct) {
|
||||
SymbolTypeStruct lValueStructType = (SymbolTypeStruct) lValueType;
|
||||
RValue rValue = assignment.getrValue2();
|
||||
boolean initialAssignment = assignment.isInitialAssignment();
|
||||
StatementSource source = assignment.getSource();
|
||||
|
||||
// Check for constant struct value assignment
|
||||
if(rValue instanceof ConstantValue && 1 == 0) {
|
||||
// TODO: Only handle __ma structs here!
|
||||
if(rValue instanceof StructZero) {
|
||||
// Zero-fill the struct value
|
||||
stmtIt.previous();
|
||||
ConstantValue structSize = OperatorSizeOf.getSizeOfConstantVar(getScope(), lValueStructType);
|
||||
MemsetValue rValueMemset = new MemsetValue(structSize);
|
||||
Statement copyStmt = new StatementAssignment(lValue, rValueMemset, initialAssignment, source, Comment.NO_COMMENTS);
|
||||
stmtIt.add(copyStmt);
|
||||
getLog().append("Adding struct variable zero-fill " + copyStmt.toString(getProgram(), false));
|
||||
stmtIt.next();
|
||||
} else if(rValue instanceof ConstantStructValue) {
|
||||
// Create global constant - and memcpy the value into the variable
|
||||
// Create a constant variable holding the array
|
||||
String constName = getScope().allocateIntermediateVariableName();
|
||||
Variable constVar = Variable.createConstant(constName, lValueType, getScope(), null, (ConstantValue) rValue, Scope.SEGMENT_DATA_DEFAULT);
|
||||
getScope().add(constVar);
|
||||
stmtIt.previous();
|
||||
ConstantValue structSize = OperatorSizeOf.getSizeOfConstantVar(getScope(), lValueStructType);
|
||||
MemcpyValue rValueMemcpy = new MemcpyValue(new PointerDereferenceSimple(constVar.getRef()), structSize);
|
||||
Statement copyStmt = new StatementAssignment(lValue, rValueMemcpy, initialAssignment, source, Comment.NO_COMMENTS);
|
||||
stmtIt.add(copyStmt);
|
||||
getLog().append("Adding struct variable copy " + copyStmt.toString(getProgram(), false));
|
||||
stmtIt.next();
|
||||
} else {
|
||||
throw new InternalError("Unknown constant struct value " + rValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for struct unwinding
|
||||
StructUnwinding.StructMemberUnwinding lValueUnwinding = getStructMemberUnwinding(lValue, assignment, stmtIt, currentBlock);
|
||||
if(lValueUnwinding == null)
|
||||
return false;
|
||||
if(lValueUnwinding == POSTPONE_UNWINDING)
|
||||
return true;
|
||||
|
||||
if(rValue instanceof StructUnwoundPlaceholder)
|
||||
return false;
|
||||
SymbolType rValueType = SymbolTypeInference.inferType(getScope(), rValue);
|
||||
boolean initialAssignment = assignment.isInitialAssignment();
|
||||
StatementSource source = assignment.getSource();
|
||||
if(rValueType.equals(lValueStructType)) {
|
||||
StructUnwinding.StructMemberUnwinding rValueUnwinding = getStructMemberUnwinding(rValue, assignment, stmtIt, currentBlock);
|
||||
if(rValueUnwinding == null) {
|
||||
@ -217,7 +256,13 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
if(rValueUnwinding == POSTPONE_UNWINDING)
|
||||
return true;
|
||||
StructUnwoundPlaceholder unwoundPlaceholder = unwindAssignment(lValueStructType, lValueUnwinding, rValueUnwinding, stmtIt, initialAssignment, source);
|
||||
List<RValue> lValueUnwoundPlaceholder = new ArrayList<>();
|
||||
for(String memberName : lValueUnwinding.getMemberNames()) {
|
||||
StructUnwinding.RValueUnwinding lValueMemberUnwinding = lValueUnwinding.getMemberUnwinding(memberName);
|
||||
StructUnwinding.RValueUnwinding rValueMemberUnwinding = rValueUnwinding.getMemberUnwinding(memberName);
|
||||
unwindAssignment(lValueMemberUnwinding, rValueMemberUnwinding, lValueUnwoundPlaceholder, stmtIt, initialAssignment, source);
|
||||
}
|
||||
StructUnwoundPlaceholder unwoundPlaceholder = new StructUnwoundPlaceholder(lValueStructType, lValueUnwoundPlaceholder);
|
||||
if(lValue instanceof VariableRef) {
|
||||
assignment.setrValue2(unwoundPlaceholder);
|
||||
} else {
|
||||
@ -225,47 +270,47 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
throw new CompileError("Incompatible struct assignment " + assignment.toString(getProgram(), false), assignment);
|
||||
}
|
||||
throw new CompileError("Incompatible struct assignment " + assignment.toString(getProgram(), false), assignment);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwind assignment of members from an RValue to an LValue
|
||||
* Unwind assignment from an RValue to an LValue
|
||||
*
|
||||
* @param structType The type of struct being unwound
|
||||
* @param lValueUnwinding The member unwinding of the LValue
|
||||
* @param rValueUnwinding The member unwinding of the RValue
|
||||
* @param lValueUnwinding The unwinding of the LValue
|
||||
* @param rValueUnwinding The unwinding of the RValue
|
||||
* @param lValueUnwoundList will receive the actual unwinding used for the lValue (if non-null)
|
||||
* @param stmtIt Statement iterator used for adding unwound assignment statements (before the current statement)
|
||||
* @param initialAssignment Is this the initial assignment
|
||||
* @param source The statement source
|
||||
* @return Struct unwound placeholder describing the performed unwinding
|
||||
*/
|
||||
private StructUnwoundPlaceholder unwindAssignment(SymbolTypeStruct structType, StructUnwinding.StructMemberUnwinding lValueUnwinding, StructUnwinding.StructMemberUnwinding rValueUnwinding, ListIterator<Statement> stmtIt, boolean initialAssignment, StatementSource source) {
|
||||
List<RValue> lValueUnwoundPlaceholder = new ArrayList<>();
|
||||
stmtIt.previous();
|
||||
for(String memberName : lValueUnwinding.getMemberNames()) {
|
||||
if(lValueUnwinding.getArraySpec(memberName) != null) {
|
||||
// Unwinding an array struct member
|
||||
RValue lValueMemberVarPointer = lValueUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
LValue lValueMemberVarRef = new PointerDereferenceSimple(lValueMemberVarPointer);
|
||||
ConstantValue arraySize = lValueUnwinding.getArraySpec(memberName).getArraySize();
|
||||
RValue rValueArrayUnwinding = rValueUnwinding.getMemberArrayUnwinding(memberName, getScope(), arraySize);
|
||||
lValueUnwoundPlaceholder.add(lValueMemberVarPointer);
|
||||
Statement copyStmt = new StatementAssignment(lValueMemberVarRef, rValueArrayUnwinding, initialAssignment, source, Comment.NO_COMMENTS);
|
||||
stmtIt.add(copyStmt);
|
||||
getLog().append("Adding struct value member variable copy " + copyStmt.toString(getProgram(), false));
|
||||
} else {
|
||||
// Unwinding a non-array struct member
|
||||
LValue lValueMemberVarRef = (LValue) lValueUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
RValue rValueMemberVarRef = rValueUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
lValueUnwoundPlaceholder.add(lValueMemberVarRef);
|
||||
Statement copyStmt = new StatementAssignment(lValueMemberVarRef, rValueMemberVarRef, initialAssignment, source, Comment.NO_COMMENTS);
|
||||
stmtIt.add(copyStmt);
|
||||
getLog().append("Adding struct value member variable copy " + copyStmt.toString(getProgram(), false));
|
||||
}
|
||||
private void unwindAssignment(StructUnwinding.RValueUnwinding lValueUnwinding, StructUnwinding.RValueUnwinding rValueUnwinding, List<RValue> lValueUnwoundList, ListIterator<Statement> stmtIt, boolean initialAssignment, StatementSource source) {
|
||||
if(lValueUnwinding.getArraySpec() != null) {
|
||||
// Unwinding an array struct member
|
||||
stmtIt.previous();
|
||||
RValue lValueMemberVarPointer = lValueUnwinding.getUnwinding(getScope());
|
||||
LValue lValueMemberVarRef = new PointerDereferenceSimple(lValueMemberVarPointer);
|
||||
ConstantValue arraySize = lValueUnwinding.getArraySpec().getArraySize();
|
||||
RValue rValueArrayUnwinding = rValueUnwinding.getArrayUnwinding(getScope(), arraySize);
|
||||
if(lValueUnwoundList != null)
|
||||
lValueUnwoundList.add(lValueMemberVarPointer);
|
||||
Statement copyStmt = new StatementAssignment(lValueMemberVarRef, rValueArrayUnwinding, initialAssignment, source, Comment.NO_COMMENTS);
|
||||
stmtIt.add(copyStmt);
|
||||
stmtIt.next();
|
||||
getLog().append("Adding struct value member variable copy " + copyStmt.toString(getProgram(), false));
|
||||
} else {
|
||||
// Unwinding a non-array struct member
|
||||
stmtIt.previous();
|
||||
LValue lValueMemberVarRef = (LValue) lValueUnwinding.getUnwinding(getScope());
|
||||
RValue rValueMemberVarRef = rValueUnwinding.getUnwinding(getScope());
|
||||
if(lValueUnwoundList != null)
|
||||
lValueUnwoundList.add(lValueMemberVarRef);
|
||||
Statement copyStmt = new StatementAssignment(lValueMemberVarRef, rValueMemberVarRef, initialAssignment, source, Comment.NO_COMMENTS);
|
||||
stmtIt.add(copyStmt);
|
||||
stmtIt.next();
|
||||
getLog().append("Adding struct value member variable copy " + copyStmt.toString(getProgram(), false));
|
||||
}
|
||||
stmtIt.next();
|
||||
return new StructUnwoundPlaceholder(structType, lValueUnwoundPlaceholder);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,34 +367,21 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
|
||||
/** Singleton signaling that unwinding should be postponed. */
|
||||
private static final StructUnwinding.StructMemberUnwinding POSTPONE_UNWINDING = new StructUnwinding.StructMemberUnwinding() {
|
||||
|
||||
@Override
|
||||
public List<String> getMemberNames() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySpec getArraySpec(String memberName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberArrayUnwinding(String memberName, ProgramScope scope, ConstantValue arraySize) {
|
||||
public StructUnwinding.RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/** Unwinding for a simple pointer deref to a struct. */
|
||||
private static class StructMemberUnwindingPointerDerefSimple implements StructUnwinding.StructMemberUnwinding {
|
||||
|
||||
private final StructDefinition structDefinition;
|
||||
private final ControlFlowBlock currentBlock;
|
||||
private final ListIterator<Statement> stmtIt;
|
||||
@ -375,32 +407,37 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
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());
|
||||
// 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());
|
||||
}
|
||||
public StructUnwinding.RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
return new StructUnwinding.RValueUnwinding() {
|
||||
@Override
|
||||
public SymbolType getType() {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
@Override
|
||||
public ArraySpec getArraySpec() {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySpec getArraySpec(String memberName) {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
@Override
|
||||
public RValue getUnwinding(ProgramScope programScope) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
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());
|
||||
// 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 RValue getMemberArrayUnwinding(String memberName, ProgramScope scope, ConstantValue arraySize) {
|
||||
throw new RuntimeException("TODO: Implement!");
|
||||
@Override
|
||||
public RValue getArrayUnwinding(ProgramScope scope, ConstantValue arraySize) {
|
||||
throw new RuntimeException("TODO: Implement!");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -432,32 +469,37 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
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());
|
||||
// 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[idx]
|
||||
return new PointerDereferenceIndexed(memberAddress.getRef(), pointerDeref.getIndex());
|
||||
}
|
||||
public StructUnwinding.RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
return new StructUnwinding.RValueUnwinding() {
|
||||
@Override
|
||||
public SymbolType getType() {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
@Override
|
||||
public ArraySpec getArraySpec() {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySpec getArraySpec(String memberName) {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
@Override
|
||||
public RValue getUnwinding(ProgramScope programScope) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
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());
|
||||
// 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[idx]
|
||||
return new PointerDereferenceIndexed(memberAddress.getRef(), pointerDeref.getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberArrayUnwinding(String memberName, ProgramScope scope, ConstantValue arraySize) {
|
||||
throw new RuntimeException("TODO: Implement!");
|
||||
@Override
|
||||
public RValue getArrayUnwinding(ProgramScope scope, ConstantValue arraySize) {
|
||||
throw new RuntimeException("TODO: Implement!");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -483,31 +525,36 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
return constantStructValue.getValue(member.getRef());
|
||||
}
|
||||
public StructUnwinding.RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
return new StructUnwinding.RValueUnwinding() {
|
||||
@Override
|
||||
public SymbolType getType() {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
@Override
|
||||
public ArraySpec getArraySpec() {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySpec getArraySpec(String memberName) {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
@Override
|
||||
public RValue getUnwinding(ProgramScope programScope) {
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
return constantStructValue.getValue(member.getRef());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberArrayUnwinding(String memberName, ProgramScope scope, ConstantValue arraySize) {
|
||||
// Create a constant variable holding the array
|
||||
String constName = scope.allocateIntermediateVariableName();
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
SymbolType memberType = member.getType();
|
||||
ConstantValue constValue = constantStructValue.getValue(member.getRef());
|
||||
Variable constVar = Variable.createConstant(constName, memberType, scope, new ArraySpec(arraySize), constValue, Scope.SEGMENT_DATA_DEFAULT);
|
||||
scope.add(constVar);
|
||||
return new MemcpyValue(new PointerDereferenceSimple(constVar.getRef()), arraySize);
|
||||
@Override
|
||||
public RValue getArrayUnwinding(ProgramScope scope, ConstantValue arraySize) {
|
||||
// Create a constant variable holding the array
|
||||
String constName = scope.allocateIntermediateVariableName();
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
SymbolType memberType = member.getType();
|
||||
ConstantValue constValue = constantStructValue.getValue(member.getRef());
|
||||
Variable constVar = Variable.createConstant(constName, memberType, scope, new ArraySpec(arraySize), constValue, Scope.SEGMENT_DATA_DEFAULT);
|
||||
scope.add(constVar);
|
||||
return new MemcpyValue(new PointerDereferenceSimple(constVar.getRef()), arraySize);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -539,44 +586,50 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(variable.getRef());
|
||||
ConstantCastValue structTypedPointer;
|
||||
if(member.isArray()) {
|
||||
// Pointer to array element type
|
||||
SymbolTypePointer arrayType = (SymbolTypePointer) member.getType();
|
||||
structTypedPointer = new ConstantCastValue(new SymbolTypePointer(arrayType.getElementType()), structPointer);
|
||||
// Calculate member address (elementtype*)&struct + OFFSET_STRUCT_NAME_MEMBER
|
||||
ConstantBinary memberArrayPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
|
||||
// Unwind to *(&struct + OFFSET_STRUCT_NAME_MEMBER)
|
||||
return memberArrayPointer;
|
||||
} else {
|
||||
// Pointer to member element type
|
||||
structTypedPointer = new ConstantCastValue(new SymbolTypePointer(member.getType()), structPointer);
|
||||
// Calculate member address (elementtype*)&struct + OFFSET_STRUCT_NAME_MEMBER
|
||||
ConstantBinary memberArrayPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
|
||||
// Unwind to *(&struct + OFFSET_STRUCT_NAME_MEMBER)
|
||||
return new PointerDereferenceSimple(memberArrayPointer);
|
||||
}
|
||||
}
|
||||
public StructUnwinding.RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
return new StructUnwinding.RValueUnwinding() {
|
||||
@Override
|
||||
public SymbolType getType() {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
@Override
|
||||
public ArraySpec getArraySpec() {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySpec getArraySpec(String memberName) {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
@Override
|
||||
public RValue getUnwinding(ProgramScope programScope) {
|
||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||
Variable member = structDefinition.getMember(memberName);
|
||||
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(variable.getRef());
|
||||
ConstantCastValue structTypedPointer;
|
||||
if(member.isArray()) {
|
||||
// Pointer to array element type
|
||||
SymbolTypePointer arrayType = (SymbolTypePointer) member.getType();
|
||||
structTypedPointer = new ConstantCastValue(new SymbolTypePointer(arrayType.getElementType()), structPointer);
|
||||
// Calculate member address (elementtype*)&struct + OFFSET_STRUCT_NAME_MEMBER
|
||||
ConstantBinary memberArrayPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
|
||||
// Unwind to *(&struct + OFFSET_STRUCT_NAME_MEMBER)
|
||||
return memberArrayPointer;
|
||||
} else {
|
||||
// Pointer to member element type
|
||||
structTypedPointer = new ConstantCastValue(new SymbolTypePointer(member.getType()), structPointer);
|
||||
// Calculate member address (elementtype*)&struct + OFFSET_STRUCT_NAME_MEMBER
|
||||
ConstantBinary memberArrayPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
|
||||
// Unwind to *(&struct + OFFSET_STRUCT_NAME_MEMBER)
|
||||
return new PointerDereferenceSimple(memberArrayPointer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberArrayUnwinding(String memberName, ProgramScope scope, ConstantValue arraySize) {
|
||||
RValue rValueMemberVarPointer = getMemberUnwinding(memberName, scope);
|
||||
LValue rValueMemberVarRef = new PointerDereferenceSimple(rValueMemberVarPointer);
|
||||
return new MemcpyValue(rValueMemberVarRef, arraySize);
|
||||
@Override
|
||||
public RValue getArrayUnwinding(ProgramScope scope, ConstantValue arraySize) {
|
||||
RValue rValueMemberVarPointer = getUnwinding(scope);
|
||||
LValue rValueMemberVarRef = new PointerDereferenceSimple(rValueMemberVarPointer);
|
||||
return new MemcpyValue(rValueMemberVarRef, arraySize);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -602,23 +655,28 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
return ZeroConstantValues.zeroValue(getMemberType(memberName), programScope);
|
||||
}
|
||||
public StructUnwinding.RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
return new StructUnwinding.RValueUnwinding() {
|
||||
@Override
|
||||
public SymbolType getType() {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
@Override
|
||||
public ArraySpec getArraySpec() {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySpec getArraySpec(String memberName) {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
@Override
|
||||
public RValue getUnwinding(ProgramScope programScope) {
|
||||
return ZeroConstantValues.zeroValue(getType(), programScope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberArrayUnwinding(String memberName, ProgramScope scope, ConstantValue arraySize) {
|
||||
return new MemsetValue(arraySize);
|
||||
@Override
|
||||
public RValue getArrayUnwinding(ProgramScope scope, ConstantValue arraySize) {
|
||||
return new MemsetValue(arraySize);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -645,24 +703,30 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
int memberIndex = getMemberNames().indexOf(memberName);
|
||||
return valueList.getList().get(memberIndex);
|
||||
public StructUnwinding.RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
return new StructUnwinding.RValueUnwinding() {
|
||||
@Override
|
||||
public SymbolType getType() {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySpec getArraySpec() {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getUnwinding(ProgramScope programScope) {
|
||||
int memberIndex = getMemberNames().indexOf(memberName);
|
||||
return valueList.getList().get(memberIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getArrayUnwinding(ProgramScope scope, ConstantValue arraySize) {
|
||||
throw new RuntimeException("TODO: Implement!");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getMemberType(String memberName) {
|
||||
return structDefinition.getMember(memberName).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySpec getArraySpec(String memberName) {
|
||||
return structDefinition.getMember(memberName).getArraySpec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue getMemberArrayUnwinding(String memberName, ProgramScope scope, ConstantValue arraySize) {
|
||||
throw new RuntimeException("TODO: Implement!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1127,9 +1127,14 @@ public class TestPrograms {
|
||||
assertError("struct-err-0", "Unknown struct type");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct29() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-29", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct28() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-28");
|
||||
compileAndCompare("struct-28", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
|
16
src/test/kc/struct-29.kc
Normal file
16
src/test/kc/struct-29.kc
Normal file
@ -0,0 +1,16 @@
|
||||
// Minimal struct with C-Standard behavior - global main-mem struct should be initialized in data, not code
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
char[2] initials;
|
||||
};
|
||||
|
||||
__mem __ma struct Point point1 = { 2, { 'j', 'g' } };
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
SCREEN[0] = point1.x;
|
||||
SCREEN[1] = point1.initials[0];
|
||||
SCREEN[2] = point1.initials[1];
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
|
@ -168,7 +168,7 @@ Allocated zp[3]:5 [ main::point2 ]
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
@ -265,7 +265,7 @@ Uplifting [] best 101 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
@ -379,7 +379,7 @@ FINAL ASSEMBLER
|
||||
Score: 84
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
|
@ -129,7 +129,7 @@ Allocated zp[4]:2 [ main::point1 ]
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
@ -202,7 +202,7 @@ Uplifting [] best 65 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
@ -295,7 +295,7 @@ FINAL ASSEMBLER
|
||||
Score: 50
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
|
@ -129,7 +129,7 @@ Allocated zp[3]:2 [ main::point1 ]
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
@ -201,7 +201,7 @@ Uplifting [] best 65 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
@ -294,7 +294,7 @@ FINAL ASSEMBLER
|
||||
Score: 50
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment (not supported yet)
|
||||
// Minimal struct with C-Standard behavior - member is array, copy assignment
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
|
28
src/test/ref/struct-29.asm
Normal file
28
src/test/ref/struct-29.asm
Normal file
@ -0,0 +1,28 @@
|
||||
// Minimal struct with C-Standard behavior - global main-mem struct should be initialized in data, not code
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_INITIALS = 1
|
||||
__bbegin:
|
||||
lda #2
|
||||
sta point1
|
||||
tay
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta point1+OFFSET_STRUCT_POINT_INITIALS-1,y
|
||||
dey
|
||||
bne !-
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
lda point1
|
||||
sta SCREEN
|
||||
lda point1+OFFSET_STRUCT_POINT_INITIALS
|
||||
sta SCREEN+1
|
||||
lda point1+OFFSET_STRUCT_POINT_INITIALS+1
|
||||
sta SCREEN+2
|
||||
rts
|
||||
}
|
||||
__0: .byte 'j', 'g'
|
||||
point1: .byte 0
|
20
src/test/ref/struct-29.cfg
Normal file
20
src/test/ref/struct-29.cfg
Normal file
@ -0,0 +1,20 @@
|
||||
@begin: scope:[] from
|
||||
[0] *((byte*)&(struct Point) point1) ← (byte) 2
|
||||
[1] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) ← memcpy(*((const byte*) $0), (number) 2)
|
||||
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] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point1)
|
||||
[6] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS)
|
||||
[7] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS+(byte) 1)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
340
src/test/ref/struct-29.log
Normal file
340
src/test/ref/struct-29.log
Normal file
@ -0,0 +1,340 @@
|
||||
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 *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
|
||||
Adding struct value member variable copy *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) ← memcpy(*((const byte*) $0), (number) 2)
|
||||
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.initials with member unwinding reference (byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS
|
||||
Replacing struct member reference (struct Point) point1.initials with member unwinding reference (byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS
|
||||
Adding versioned struct unwinding for (struct Point) point1
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
|
||||
*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) ← memcpy(*((const byte*) $0), (number) 2)
|
||||
(struct Point) point1 ← struct-unwound {*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X), (byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS}
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
*((const byte*) SCREEN + (number) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
|
||||
*((const byte*) SCREEN + (number) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (number) 0)
|
||||
*((const byte*) SCREEN + (number) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (number) 1)
|
||||
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
|
||||
(const byte*) $0[(number) 2] = { (byte) 'j', (byte) 'g' }
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_INITIALS = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte*) Point::initials[(number) 2] = { fill( 2, 0) }
|
||||
(byte) Point::x
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) point1 loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
|
||||
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (number) 0)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (unumber)(number) 0)
|
||||
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (number) 1)
|
||||
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (unumber)(number) 1)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast 2
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
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 [2] (struct Point) point1 ← struct-unwound {*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X), (byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS}
|
||||
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*)&point1 in [3] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
|
||||
Simplifying expression containing zero SCREEN in [3] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1)
|
||||
Simplifying expression containing zero (byte*)&point1+OFFSET_STRUCT_POINT_INITIALS in [4] *((const byte*) SCREEN + (byte) 1) ← *((byte*)&(struct Point) point1+(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
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Consolidated array index constant in *((byte*)&point1+OFFSET_STRUCT_POINT_INITIALS+1)
|
||||
Consolidated array index constant in *(SCREEN+2)
|
||||
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) point1) ← (byte) 2
|
||||
[1] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) ← memcpy(*((const byte*) $0), (number) 2)
|
||||
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] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point1)
|
||||
[6] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS)
|
||||
[7] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS+(byte) 1)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(void()) main()
|
||||
(struct Point) point1 loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable point1 to live range equivalence class [ point1 ]
|
||||
Complete equivalence classes
|
||||
[ point1 ]
|
||||
Allocated mem[3] [ point1 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - global main-mem struct should be initialized in data, not code
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_INITIALS = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((byte*)&(struct Point) point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta point1
|
||||
// [1] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) ← memcpy(*((const byte*) $0), (number) 2) -- _deref_pbuc1=_deref_pbuc2_memcpy_vbuc3
|
||||
ldy #2
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta point1+OFFSET_STRUCT_POINT_INITIALS-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [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] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1
|
||||
sta SCREEN
|
||||
// [6] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_INITIALS
|
||||
sta SCREEN+1
|
||||
// [7] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS+(byte) 1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_INITIALS+1
|
||||
sta SCREEN+2
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .byte 'j', 'g'
|
||||
point1: .byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *((byte*)&(struct Point) point1) ← (byte) 2 [ point1 ] ( [ point1 ] ) always clobbers reg byte a
|
||||
Statement [1] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) ← memcpy(*((const byte*) $0), (number) 2) [ point1 ] ( [ point1 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [5] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point1) [ point1 ] ( main:3 [ point1 ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) [ point1 ] ( main:3 [ point1 ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS+(byte) 1) [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Potential registers mem[3] [ point1 ] : mem[3] ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main]
|
||||
Uplift Scope [] 0: mem[3] [ point1 ]
|
||||
|
||||
Uplifting [Point] best 67 combination
|
||||
Uplifting [main] best 67 combination
|
||||
Uplifting [] best 67 combination mem[3] [ point1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - global main-mem struct should be initialized in data, not code
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_INITIALS = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((byte*)&(struct Point) point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta point1
|
||||
// [1] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) ← memcpy(*((const byte*) $0), (number) 2) -- _deref_pbuc1=_deref_pbuc2_memcpy_vbuc3
|
||||
ldy #2
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta point1+OFFSET_STRUCT_POINT_INITIALS-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [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] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1
|
||||
sta SCREEN
|
||||
// [6] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_INITIALS
|
||||
sta SCREEN+1
|
||||
// [7] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS+(byte) 1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_INITIALS+1
|
||||
sta SCREEN+2
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .byte 'j', 'g'
|
||||
point1: .byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing instruction ldy #2 with TAY
|
||||
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
|
||||
(const byte*) $0[(number) 2] = { (byte) 'j', (byte) 'g' }
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_INITIALS = (byte) 1
|
||||
(const byte*) Point::initials[(number) 2] = { fill( 2, 0) }
|
||||
(byte) Point::x
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) point1 loadstore mem[3]
|
||||
|
||||
mem[3] [ point1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 64
|
||||
|
||||
// File Comments
|
||||
// Minimal struct with C-Standard behavior - global main-mem struct should be initialized in data, not code
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const OFFSET_STRUCT_POINT_INITIALS = 1
|
||||
// @begin
|
||||
__bbegin:
|
||||
// point1 = { 2, { 'j', 'g' } }
|
||||
// [0] *((byte*)&(struct Point) point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
|
||||
lda #2
|
||||
sta point1
|
||||
// [1] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) ← memcpy(*((const byte*) $0), (number) 2) -- _deref_pbuc1=_deref_pbuc2_memcpy_vbuc3
|
||||
tay
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta point1+OFFSET_STRUCT_POINT_INITIALS-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [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: {
|
||||
// SCREEN[0] = point1.x
|
||||
// [5] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1
|
||||
sta SCREEN
|
||||
// SCREEN[1] = point1.initials[0]
|
||||
// [6] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_INITIALS
|
||||
sta SCREEN+1
|
||||
// SCREEN[2] = point1.initials[1]
|
||||
// [7] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS+(byte) 1) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda point1+OFFSET_STRUCT_POINT_INITIALS+1
|
||||
sta SCREEN+2
|
||||
// main::@return
|
||||
// }
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .byte 'j', 'g'
|
||||
point1: .byte 0
|
||||
|
13
src/test/ref/struct-29.sym
Normal file
13
src/test/ref/struct-29.sym
Normal file
@ -0,0 +1,13 @@
|
||||
(const byte*) $0[(number) 2] = { (byte) 'j', (byte) 'g' }
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_INITIALS = (byte) 1
|
||||
(const byte*) Point::initials[(number) 2] = { fill( 2, 0) }
|
||||
(byte) Point::x
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(struct Point) point1 loadstore mem[3]
|
||||
|
||||
mem[3] [ point1 ]
|
Loading…
x
Reference in New Issue
Block a user