mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-27 09:31:18 +00:00
Refactored unwindings into separate classes for better reuse.
This commit is contained in:
parent
a32f783b74
commit
7ea2453733
@ -7,12 +7,10 @@ import dk.camelot64.kickc.model.statements.Statement;
|
|||||||
import dk.camelot64.kickc.model.statements.StatementInfos;
|
import dk.camelot64.kickc.model.statements.StatementInfos;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.values.LabelRef;
|
import dk.camelot64.kickc.model.values.LabelRef;
|
||||||
import dk.camelot64.kickc.model.values.SymbolVariableRef;
|
|
||||||
import dk.camelot64.kickc.passes.calcs.*;
|
import dk.camelot64.kickc.passes.calcs.*;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -63,7 +61,7 @@ public class Program {
|
|||||||
/** Variables modified inside procedures. PASS 1 (STATIC) */
|
/** Variables modified inside procedures. PASS 1 (STATIC) */
|
||||||
private ProcedureModifiedVars procedureModifiedVars;
|
private ProcedureModifiedVars procedureModifiedVars;
|
||||||
/** Struct values unwound to individual variables. PASS 1 (STATIC) */
|
/** Struct values unwound to individual variables. PASS 1 (STATIC) */
|
||||||
private StructUnwinding structUnwinding;
|
private StructVariableMemberUnwinding structVariableMemberUnwinding;
|
||||||
|
|
||||||
/** The main scope. PASS 0-5 (DYNAMIC) */
|
/** The main scope. PASS 0-5 (DYNAMIC) */
|
||||||
private ProgramScope scope;
|
private ProgramScope scope;
|
||||||
@ -119,7 +117,7 @@ public class Program {
|
|||||||
this.imported = null;
|
this.imported = null;
|
||||||
this.statementSequence = null;
|
this.statementSequence = null;
|
||||||
this.procedureModifiedVars = null;
|
this.procedureModifiedVars = null;
|
||||||
this.structUnwinding = null;
|
this.structVariableMemberUnwinding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -219,12 +217,12 @@ public class Program {
|
|||||||
this.targetPlatform = targetPlatform;
|
this.targetPlatform = targetPlatform;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StructUnwinding getStructUnwinding() {
|
public StructVariableMemberUnwinding getStructVariableMemberUnwinding() {
|
||||||
return structUnwinding;
|
return structVariableMemberUnwinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStructUnwinding(StructUnwinding structUnwinding) {
|
public void setStructVariableMemberUnwinding(StructVariableMemberUnwinding structVariableMemberUnwinding) {
|
||||||
this.structUnwinding = structUnwinding;
|
this.structVariableMemberUnwinding = structVariableMemberUnwinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Comment> getFileComments() {
|
public List<Comment> getFileComments() {
|
||||||
|
@ -4,10 +4,9 @@ import dk.camelot64.kickc.model.symbols.ArraySpec;
|
|||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
|
||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
import dk.camelot64.kickc.passes.unwinding.RValueUnwinding;
|
import dk.camelot64.kickc.passes.unwinding.RValueUnwinding;
|
||||||
import dk.camelot64.kickc.passes.unwinding.StructMemberUnwinding;
|
import dk.camelot64.kickc.passes.unwinding.StructUnwinding;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -17,7 +16,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* Keeps track of all struct variables that have been unwound into member variables.
|
* Keeps track of all struct variables that have been unwound into member variables.
|
||||||
*/
|
*/
|
||||||
public class StructUnwinding {
|
public class StructVariableMemberUnwinding {
|
||||||
|
|
||||||
/** Maps struct variables to unwinding of each member. */
|
/** Maps struct variables to unwinding of each member. */
|
||||||
Map<SymbolVariableRef, VariableUnwinding> structVariables = new LinkedHashMap<>();
|
Map<SymbolVariableRef, VariableUnwinding> structVariables = new LinkedHashMap<>();
|
||||||
@ -48,7 +47,7 @@ public class StructUnwinding {
|
|||||||
|
|
||||||
|
|
||||||
/** Information about how a single struct variable was unwound. */
|
/** Information about how a single struct variable was unwound. */
|
||||||
public static class VariableUnwinding implements StructMemberUnwinding {
|
public static class VariableUnwinding implements StructUnwinding {
|
||||||
|
|
||||||
StructDefinition structDefinition;
|
StructDefinition structDefinition;
|
||||||
|
|
||||||
@ -70,7 +69,7 @@ public class StructUnwinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||||
return new RValueUnwinding() {
|
return new RValueUnwinding() {
|
||||||
@Override
|
@Override
|
||||||
public SymbolType getSymbolType() {
|
public SymbolType getSymbolType() {
|
@ -77,11 +77,11 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
|||||||
procReturnVarRef = (LValue) procReturnVar.getRef();
|
procReturnVarRef = (LValue) procReturnVar.getRef();
|
||||||
// Special handing of struct value returns
|
// Special handing of struct value returns
|
||||||
if(procReturnVar.getType() instanceof SymbolTypeStruct) {
|
if(procReturnVar.getType() instanceof SymbolTypeStruct) {
|
||||||
StructUnwinding.VariableUnwinding returnVarUnwinding = program.getStructUnwinding().getVariableUnwinding((VariableRef) procReturnVarRef);
|
StructVariableMemberUnwinding.VariableUnwinding returnVarUnwinding = program.getStructVariableMemberUnwinding().getVariableUnwinding((VariableRef) procReturnVarRef);
|
||||||
if(returnVarUnwinding!=null) {
|
if(returnVarUnwinding!=null) {
|
||||||
ArrayList<RValue> unwoundReturnVars = new ArrayList<>();
|
ArrayList<RValue> unwoundReturnVars = new ArrayList<>();
|
||||||
for(String memberName : returnVarUnwinding.getMemberNames()) {
|
for(String memberName : returnVarUnwinding.getMemberNames()) {
|
||||||
RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName);
|
RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName, getScope());
|
||||||
unwoundReturnVars.add(memberUnwinding.getUnwinding(getScope()));
|
unwoundReturnVars.add(memberUnwinding.getUnwinding(getScope()));
|
||||||
}
|
}
|
||||||
procReturnVarRef = new ValueList(unwoundReturnVars);
|
procReturnVarRef = new ValueList(unwoundReturnVars);
|
||||||
|
@ -10,6 +10,7 @@ import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
|||||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
import dk.camelot64.kickc.passes.unwinding.*;
|
import dk.camelot64.kickc.passes.unwinding.*;
|
||||||
|
import dk.camelot64.kickc.passes.unwinding.StructUnwinding;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -25,8 +26,8 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean step() {
|
public boolean step() {
|
||||||
if(getProgram().getStructUnwinding() == null) {
|
if(getProgram().getStructVariableMemberUnwinding() == null) {
|
||||||
getProgram().setStructUnwinding(new StructUnwinding());
|
getProgram().setStructVariableMemberUnwinding(new StructVariableMemberUnwinding());
|
||||||
}
|
}
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
// Unwind all procedure declaration parameters
|
// Unwind all procedure declaration parameters
|
||||||
@ -69,9 +70,9 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
if(programValue.get() instanceof StructMemberRef) {
|
if(programValue.get() instanceof StructMemberRef) {
|
||||||
StructMemberRef structMemberRef = (StructMemberRef) programValue.get();
|
StructMemberRef structMemberRef = (StructMemberRef) programValue.get();
|
||||||
if(structMemberRef.getStruct() instanceof VariableRef) {
|
if(structMemberRef.getStruct() instanceof VariableRef) {
|
||||||
StructMemberUnwinding memberVariables = getStructMemberUnwinding(structMemberRef.getStruct(), currentStmt, stmtIt, currentBlock);
|
StructUnwinding memberVariables = getStructMemberUnwinding(structMemberRef.getStruct(), currentStmt, stmtIt, currentBlock);
|
||||||
if(memberVariables != null && memberVariables != POSTPONE_UNWINDING) {
|
if(memberVariables != null && memberVariables != POSTPONE_UNWINDING) {
|
||||||
RValueUnwinding memberUnwinding = memberVariables.getMemberUnwinding(structMemberRef.getMemberName());
|
RValueUnwinding memberUnwinding = memberVariables.getMemberUnwinding(structMemberRef.getMemberName(), getScope());
|
||||||
RValue structMemberVariable = memberUnwinding.getUnwinding(getScope());
|
RValue structMemberVariable = memberUnwinding.getUnwinding(getScope());
|
||||||
getLog().append("Replacing struct member reference " + structMemberRef.toString(getProgram()) + " with member unwinding reference " + structMemberVariable.toString(getProgram()));
|
getLog().append("Replacing struct member reference " + structMemberRef.toString(getProgram()) + " with member unwinding reference " + structMemberVariable.toString(getProgram()));
|
||||||
programValue.set(structMemberVariable);
|
programValue.set(structMemberVariable);
|
||||||
@ -91,11 +92,11 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
private boolean unwindCall(StatementCall call, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
private boolean unwindCall(StatementCall call, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||||
// Unwind struct value return value
|
// Unwind struct value return value
|
||||||
boolean lvalUnwound = false;
|
boolean lvalUnwound = false;
|
||||||
StructMemberUnwinding lValueUnwinding = getStructMemberUnwinding(call.getlValue(), call, stmtIt, currentBlock);
|
StructUnwinding lValueUnwinding = getStructMemberUnwinding(call.getlValue(), call, stmtIt, currentBlock);
|
||||||
if(lValueUnwinding != null && lValueUnwinding != POSTPONE_UNWINDING) {
|
if(lValueUnwinding != null && lValueUnwinding != POSTPONE_UNWINDING) {
|
||||||
ArrayList<RValue> unwoundMembers = new ArrayList<>();
|
ArrayList<RValue> unwoundMembers = new ArrayList<>();
|
||||||
for(String memberName : lValueUnwinding.getMemberNames()) {
|
for(String memberName : lValueUnwinding.getMemberNames()) {
|
||||||
RValueUnwinding memberUnwinding = lValueUnwinding.getMemberUnwinding(memberName);
|
RValueUnwinding memberUnwinding = lValueUnwinding.getMemberUnwinding(memberName, getScope());
|
||||||
unwoundMembers.add(memberUnwinding.getUnwinding(getScope()));
|
unwoundMembers.add(memberUnwinding.getUnwinding(getScope()));
|
||||||
}
|
}
|
||||||
ValueList unwoundLValue = new ValueList(unwoundMembers);
|
ValueList unwoundLValue = new ValueList(unwoundMembers);
|
||||||
@ -109,11 +110,11 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
boolean anyParameterUnwound = false;
|
boolean anyParameterUnwound = false;
|
||||||
for(RValue parameter : call.getParameters()) {
|
for(RValue parameter : call.getParameters()) {
|
||||||
boolean unwound = false;
|
boolean unwound = false;
|
||||||
StructMemberUnwinding parameterUnwinding = getStructMemberUnwinding(parameter, call, stmtIt, currentBlock);
|
StructUnwinding parameterUnwinding = getStructMemberUnwinding(parameter, call, stmtIt, currentBlock);
|
||||||
if(parameterUnwinding != null && parameterUnwinding != POSTPONE_UNWINDING) {
|
if(parameterUnwinding != null && parameterUnwinding != POSTPONE_UNWINDING) {
|
||||||
// Passing a struct variable - convert it to member variables
|
// Passing a struct variable - convert it to member variables
|
||||||
for(String memberName : parameterUnwinding.getMemberNames()) {
|
for(String memberName : parameterUnwinding.getMemberNames()) {
|
||||||
RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName);
|
RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName, getScope());
|
||||||
unwoundParameters.add(memberUnwinding.getUnwinding(getScope()));
|
unwoundParameters.add(memberUnwinding.getUnwinding(getScope()));
|
||||||
}
|
}
|
||||||
unwound = true;
|
unwound = true;
|
||||||
@ -140,11 +141,11 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
private boolean unwindReturn(StatementReturn statementReturn, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
private boolean unwindReturn(StatementReturn statementReturn, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
// Unwind struct value return value
|
// Unwind struct value return value
|
||||||
StructMemberUnwinding returnVarUnwinding = getStructMemberUnwinding(statementReturn.getValue(), statementReturn, stmtIt, currentBlock);
|
StructUnwinding returnVarUnwinding = getStructMemberUnwinding(statementReturn.getValue(), statementReturn, stmtIt, currentBlock);
|
||||||
if(returnVarUnwinding != null && returnVarUnwinding != POSTPONE_UNWINDING) {
|
if(returnVarUnwinding != null && returnVarUnwinding != POSTPONE_UNWINDING) {
|
||||||
ArrayList<RValue> unwoundMembers = new ArrayList<>();
|
ArrayList<RValue> unwoundMembers = new ArrayList<>();
|
||||||
for(String memberName : returnVarUnwinding.getMemberNames()) {
|
for(String memberName : returnVarUnwinding.getMemberNames()) {
|
||||||
RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName);
|
RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName, getScope());
|
||||||
unwoundMembers.add(memberUnwinding.getUnwinding(getScope()));
|
unwoundMembers.add(memberUnwinding.getUnwinding(getScope()));
|
||||||
}
|
}
|
||||||
ValueList unwoundReturnValue = new ValueList(unwoundMembers);
|
ValueList unwoundReturnValue = new ValueList(unwoundMembers);
|
||||||
@ -167,10 +168,10 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
boolean procedureUnwound = false;
|
boolean procedureUnwound = false;
|
||||||
for(Variable parameter : procedure.getParameters()) {
|
for(Variable parameter : procedure.getParameters()) {
|
||||||
if(parameter.getType() instanceof SymbolTypeStruct) {
|
if(parameter.getType() instanceof SymbolTypeStruct) {
|
||||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
StructVariableMemberUnwinding structVariableMemberUnwinding = getProgram().getStructVariableMemberUnwinding();
|
||||||
StructUnwinding.VariableUnwinding parameterUnwinding = structUnwinding.getVariableUnwinding(parameter.getRef());
|
StructVariableMemberUnwinding.VariableUnwinding parameterUnwinding = structVariableMemberUnwinding.getVariableUnwinding(parameter.getRef());
|
||||||
for(String memberName : parameterUnwinding.getMemberNames()) {
|
for(String memberName : parameterUnwinding.getMemberNames()) {
|
||||||
RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName);
|
RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName, getScope());
|
||||||
SymbolVariableRef memberUnwindingRef = (SymbolVariableRef) memberUnwinding.getUnwinding(getScope());
|
SymbolVariableRef memberUnwindingRef = (SymbolVariableRef) memberUnwinding.getUnwinding(getScope());
|
||||||
unwoundParameterNames.add(memberUnwindingRef.getLocalName());
|
unwoundParameterNames.add(memberUnwindingRef.getLocalName());
|
||||||
procedureUnwound = true;
|
procedureUnwound = true;
|
||||||
@ -219,7 +220,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for struct unwinding
|
// Check for struct unwinding
|
||||||
StructMemberUnwinding lValueUnwinding = getStructMemberUnwinding(lValue, assignment, stmtIt, currentBlock);
|
StructUnwinding lValueUnwinding = getStructMemberUnwinding(lValue, assignment, stmtIt, currentBlock);
|
||||||
if(lValueUnwinding == null)
|
if(lValueUnwinding == null)
|
||||||
return false;
|
return false;
|
||||||
if(lValueUnwinding == POSTPONE_UNWINDING)
|
if(lValueUnwinding == POSTPONE_UNWINDING)
|
||||||
@ -228,7 +229,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
return false;
|
return false;
|
||||||
SymbolType rValueType = SymbolTypeInference.inferType(getScope(), rValue);
|
SymbolType rValueType = SymbolTypeInference.inferType(getScope(), rValue);
|
||||||
if(rValueType.equals(lValueStructType)) {
|
if(rValueType.equals(lValueStructType)) {
|
||||||
StructMemberUnwinding rValueUnwinding = getStructMemberUnwinding(rValue, assignment, stmtIt, currentBlock);
|
StructUnwinding rValueUnwinding = getStructMemberUnwinding(rValue, assignment, stmtIt, currentBlock);
|
||||||
if(rValueUnwinding == null) {
|
if(rValueUnwinding == null) {
|
||||||
throw new CompileError("Incompatible struct assignment " + assignment.toString(getProgram(), false), assignment);
|
throw new CompileError("Incompatible struct assignment " + assignment.toString(getProgram(), false), assignment);
|
||||||
}
|
}
|
||||||
@ -236,8 +237,8 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
return true;
|
return true;
|
||||||
List<RValue> lValueUnwoundPlaceholder = new ArrayList<>();
|
List<RValue> lValueUnwoundPlaceholder = new ArrayList<>();
|
||||||
for(String memberName : lValueUnwinding.getMemberNames()) {
|
for(String memberName : lValueUnwinding.getMemberNames()) {
|
||||||
RValueUnwinding lValueMemberUnwinding = lValueUnwinding.getMemberUnwinding(memberName);
|
RValueUnwinding lValueMemberUnwinding = lValueUnwinding.getMemberUnwinding(memberName, getScope());
|
||||||
RValueUnwinding rValueMemberUnwinding = rValueUnwinding.getMemberUnwinding(memberName);
|
RValueUnwinding rValueMemberUnwinding = rValueUnwinding.getMemberUnwinding(memberName, getScope());
|
||||||
unwindAssignment(lValueMemberUnwinding, rValueMemberUnwinding, lValueUnwoundPlaceholder, stmtIt, initialAssignment, source);
|
unwindAssignment(lValueMemberUnwinding, rValueMemberUnwinding, lValueUnwoundPlaceholder, stmtIt, initialAssignment, source);
|
||||||
}
|
}
|
||||||
StructUnwoundPlaceholder unwoundPlaceholder = new StructUnwoundPlaceholder(lValueStructType, lValueUnwoundPlaceholder);
|
StructUnwoundPlaceholder unwoundPlaceholder = new StructUnwoundPlaceholder(lValueStructType, lValueUnwoundPlaceholder);
|
||||||
@ -329,14 +330,14 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
if(value instanceof VariableRef) {
|
if(value instanceof VariableRef) {
|
||||||
Variable variable = getScope().getVariable((VariableRef) value);
|
Variable variable = getScope().getVariable((VariableRef) value);
|
||||||
if(variable.isStructClassic()) {
|
if(variable.isStructClassic()) {
|
||||||
return new StructVariableValueUnwinding(variable);
|
return new RValueUnwindingStructVariable(variable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(value instanceof StructZero) {
|
if(value instanceof StructZero) {
|
||||||
return new ZeroValueUnwinding(valueType, null);
|
return new RValueUnwindingZero(valueType, null);
|
||||||
}
|
}
|
||||||
if(value instanceof ConstantStructValue) {
|
if(value instanceof ConstantStructValue) {
|
||||||
return new ConstantValueUnwinding(valueType, null, (ConstantStructValue) value);
|
return new RValueUnwindingConstant(valueType, null, (ConstantStructValue) value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -353,7 +354,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
* @param currentBlock Program Context information. Current block
|
* @param currentBlock Program Context information. Current block
|
||||||
* @return null if the value is not a struct. Unwinding for the passed value if it is a struct. {@link #POSTPONE_UNWINDING} if the struct is not ready for unwinding yet.
|
* @return null if the value is not a struct. Unwinding for the passed value if it is a struct. {@link #POSTPONE_UNWINDING} if the struct is not ready for unwinding yet.
|
||||||
*/
|
*/
|
||||||
private StructMemberUnwinding getStructMemberUnwinding(RValue value, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
private StructUnwinding getStructMemberUnwinding(RValue value, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||||
if(value != null) {
|
if(value != null) {
|
||||||
SymbolType valueType = SymbolTypeInference.inferType(getScope(), value);
|
SymbolType valueType = SymbolTypeInference.inferType(getScope(), value);
|
||||||
if(valueType instanceof SymbolTypeStruct) {
|
if(valueType instanceof SymbolTypeStruct) {
|
||||||
@ -365,7 +366,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
if(numMembers != valueList.getList().size()) {
|
if(numMembers != valueList.getList().size()) {
|
||||||
throw new CompileError("Struct initialization list has wrong size. Need " + numMembers + " got " + valueList.getList().size(), currentStmt);
|
throw new CompileError("Struct initialization list has wrong size. Need " + numMembers + " got " + valueList.getList().size(), currentStmt);
|
||||||
}
|
}
|
||||||
return new StructMemberUnwindingValueList(valueList, structDefinition);
|
return new StructUnwindingValueList(valueList, structDefinition);
|
||||||
}
|
}
|
||||||
if(value instanceof CastValue)
|
if(value instanceof CastValue)
|
||||||
value = ((CastValue) value).getValue();
|
value = ((CastValue) value).getValue();
|
||||||
@ -373,21 +374,21 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
if(value instanceof VariableRef) {
|
if(value instanceof VariableRef) {
|
||||||
Variable variable = getScope().getVariable((VariableRef) value);
|
Variable variable = getScope().getVariable((VariableRef) value);
|
||||||
if(variable.isStructUnwind()) {
|
if(variable.isStructUnwind()) {
|
||||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
StructVariableMemberUnwinding structVariableMemberUnwinding = getProgram().getStructVariableMemberUnwinding();
|
||||||
return structUnwinding.getVariableUnwinding((VariableRef) value);
|
return structVariableMemberUnwinding.getVariableUnwinding((VariableRef) value);
|
||||||
} else if(variable.isStructClassic()) {
|
} else if(variable.isStructClassic()) {
|
||||||
return new StructVariableMemberUnwinding(variable, structDefinition, currentBlock, stmtIt, currentStmt);
|
return new StructUnwindingVariable(variable, structDefinition);
|
||||||
}
|
}
|
||||||
} else if(value instanceof StructMemberRef && ((StructMemberRef) value).getStruct() instanceof VariableRef) {
|
} else if(value instanceof StructMemberRef && ((StructMemberRef) value).getStruct() instanceof VariableRef) {
|
||||||
return POSTPONE_UNWINDING;
|
return POSTPONE_UNWINDING;
|
||||||
} else if(value instanceof PointerDereferenceSimple) {
|
} else if(value instanceof PointerDereferenceSimple) {
|
||||||
return new StructMemberUnwindingPointerDerefSimple((PointerDereferenceSimple) value, structDefinition, stmtIt, currentBlock, currentStmt);
|
return new StructUnwindingPointerDerefSimple((PointerDereferenceSimple) value, structDefinition, stmtIt, currentBlock, currentStmt);
|
||||||
} else if(value instanceof PointerDereferenceIndexed) {
|
} else if(value instanceof PointerDereferenceIndexed) {
|
||||||
return new StructMemberUnwindingPointerDerefIndexed((PointerDereferenceIndexed) value, structDefinition, stmtIt, currentBlock, currentStmt);
|
return new StructUnwindingPointerDerefIndexed((PointerDereferenceIndexed) value, structDefinition, stmtIt, currentBlock, currentStmt);
|
||||||
} else if(value instanceof ConstantStructValue) {
|
} else if(value instanceof ConstantStructValue) {
|
||||||
return new StructMemberUnwindingConstantValue((ConstantStructValue) value, structDefinition);
|
return new StructUnwindingConstant((ConstantStructValue) value, structDefinition);
|
||||||
} else if(value instanceof StructZero) {
|
} else if(value instanceof StructZero) {
|
||||||
return new StructMemberUnwindingZero((StructZero) value, structDefinition);
|
return new StructUnwindingZero((StructZero) value, structDefinition);
|
||||||
} else {
|
} else {
|
||||||
throw new InternalError("Struct unwinding not implemented for " + value.toString(getProgram()));
|
throw new InternalError("Struct unwinding not implemented for " + value.toString(getProgram()));
|
||||||
}
|
}
|
||||||
@ -397,7 +398,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Singleton signaling that unwinding should be postponed. */
|
/** Singleton signaling that unwinding should be postponed. */
|
||||||
private static final StructMemberUnwinding POSTPONE_UNWINDING = new StructMemberUnwinding() {
|
private static final StructUnwinding POSTPONE_UNWINDING = new StructUnwinding() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getMemberNames() {
|
public List<String> getMemberNames() {
|
||||||
@ -405,7 +406,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package dk.camelot64.kickc.passes;
|
package dk.camelot64.kickc.passes;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.Program;
|
import dk.camelot64.kickc.model.Program;
|
||||||
import dk.camelot64.kickc.model.StructUnwinding;
|
import dk.camelot64.kickc.model.StructVariableMemberUnwinding;
|
||||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||||
import dk.camelot64.kickc.model.symbols.Scope;
|
import dk.camelot64.kickc.model.symbols.Scope;
|
||||||
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
||||||
@ -9,7 +9,7 @@ import dk.camelot64.kickc.model.symbols.Variable;
|
|||||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||||
|
|
||||||
/** Create unwindings for all unwinding struct variables. The unwinding is a conversion to one variable per member.
|
/** Create unwindings for all unwinding struct variables. The unwinding is a conversion to one variable per member.
|
||||||
* The unwindings are stored in {@link Program#getStructUnwinding()}
|
* The unwindings are stored in {@link Program#getStructVariableMemberUnwinding()}
|
||||||
* */
|
* */
|
||||||
public class Pass1UnwindStructVariables extends Pass1Base {
|
public class Pass1UnwindStructVariables extends Pass1Base {
|
||||||
|
|
||||||
@ -19,8 +19,8 @@ public class Pass1UnwindStructVariables extends Pass1Base {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean step() {
|
public boolean step() {
|
||||||
if(getProgram().getStructUnwinding() == null) {
|
if(getProgram().getStructVariableMemberUnwinding() == null) {
|
||||||
getProgram().setStructUnwinding(new StructUnwinding());
|
getProgram().setStructVariableMemberUnwinding(new StructVariableMemberUnwinding());
|
||||||
}
|
}
|
||||||
// Iterate through all scopes generating member-variables for each struct
|
// Iterate through all scopes generating member-variables for each struct
|
||||||
return unwindStructVariables();
|
return unwindStructVariables();
|
||||||
@ -36,14 +36,14 @@ public class Pass1UnwindStructVariables extends Pass1Base {
|
|||||||
// Iterate through all scopes generating member-variables for each struct
|
// Iterate through all scopes generating member-variables for each struct
|
||||||
for(Variable variable : getScope().getAllVariables(true)) {
|
for(Variable variable : getScope().getAllVariables(true)) {
|
||||||
if(variable.isStructUnwind()) {
|
if(variable.isStructUnwind()) {
|
||||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
StructVariableMemberUnwinding structVariableMemberUnwinding = getProgram().getStructVariableMemberUnwinding();
|
||||||
if(structUnwinding.getVariableUnwinding(variable.getRef()) == null) {
|
if(structVariableMemberUnwinding.getVariableUnwinding(variable.getRef()) == null) {
|
||||||
// A non-volatile struct variable
|
// A non-volatile struct variable
|
||||||
Scope scope = variable.getScope();
|
Scope scope = variable.getScope();
|
||||||
if(!(scope instanceof StructDefinition)) {
|
if(!(scope instanceof StructDefinition)) {
|
||||||
// Not inside another struct
|
// Not inside another struct
|
||||||
StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope());
|
StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope());
|
||||||
StructUnwinding.VariableUnwinding variableUnwinding = structUnwinding.createVariableUnwinding(variable.getRef(), structDefinition);
|
StructVariableMemberUnwinding.VariableUnwinding variableUnwinding = structVariableMemberUnwinding.createVariableUnwinding(variable.getRef(), structDefinition);
|
||||||
for(Variable member : structDefinition.getAllVars(false)) {
|
for(Variable member : structDefinition.getAllVars(false)) {
|
||||||
boolean isParameter = scope instanceof Procedure && ((Procedure) scope).getParameters().contains(variable);
|
boolean isParameter = scope instanceof Procedure && ((Procedure) scope).getParameters().contains(variable);
|
||||||
Variable memberVariable = Variable.createStructMemberUnwound(variable, member, isParameter);
|
Variable memberVariable = Variable.createStructMemberUnwound(variable, member, isParameter);
|
||||||
|
@ -10,12 +10,12 @@ import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
|||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
/** Unwinding a constant value. */
|
/** Unwinding a constant value. */
|
||||||
public class ConstantValueUnwinding implements RValueUnwinding {
|
public class RValueUnwindingConstant implements RValueUnwinding {
|
||||||
private final SymbolType symbolType;
|
private final SymbolType symbolType;
|
||||||
private final ArraySpec arraySpec;
|
private final ArraySpec arraySpec;
|
||||||
private final ConstantValue value;
|
private final ConstantValue value;
|
||||||
|
|
||||||
public ConstantValueUnwinding(SymbolType symbolType, ArraySpec arraySpec, ConstantValue value) {
|
public RValueUnwindingConstant(SymbolType symbolType, ArraySpec arraySpec, ConstantValue value) {
|
||||||
this.symbolType = symbolType;
|
this.symbolType = symbolType;
|
||||||
this.arraySpec = arraySpec;
|
this.arraySpec = arraySpec;
|
||||||
this.value = value;
|
this.value = value;
|
@ -7,12 +7,12 @@ import dk.camelot64.kickc.model.values.LValue;
|
|||||||
import dk.camelot64.kickc.model.values.RValue;
|
import dk.camelot64.kickc.model.values.RValue;
|
||||||
|
|
||||||
/** Value unwinding that just returns a non-unwindable RValue. */
|
/** Value unwinding that just returns a non-unwindable RValue. */
|
||||||
class SimpleRValueUnwinding implements RValueUnwinding {
|
class RValueUnwindingSimple implements RValueUnwinding {
|
||||||
private final SymbolType type;
|
private final SymbolType type;
|
||||||
private final ArraySpec arraySpec;
|
private final ArraySpec arraySpec;
|
||||||
private final RValue memberValue;
|
private final RValue memberValue;
|
||||||
|
|
||||||
public SimpleRValueUnwinding(SymbolType type, ArraySpec arraySpec, RValue memberValue) {
|
public RValueUnwindingSimple(SymbolType type, ArraySpec arraySpec, RValue memberValue) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.arraySpec = arraySpec;
|
this.arraySpec = arraySpec;
|
||||||
this.memberValue = memberValue;
|
this.memberValue = memberValue;
|
@ -0,0 +1,70 @@
|
|||||||
|
package dk.camelot64.kickc.passes.unwinding;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||||
|
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.values.*;
|
||||||
|
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
class RValueUnwindingStructPointerDerefSimple implements RValueUnwinding {
|
||||||
|
private final PointerDereferenceSimple structPointerDeref;
|
||||||
|
private final ArraySpec memberArraySpec;
|
||||||
|
private final SymbolType memberType;
|
||||||
|
private final ConstantRef memberOffsetConstant;
|
||||||
|
|
||||||
|
private final ControlFlowBlock currentBlock;
|
||||||
|
private final ListIterator<Statement> stmtIt;
|
||||||
|
private final Statement currentStmt;
|
||||||
|
|
||||||
|
public RValueUnwindingStructPointerDerefSimple(PointerDereferenceSimple structPointerDeref, ArraySpec memberArraySpec, SymbolType memberType, ConstantRef memberOffsetConstant, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt, Statement currentStmt) {
|
||||||
|
this.structPointerDeref = structPointerDeref;
|
||||||
|
this.memberArraySpec = memberArraySpec;
|
||||||
|
this.memberType = memberType;
|
||||||
|
this.memberOffsetConstant = memberOffsetConstant;
|
||||||
|
this.currentBlock = currentBlock;
|
||||||
|
this.stmtIt = stmtIt;
|
||||||
|
this.currentStmt = currentStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SymbolType getSymbolType() {
|
||||||
|
return memberType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArraySpec getArraySpec() {
|
||||||
|
return memberArraySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getUnwinding(ProgramScope programScope) {
|
||||||
|
Scope scope = programScope.getScope(currentBlock.getScope());
|
||||||
|
Variable memberAddress = scope.addVariableIntermediate();
|
||||||
|
memberAddress.setType(new SymbolTypePointer(memberType));
|
||||||
|
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(memberType), structPointerDeref.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 boolean isBulkCopyable() {
|
||||||
|
return getArraySpec()!=null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LValue getBulkLValue(ProgramScope scope) {
|
||||||
|
return (LValue) getUnwinding(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getBulkRValue(ProgramScope scope) {
|
||||||
|
throw new RuntimeException("TODO: Implement!");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package dk.camelot64.kickc.passes.unwinding;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||||
|
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.values.*;
|
||||||
|
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
class RValueUnwindingStructPointerDereferenceIndexedMember implements RValueUnwinding {
|
||||||
|
private final PointerDereferenceIndexed structPointerDeref;
|
||||||
|
private final SymbolType memberType;
|
||||||
|
private final ArraySpec memberArraySpec;
|
||||||
|
private final ConstantRef memberOffsetConstant;
|
||||||
|
private final ControlFlowBlock currentBlock;
|
||||||
|
private final ListIterator<Statement> stmtIt;
|
||||||
|
private final Statement currentStmt;
|
||||||
|
|
||||||
|
public RValueUnwindingStructPointerDereferenceIndexedMember(PointerDereferenceIndexed structPointerDeref, SymbolType memberType, ArraySpec memberArraySpec, ConstantRef memberOffsetConstant, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt, Statement currentStmt) {
|
||||||
|
this.structPointerDeref = structPointerDeref;
|
||||||
|
this.memberType = memberType;
|
||||||
|
this.memberArraySpec = memberArraySpec;
|
||||||
|
this.memberOffsetConstant = memberOffsetConstant;
|
||||||
|
this.currentBlock = currentBlock;
|
||||||
|
this.stmtIt = stmtIt;
|
||||||
|
this.currentStmt = currentStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SymbolType getSymbolType() {
|
||||||
|
return memberType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArraySpec getArraySpec() {
|
||||||
|
return memberArraySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getUnwinding(ProgramScope programScope) {
|
||||||
|
Scope scope = programScope.getScope(currentBlock.getScope());
|
||||||
|
Variable memberAddress = scope.addVariableIntermediate();
|
||||||
|
memberAddress.setType(new SymbolTypePointer(memberType));
|
||||||
|
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(memberType), structPointerDeref.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(), structPointerDeref.getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBulkCopyable() {
|
||||||
|
return getArraySpec() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LValue getBulkLValue(ProgramScope scope) {
|
||||||
|
return (LValue) getUnwinding(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getBulkRValue(ProgramScope scope) {
|
||||||
|
throw new RuntimeException("TODO: Implement!");
|
||||||
|
}
|
||||||
|
}
|
@ -9,11 +9,11 @@ import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
|||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
/** Value unwinding for a variable. */
|
/** Value unwinding for a variable. */
|
||||||
public class StructVariableValueUnwinding implements RValueUnwinding {
|
public class RValueUnwindingStructVariable implements RValueUnwinding {
|
||||||
|
|
||||||
private final Variable variable;
|
private final Variable variable;
|
||||||
|
|
||||||
public StructVariableValueUnwinding(Variable variable) {
|
public RValueUnwindingStructVariable(Variable variable) {
|
||||||
this.variable = variable;
|
this.variable = variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,8 +29,7 @@ public class StructVariableValueUnwinding implements RValueUnwinding {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RValue getUnwinding(ProgramScope programScope) {
|
public RValue getUnwinding(ProgramScope programScope) {
|
||||||
ConstantSymbolPointer pointer = new ConstantSymbolPointer(variable.getRef());
|
return new ConstantSymbolPointer(variable.getRef());
|
||||||
return pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -41,8 +40,7 @@ public class StructVariableValueUnwinding implements RValueUnwinding {
|
|||||||
@Override
|
@Override
|
||||||
public LValue getBulkLValue(ProgramScope scope) {
|
public LValue getBulkLValue(ProgramScope scope) {
|
||||||
ConstantSymbolPointer pointer = new ConstantSymbolPointer(variable.getRef());
|
ConstantSymbolPointer pointer = new ConstantSymbolPointer(variable.getRef());
|
||||||
LValue pointerDeref = new PointerDereferenceSimple(pointer);
|
return new PointerDereferenceSimple(pointer);
|
||||||
return pointerDeref;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConstantValue getByteSize(ProgramScope scope) {
|
private ConstantValue getByteSize(ProgramScope scope) {
|
||||||
@ -56,5 +54,4 @@ public class StructVariableValueUnwinding implements RValueUnwinding {
|
|||||||
return new MemcpyValue(pointerDeref, getByteSize(scope), getSymbolType());
|
return new MemcpyValue(pointerDeref, getByteSize(scope), getSymbolType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package dk.camelot64.kickc.passes.unwinding;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.operators.Operators;
|
||||||
|
import dk.camelot64.kickc.model.symbols.ArraySpec;
|
||||||
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
|
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.values.*;
|
||||||
|
|
||||||
|
class RValueUnwindingStructVariableMemberArray implements RValueUnwinding {
|
||||||
|
private Variable structVariable;
|
||||||
|
private final SymbolType memberType;
|
||||||
|
private final ArraySpec memberArraySpec;
|
||||||
|
private final ConstantRef memberOffsetConstant;
|
||||||
|
|
||||||
|
public RValueUnwindingStructVariableMemberArray(Variable structVariable, SymbolType memberType, ArraySpec memberArraySpec, ConstantRef memberOffsetConstant) {
|
||||||
|
this.structVariable = structVariable;
|
||||||
|
this.memberType = memberType;
|
||||||
|
this.memberArraySpec = memberArraySpec;
|
||||||
|
this.memberOffsetConstant = memberOffsetConstant;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SymbolType getSymbolType() {
|
||||||
|
return memberType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArraySpec getArraySpec() {
|
||||||
|
return memberArraySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getUnwinding(ProgramScope programScope) {
|
||||||
|
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(structVariable.getRef());
|
||||||
|
// Pointer to member element type (elmtype*)&struct
|
||||||
|
SymbolTypePointer memberType = (SymbolTypePointer) getSymbolType();
|
||||||
|
ConstantCastValue structTypedPointer = new ConstantCastValue(new SymbolTypePointer(memberType.getElementType()), structPointer);
|
||||||
|
// Calculate member address (elmtype*)&struct + OFFSET_MEMBER
|
||||||
|
ConstantBinary memberArrayPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
|
||||||
|
// Unwind to (elmtype*)&struct + OFFSET_MEMBER
|
||||||
|
return memberArrayPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBulkCopyable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LValue getBulkLValue(ProgramScope scope) {
|
||||||
|
RValue memberArrayPointer = getUnwinding(scope);
|
||||||
|
return new PointerDereferenceSimple(memberArrayPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getBulkRValue(ProgramScope scope) {
|
||||||
|
RValue memberArrayPointer = getUnwinding(scope);
|
||||||
|
return new MemcpyValue(new PointerDereferenceSimple(memberArrayPointer), getArraySpec().getArraySize(), getSymbolType());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package dk.camelot64.kickc.passes.unwinding;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.operators.Operators;
|
||||||
|
import dk.camelot64.kickc.model.symbols.ArraySpec;
|
||||||
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
|
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.values.*;
|
||||||
|
|
||||||
|
class RValueUnwindingStructVariableMemberSimple implements RValueUnwinding {
|
||||||
|
private Variable structVariable;
|
||||||
|
private final SymbolType memberType;
|
||||||
|
private final ArraySpec memberArraySpec;
|
||||||
|
private final ConstantRef memberOffsetConstant;
|
||||||
|
|
||||||
|
public RValueUnwindingStructVariableMemberSimple(Variable structVariable, SymbolType memberType, ArraySpec memberArraySpec, ConstantRef memberOffsetConstant) {
|
||||||
|
this.structVariable = structVariable;
|
||||||
|
this.memberType = memberType;
|
||||||
|
this.memberArraySpec = memberArraySpec;
|
||||||
|
this.memberOffsetConstant = memberOffsetConstant;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SymbolType getSymbolType() {
|
||||||
|
return memberType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArraySpec getArraySpec() {
|
||||||
|
return memberArraySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getUnwinding(ProgramScope programScope) {
|
||||||
|
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(structVariable.getRef());
|
||||||
|
// Pointer to member type
|
||||||
|
ConstantCastValue structTypedPointer = new ConstantCastValue(new SymbolTypePointer(getSymbolType()), structPointer);
|
||||||
|
// Calculate member address (type*)&struct + OFFSET_MEMBER
|
||||||
|
ConstantBinary memberArrayPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
|
||||||
|
// Unwind to *((type*)&struct + OFFSET_MEMBER)
|
||||||
|
return new PointerDereferenceSimple(memberArrayPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBulkCopyable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LValue getBulkLValue(ProgramScope scope) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getBulkRValue(ProgramScope scope) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -10,11 +10,11 @@ import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
|||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
/** Assignment unwinding for a zero value. */
|
/** Assignment unwinding for a zero value. */
|
||||||
public class ZeroValueUnwinding implements RValueUnwinding {
|
public class RValueUnwindingZero implements RValueUnwinding {
|
||||||
private final SymbolType symbolType;
|
private final SymbolType symbolType;
|
||||||
private final ArraySpec arraySpec;
|
private final ArraySpec arraySpec;
|
||||||
|
|
||||||
public ZeroValueUnwinding(SymbolType symbolType, ArraySpec arraySpec) {
|
public RValueUnwindingZero(SymbolType symbolType, ArraySpec arraySpec) {
|
||||||
this.symbolType = symbolType;
|
this.symbolType = symbolType;
|
||||||
this.arraySpec = arraySpec;
|
this.arraySpec = arraySpec;
|
||||||
}
|
}
|
@ -1,88 +0,0 @@
|
|||||||
package dk.camelot64.kickc.passes.unwinding;
|
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
|
||||||
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.values.*;
|
|
||||||
import dk.camelot64.kickc.passes.PassNStructPointerRewriting;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
|
|
||||||
/** Unwinding for a indexed pointer deref to a struct. */
|
|
||||||
public class StructMemberUnwindingPointerDerefIndexed implements StructMemberUnwinding {
|
|
||||||
private final PointerDereferenceIndexed pointerDeref;
|
|
||||||
private final StructDefinition structDefinition;
|
|
||||||
private final ControlFlowBlock currentBlock;
|
|
||||||
private final ListIterator<Statement> stmtIt;
|
|
||||||
private final Statement currentStmt;
|
|
||||||
|
|
||||||
public StructMemberUnwindingPointerDerefIndexed(PointerDereferenceIndexed pointerDeref, StructDefinition structDefinition, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) {
|
|
||||||
this.structDefinition = structDefinition;
|
|
||||||
this.currentBlock = currentBlock;
|
|
||||||
this.stmtIt = stmtIt;
|
|
||||||
this.pointerDeref = pointerDeref;
|
|
||||||
this.currentStmt = currentStmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getMemberNames() {
|
|
||||||
Collection<Variable> structMemberVars = structDefinition.getAllVariables(false);
|
|
||||||
ArrayList<String> memberNames = new ArrayList<>();
|
|
||||||
for(Variable structMemberVar : structMemberVars) {
|
|
||||||
memberNames.add(structMemberVar.getLocalName());
|
|
||||||
}
|
|
||||||
return memberNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
|
||||||
return new RValueUnwinding() {
|
|
||||||
@Override
|
|
||||||
public SymbolType getSymbolType() {
|
|
||||||
return structDefinition.getMember(memberName).getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ArraySpec getArraySpec() {
|
|
||||||
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 boolean isBulkCopyable() {
|
|
||||||
return getArraySpec()!=null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LValue getBulkLValue(ProgramScope scope) {
|
|
||||||
return (LValue) getUnwinding(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RValue getBulkRValue(ProgramScope scope) {
|
|
||||||
throw new RuntimeException("TODO: Implement!");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
package dk.camelot64.kickc.passes.unwinding;
|
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
|
||||||
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.values.*;
|
|
||||||
import dk.camelot64.kickc.passes.PassNStructPointerRewriting;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
|
|
||||||
/** Unwinding for a simple pointer deref to a struct. */
|
|
||||||
public class StructMemberUnwindingPointerDerefSimple implements StructMemberUnwinding {
|
|
||||||
|
|
||||||
private final StructDefinition structDefinition;
|
|
||||||
private final ControlFlowBlock currentBlock;
|
|
||||||
private final ListIterator<Statement> stmtIt;
|
|
||||||
private final PointerDereferenceSimple pointerDeref;
|
|
||||||
private final Statement currentStmt;
|
|
||||||
|
|
||||||
public StructMemberUnwindingPointerDerefSimple(PointerDereferenceSimple pointerDeref, StructDefinition structDefinition, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) {
|
|
||||||
this.structDefinition = structDefinition;
|
|
||||||
this.currentBlock = currentBlock;
|
|
||||||
this.stmtIt = stmtIt;
|
|
||||||
this.pointerDeref = pointerDeref;
|
|
||||||
this.currentStmt = currentStmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getMemberNames() {
|
|
||||||
Collection<Variable> structMemberVars = structDefinition.getAllVariables(false);
|
|
||||||
ArrayList<String> memberNames = new ArrayList<>();
|
|
||||||
for(Variable structMemberVar : structMemberVars) {
|
|
||||||
memberNames.add(structMemberVar.getLocalName());
|
|
||||||
}
|
|
||||||
return memberNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
|
||||||
return new RValueUnwinding() {
|
|
||||||
@Override
|
|
||||||
public SymbolType getSymbolType() {
|
|
||||||
return structDefinition.getMember(memberName).getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ArraySpec getArraySpec() {
|
|
||||||
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 boolean isBulkCopyable() {
|
|
||||||
return getArraySpec()!=null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LValue getBulkLValue(ProgramScope scope) {
|
|
||||||
return (LValue) getUnwinding(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RValue getBulkRValue(ProgramScope scope) {
|
|
||||||
throw new RuntimeException("TODO: Implement!");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,9 +1,11 @@
|
|||||||
package dk.camelot64.kickc.passes.unwinding;
|
package dk.camelot64.kickc.passes.unwinding;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Assignment unwinding information for a struct value into separate members. */
|
/** Assignment unwinding information for a struct value into separate members. */
|
||||||
public interface StructMemberUnwinding {
|
public interface StructUnwinding {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the names of the members of the struct
|
* Get the names of the members of the struct
|
||||||
@ -16,8 +18,9 @@ public interface StructMemberUnwinding {
|
|||||||
* Get the RValue unwinding to use for copying a single member of the struct
|
* Get the RValue unwinding to use for copying a single member of the struct
|
||||||
*
|
*
|
||||||
* @param memberName The member name
|
* @param memberName The member name
|
||||||
|
* @param programScope
|
||||||
* @return The unwinding of the member
|
* @return The unwinding of the member
|
||||||
*/
|
*/
|
||||||
RValueUnwinding getMemberUnwinding(String memberName);
|
RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope);
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package dk.camelot64.kickc.passes.unwinding;
|
package dk.camelot64.kickc.passes.unwinding;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.symbols.ArraySpec;
|
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.StructDefinition;
|
||||||
import dk.camelot64.kickc.model.symbols.Variable;
|
import dk.camelot64.kickc.model.symbols.Variable;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
@ -12,11 +13,11 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Member unwinding for constant struct value. */
|
/** Member unwinding for constant struct value. */
|
||||||
public class StructMemberUnwindingConstantValue implements StructMemberUnwinding {
|
public class StructUnwindingConstant implements StructUnwinding {
|
||||||
private final ConstantStructValue constantStructValue;
|
private final ConstantStructValue constantStructValue;
|
||||||
private final StructDefinition structDefinition;
|
private final StructDefinition structDefinition;
|
||||||
|
|
||||||
public StructMemberUnwindingConstantValue(ConstantStructValue constantStructValue, StructDefinition structDefinition) {
|
public StructUnwindingConstant(ConstantStructValue constantStructValue, StructDefinition structDefinition) {
|
||||||
this.constantStructValue = constantStructValue;
|
this.constantStructValue = constantStructValue;
|
||||||
this.structDefinition = structDefinition;
|
this.structDefinition = structDefinition;
|
||||||
}
|
}
|
||||||
@ -32,12 +33,12 @@ public class StructMemberUnwindingConstantValue implements StructMemberUnwinding
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||||
final Variable member = structDefinition.getMember(memberName);
|
final Variable member = structDefinition.getMember(memberName);
|
||||||
final SymbolType type = member.getType();
|
final SymbolType type = member.getType();
|
||||||
final ArraySpec arraySpec = member.getArraySpec();
|
final ArraySpec arraySpec = member.getArraySpec();
|
||||||
final ConstantValue memberValue = constantStructValue.getValue(member.getRef());
|
final ConstantValue memberValue = constantStructValue.getValue(member.getRef());
|
||||||
return new ConstantValueUnwinding(type, arraySpec, memberValue);
|
return new RValueUnwindingConstant(type, arraySpec, memberValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
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.*;
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/** Unwinding for a indexed pointer deref to a struct. */
|
||||||
|
public class StructUnwindingPointerDerefIndexed implements StructUnwinding {
|
||||||
|
private final PointerDereferenceIndexed pointerDeref;
|
||||||
|
private final StructDefinition structDefinition;
|
||||||
|
private final ControlFlowBlock currentBlock;
|
||||||
|
private final ListIterator<Statement> stmtIt;
|
||||||
|
private final Statement currentStmt;
|
||||||
|
|
||||||
|
public StructUnwindingPointerDerefIndexed(PointerDereferenceIndexed pointerDeref, StructDefinition structDefinition, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) {
|
||||||
|
this.structDefinition = structDefinition;
|
||||||
|
this.currentBlock = currentBlock;
|
||||||
|
this.stmtIt = stmtIt;
|
||||||
|
this.pointerDeref = pointerDeref;
|
||||||
|
this.currentStmt = currentStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getMemberNames() {
|
||||||
|
Collection<Variable> structMemberVars = structDefinition.getAllVariables(false);
|
||||||
|
ArrayList<String> memberNames = new ArrayList<>();
|
||||||
|
for(Variable structMemberVar : structMemberVars) {
|
||||||
|
memberNames.add(structMemberVar.getLocalName());
|
||||||
|
}
|
||||||
|
return memberNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||||
|
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||||
|
Variable member = structDefinition.getMember(memberName);
|
||||||
|
SymbolType memberType = member.getType();
|
||||||
|
ArraySpec memberArraySpec = member.getArraySpec();
|
||||||
|
return new RValueUnwindingStructPointerDereferenceIndexedMember(pointerDeref, memberType, memberArraySpec, memberOffsetConstant, currentBlock, stmtIt, currentStmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
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.*;
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/** Unwinding for a simple pointer deref to a struct. */
|
||||||
|
public class StructUnwindingPointerDerefSimple implements StructUnwinding {
|
||||||
|
|
||||||
|
private final StructDefinition structDefinition;
|
||||||
|
private final ControlFlowBlock currentBlock;
|
||||||
|
private final ListIterator<Statement> stmtIt;
|
||||||
|
private final PointerDereferenceSimple pointerDeref;
|
||||||
|
private final Statement currentStmt;
|
||||||
|
|
||||||
|
public StructUnwindingPointerDerefSimple(PointerDereferenceSimple pointerDeref, StructDefinition structDefinition, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) {
|
||||||
|
this.structDefinition = structDefinition;
|
||||||
|
this.currentBlock = currentBlock;
|
||||||
|
this.stmtIt = stmtIt;
|
||||||
|
this.pointerDeref = pointerDeref;
|
||||||
|
this.currentStmt = currentStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getMemberNames() {
|
||||||
|
Collection<Variable> structMemberVars = structDefinition.getAllVariables(false);
|
||||||
|
ArrayList<String> memberNames = new ArrayList<>();
|
||||||
|
for(Variable structMemberVar : structMemberVars) {
|
||||||
|
memberNames.add(structMemberVar.getLocalName());
|
||||||
|
}
|
||||||
|
return memberNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||||
|
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||||
|
Variable member = structDefinition.getMember(memberName);
|
||||||
|
SymbolType memberType = member.getType();
|
||||||
|
ArraySpec memberArraySpec = member.getArraySpec();
|
||||||
|
return new RValueUnwindingStructPointerDerefSimple(pointerDeref, memberArraySpec, memberType, memberOffsetConstant, currentBlock, stmtIt, currentStmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package dk.camelot64.kickc.passes.unwinding;
|
package dk.camelot64.kickc.passes.unwinding;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.symbols.ArraySpec;
|
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.StructDefinition;
|
||||||
import dk.camelot64.kickc.model.symbols.Variable;
|
import dk.camelot64.kickc.model.symbols.Variable;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
@ -12,12 +13,12 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Member unwinding for a struct valueList. */
|
/** Member unwinding for a struct valueList. */
|
||||||
public class StructMemberUnwindingValueList implements StructMemberUnwinding {
|
public class StructUnwindingValueList implements StructUnwinding {
|
||||||
|
|
||||||
private final StructDefinition structDefinition;
|
private final StructDefinition structDefinition;
|
||||||
private final ValueList valueList;
|
private final ValueList valueList;
|
||||||
|
|
||||||
public StructMemberUnwindingValueList(ValueList valueList, StructDefinition structDefinition) {
|
public StructUnwindingValueList(ValueList valueList, StructDefinition structDefinition) {
|
||||||
this.valueList = valueList;
|
this.valueList = valueList;
|
||||||
this.structDefinition = structDefinition;
|
this.structDefinition = structDefinition;
|
||||||
}
|
}
|
||||||
@ -33,12 +34,12 @@ public class StructMemberUnwindingValueList implements StructMemberUnwinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||||
final SymbolType type = structDefinition.getMember(memberName).getType();
|
final SymbolType type = structDefinition.getMember(memberName).getType();
|
||||||
final ArraySpec arraySpec = structDefinition.getMember(memberName).getArraySpec();
|
final ArraySpec arraySpec = structDefinition.getMember(memberName).getArraySpec();
|
||||||
int memberIndex = getMemberNames().indexOf(memberName);
|
int memberIndex = getMemberNames().indexOf(memberName);
|
||||||
final RValue memberValue = valueList.getList().get(memberIndex);
|
final RValue memberValue = valueList.getList().get(memberIndex);
|
||||||
return new SimpleRValueUnwinding(type, arraySpec, memberValue);
|
return new RValueUnwindingSimple(type, arraySpec, memberValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
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.symbols.StructDefinition;
|
||||||
|
import dk.camelot64.kickc.model.symbols.Variable;
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/** Unwinding for a struct value with C-classic memory layout. */
|
||||||
|
public class StructUnwindingVariable implements StructUnwinding {
|
||||||
|
private Variable variable;
|
||||||
|
private StructDefinition structDefinition;
|
||||||
|
|
||||||
|
public StructUnwindingVariable(Variable variable, StructDefinition structDefinition) {
|
||||||
|
this.variable = variable;
|
||||||
|
this.structDefinition = structDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getMemberNames() {
|
||||||
|
Collection<Variable> structMemberVars = structDefinition.getAllVars(false);
|
||||||
|
ArrayList<String> memberNames = new ArrayList<>();
|
||||||
|
for(Variable structMemberVar : structMemberVars) {
|
||||||
|
memberNames.add(structMemberVar.getLocalName());
|
||||||
|
}
|
||||||
|
return memberNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||||
|
final SymbolType symbolType = structDefinition.getMember(memberName).getType();
|
||||||
|
final ArraySpec arraySpec = structDefinition.getMember(memberName).getArraySpec();
|
||||||
|
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
||||||
|
if(arraySpec==null) {
|
||||||
|
// Simple member value - unwind to value of member *((type*)&struct + OFFSET_MEMBER)
|
||||||
|
return new RValueUnwindingStructVariableMemberSimple(variable, symbolType, arraySpec, memberOffsetConstant);
|
||||||
|
} else {
|
||||||
|
// Array struct member - unwind to pointer to first element (elmtype*)&struct + OFFSET_MEMBER
|
||||||
|
return new RValueUnwindingStructVariableMemberArray(variable, symbolType, arraySpec, memberOffsetConstant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package dk.camelot64.kickc.passes.unwinding;
|
package dk.camelot64.kickc.passes.unwinding;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
||||||
import dk.camelot64.kickc.model.symbols.Variable;
|
import dk.camelot64.kickc.model.symbols.Variable;
|
||||||
import dk.camelot64.kickc.model.values.StructZero;
|
import dk.camelot64.kickc.model.values.StructZero;
|
||||||
@ -9,11 +10,11 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Unwinding for StructZero */
|
/** Unwinding for StructZero */
|
||||||
public class StructMemberUnwindingZero implements StructMemberUnwinding {
|
public class StructUnwindingZero implements StructUnwinding {
|
||||||
private StructZero structZero;
|
private StructZero structZero;
|
||||||
private StructDefinition structDefinition;
|
private StructDefinition structDefinition;
|
||||||
|
|
||||||
public StructMemberUnwindingZero(StructZero structZero, StructDefinition structDefinition) {
|
public StructUnwindingZero(StructZero structZero, StructDefinition structDefinition) {
|
||||||
this.structZero = structZero;
|
this.structZero = structZero;
|
||||||
this.structDefinition = structDefinition;
|
this.structDefinition = structDefinition;
|
||||||
}
|
}
|
||||||
@ -29,9 +30,9 @@ public class StructMemberUnwindingZero implements StructMemberUnwinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||||
Variable member = structDefinition.getMember(memberName);
|
Variable member = structDefinition.getMember(memberName);
|
||||||
return new ZeroValueUnwinding(member.getType(), member.getArraySpec());
|
return new RValueUnwindingZero(member.getType(), member.getArraySpec());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,141 +0,0 @@
|
|||||||
package dk.camelot64.kickc.passes.unwinding;
|
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
|
||||||
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.values.*;
|
|
||||||
import dk.camelot64.kickc.passes.PassNStructPointerRewriting;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
|
|
||||||
/** Unwinding for a struct value with C-classic memory layout. */
|
|
||||||
public class StructVariableMemberUnwinding implements StructMemberUnwinding {
|
|
||||||
private Variable variable;
|
|
||||||
private StructDefinition structDefinition;
|
|
||||||
private final ControlFlowBlock currentBlock;
|
|
||||||
private final ListIterator<Statement> stmtIt;
|
|
||||||
private final Statement currentStmt;
|
|
||||||
|
|
||||||
public StructVariableMemberUnwinding(Variable variable, StructDefinition structDefinition, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt, Statement currentStmt) {
|
|
||||||
this.variable = variable;
|
|
||||||
this.structDefinition = structDefinition;
|
|
||||||
this.currentBlock = currentBlock;
|
|
||||||
this.stmtIt = stmtIt;
|
|
||||||
this.currentStmt = currentStmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getMemberNames() {
|
|
||||||
Collection<Variable> structMemberVars = structDefinition.getAllVars(false);
|
|
||||||
ArrayList<String> memberNames = new ArrayList<>();
|
|
||||||
for(Variable structMemberVar : structMemberVars) {
|
|
||||||
memberNames.add(structMemberVar.getLocalName());
|
|
||||||
}
|
|
||||||
return memberNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
|
||||||
final SymbolType symbolType = structDefinition.getMember(memberName).getType();
|
|
||||||
final ArraySpec arraySpec = structDefinition.getMember(memberName).getArraySpec();
|
|
||||||
|
|
||||||
if(arraySpec==null) {
|
|
||||||
// Simple member value - unwind to value of member *((type*)&struct + OFFSET_MEMBER)
|
|
||||||
return new RValueUnwinding() {
|
|
||||||
@Override
|
|
||||||
public SymbolType getSymbolType() {
|
|
||||||
return symbolType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ArraySpec getArraySpec() {
|
|
||||||
return arraySpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RValue getUnwinding(ProgramScope programScope) {
|
|
||||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
|
||||||
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(variable.getRef());
|
|
||||||
// Pointer to member type
|
|
||||||
ConstantCastValue structTypedPointer = new ConstantCastValue(new SymbolTypePointer(getSymbolType()), structPointer);
|
|
||||||
// Calculate member address (type*)&struct + OFFSET_MEMBER
|
|
||||||
ConstantBinary memberArrayPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
|
|
||||||
// Unwind to *((type*)&struct + OFFSET_MEMBER)
|
|
||||||
return new PointerDereferenceSimple(memberArrayPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBulkCopyable() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LValue getBulkLValue(ProgramScope scope) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RValue getBulkRValue(ProgramScope scope) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// Array struct member - unwind to pointer to first element (elmtype*)&struct + OFFSET_MEMBER
|
|
||||||
return new RValueUnwinding() {
|
|
||||||
@Override
|
|
||||||
public SymbolType getSymbolType() {
|
|
||||||
return symbolType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ArraySpec getArraySpec() {
|
|
||||||
return arraySpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RValue getUnwinding(ProgramScope programScope) {
|
|
||||||
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
|
|
||||||
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(variable.getRef());
|
|
||||||
// Pointer to member element type (elmtype*)&struct
|
|
||||||
SymbolTypePointer memberType = (SymbolTypePointer) getSymbolType();
|
|
||||||
ConstantCastValue structTypedPointer = new ConstantCastValue(new SymbolTypePointer(memberType.getElementType()), structPointer);
|
|
||||||
// Calculate member address (elmtype*)&struct + OFFSET_MEMBER
|
|
||||||
ConstantBinary memberArrayPointer = new ConstantBinary(structTypedPointer, Operators.PLUS, memberOffsetConstant);
|
|
||||||
// Unwind to (elmtype*)&struct + OFFSET_MEMBER
|
|
||||||
return memberArrayPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBulkCopyable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LValue getBulkLValue(ProgramScope scope) {
|
|
||||||
RValue memberArrayPointer = getUnwinding(scope);
|
|
||||||
return new PointerDereferenceSimple(memberArrayPointer);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RValue getBulkRValue(ProgramScope scope) {
|
|
||||||
RValue memberArrayPointer = getUnwinding(scope);
|
|
||||||
return new MemcpyValue(new PointerDereferenceSimple(memberArrayPointer), getArraySpec().getArraySize(), getSymbolType());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user