mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-26 18:29:54 +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.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
import dk.camelot64.kickc.model.values.SymbolVariableRef;
|
||||
import dk.camelot64.kickc.passes.calcs.*;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -63,7 +61,7 @@ public class Program {
|
||||
/** Variables modified inside procedures. PASS 1 (STATIC) */
|
||||
private ProcedureModifiedVars procedureModifiedVars;
|
||||
/** Struct values unwound to individual variables. PASS 1 (STATIC) */
|
||||
private StructUnwinding structUnwinding;
|
||||
private StructVariableMemberUnwinding structVariableMemberUnwinding;
|
||||
|
||||
/** The main scope. PASS 0-5 (DYNAMIC) */
|
||||
private ProgramScope scope;
|
||||
@ -119,7 +117,7 @@ public class Program {
|
||||
this.imported = null;
|
||||
this.statementSequence = null;
|
||||
this.procedureModifiedVars = null;
|
||||
this.structUnwinding = null;
|
||||
this.structVariableMemberUnwinding = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,12 +217,12 @@ public class Program {
|
||||
this.targetPlatform = targetPlatform;
|
||||
}
|
||||
|
||||
public StructUnwinding getStructUnwinding() {
|
||||
return structUnwinding;
|
||||
public StructVariableMemberUnwinding getStructVariableMemberUnwinding() {
|
||||
return structVariableMemberUnwinding;
|
||||
}
|
||||
|
||||
public void setStructUnwinding(StructUnwinding structUnwinding) {
|
||||
this.structUnwinding = structUnwinding;
|
||||
public void setStructVariableMemberUnwinding(StructVariableMemberUnwinding structVariableMemberUnwinding) {
|
||||
this.structVariableMemberUnwinding = structVariableMemberUnwinding;
|
||||
}
|
||||
|
||||
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.StructDefinition;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
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.LinkedHashMap;
|
||||
@ -17,7 +16,7 @@ import java.util.Map;
|
||||
/**
|
||||
* 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. */
|
||||
Map<SymbolVariableRef, VariableUnwinding> structVariables = new LinkedHashMap<>();
|
||||
@ -48,7 +47,7 @@ public class StructUnwinding {
|
||||
|
||||
|
||||
/** Information about how a single struct variable was unwound. */
|
||||
public static class VariableUnwinding implements StructMemberUnwinding {
|
||||
public static class VariableUnwinding implements StructUnwinding {
|
||||
|
||||
StructDefinition structDefinition;
|
||||
|
||||
@ -70,7 +69,7 @@ public class StructUnwinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
return new RValueUnwinding() {
|
||||
@Override
|
||||
public SymbolType getSymbolType() {
|
@ -77,11 +77,11 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
||||
procReturnVarRef = (LValue) procReturnVar.getRef();
|
||||
// Special handing of struct value returns
|
||||
if(procReturnVar.getType() instanceof SymbolTypeStruct) {
|
||||
StructUnwinding.VariableUnwinding returnVarUnwinding = program.getStructUnwinding().getVariableUnwinding((VariableRef) procReturnVarRef);
|
||||
StructVariableMemberUnwinding.VariableUnwinding returnVarUnwinding = program.getStructVariableMemberUnwinding().getVariableUnwinding((VariableRef) procReturnVarRef);
|
||||
if(returnVarUnwinding!=null) {
|
||||
ArrayList<RValue> unwoundReturnVars = new ArrayList<>();
|
||||
for(String memberName : returnVarUnwinding.getMemberNames()) {
|
||||
RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName);
|
||||
RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
unwoundReturnVars.add(memberUnwinding.getUnwinding(getScope()));
|
||||
}
|
||||
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.values.*;
|
||||
import dk.camelot64.kickc.passes.unwinding.*;
|
||||
import dk.camelot64.kickc.passes.unwinding.StructUnwinding;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -25,8 +26,8 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
if(getProgram().getStructUnwinding() == null) {
|
||||
getProgram().setStructUnwinding(new StructUnwinding());
|
||||
if(getProgram().getStructVariableMemberUnwinding() == null) {
|
||||
getProgram().setStructVariableMemberUnwinding(new StructVariableMemberUnwinding());
|
||||
}
|
||||
boolean modified = false;
|
||||
// Unwind all procedure declaration parameters
|
||||
@ -69,9 +70,9 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
if(programValue.get() instanceof StructMemberRef) {
|
||||
StructMemberRef structMemberRef = (StructMemberRef) programValue.get();
|
||||
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) {
|
||||
RValueUnwinding memberUnwinding = memberVariables.getMemberUnwinding(structMemberRef.getMemberName());
|
||||
RValueUnwinding memberUnwinding = memberVariables.getMemberUnwinding(structMemberRef.getMemberName(), getScope());
|
||||
RValue structMemberVariable = memberUnwinding.getUnwinding(getScope());
|
||||
getLog().append("Replacing struct member reference " + structMemberRef.toString(getProgram()) + " with member unwinding reference " + structMemberVariable.toString(getProgram()));
|
||||
programValue.set(structMemberVariable);
|
||||
@ -91,11 +92,11 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
private boolean unwindCall(StatementCall call, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
// Unwind struct value return value
|
||||
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) {
|
||||
ArrayList<RValue> unwoundMembers = new ArrayList<>();
|
||||
for(String memberName : lValueUnwinding.getMemberNames()) {
|
||||
RValueUnwinding memberUnwinding = lValueUnwinding.getMemberUnwinding(memberName);
|
||||
RValueUnwinding memberUnwinding = lValueUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
unwoundMembers.add(memberUnwinding.getUnwinding(getScope()));
|
||||
}
|
||||
ValueList unwoundLValue = new ValueList(unwoundMembers);
|
||||
@ -109,11 +110,11 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
boolean anyParameterUnwound = false;
|
||||
for(RValue parameter : call.getParameters()) {
|
||||
boolean unwound = false;
|
||||
StructMemberUnwinding parameterUnwinding = getStructMemberUnwinding(parameter, call, stmtIt, currentBlock);
|
||||
StructUnwinding parameterUnwinding = getStructMemberUnwinding(parameter, call, stmtIt, currentBlock);
|
||||
if(parameterUnwinding != null && parameterUnwinding != POSTPONE_UNWINDING) {
|
||||
// Passing a struct variable - convert it to member variables
|
||||
for(String memberName : parameterUnwinding.getMemberNames()) {
|
||||
RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName);
|
||||
RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
unwoundParameters.add(memberUnwinding.getUnwinding(getScope()));
|
||||
}
|
||||
unwound = true;
|
||||
@ -140,11 +141,11 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
private boolean unwindReturn(StatementReturn statementReturn, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
boolean modified = false;
|
||||
// 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) {
|
||||
ArrayList<RValue> unwoundMembers = new ArrayList<>();
|
||||
for(String memberName : returnVarUnwinding.getMemberNames()) {
|
||||
RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName);
|
||||
RValueUnwinding memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
unwoundMembers.add(memberUnwinding.getUnwinding(getScope()));
|
||||
}
|
||||
ValueList unwoundReturnValue = new ValueList(unwoundMembers);
|
||||
@ -167,10 +168,10 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
boolean procedureUnwound = false;
|
||||
for(Variable parameter : procedure.getParameters()) {
|
||||
if(parameter.getType() instanceof SymbolTypeStruct) {
|
||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
||||
StructUnwinding.VariableUnwinding parameterUnwinding = structUnwinding.getVariableUnwinding(parameter.getRef());
|
||||
StructVariableMemberUnwinding structVariableMemberUnwinding = getProgram().getStructVariableMemberUnwinding();
|
||||
StructVariableMemberUnwinding.VariableUnwinding parameterUnwinding = structVariableMemberUnwinding.getVariableUnwinding(parameter.getRef());
|
||||
for(String memberName : parameterUnwinding.getMemberNames()) {
|
||||
RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName);
|
||||
RValueUnwinding memberUnwinding = parameterUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
SymbolVariableRef memberUnwindingRef = (SymbolVariableRef) memberUnwinding.getUnwinding(getScope());
|
||||
unwoundParameterNames.add(memberUnwindingRef.getLocalName());
|
||||
procedureUnwound = true;
|
||||
@ -219,7 +220,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
// Check for struct unwinding
|
||||
StructMemberUnwinding lValueUnwinding = getStructMemberUnwinding(lValue, assignment, stmtIt, currentBlock);
|
||||
StructUnwinding lValueUnwinding = getStructMemberUnwinding(lValue, assignment, stmtIt, currentBlock);
|
||||
if(lValueUnwinding == null)
|
||||
return false;
|
||||
if(lValueUnwinding == POSTPONE_UNWINDING)
|
||||
@ -228,7 +229,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
return false;
|
||||
SymbolType rValueType = SymbolTypeInference.inferType(getScope(), rValue);
|
||||
if(rValueType.equals(lValueStructType)) {
|
||||
StructMemberUnwinding rValueUnwinding = getStructMemberUnwinding(rValue, assignment, stmtIt, currentBlock);
|
||||
StructUnwinding rValueUnwinding = getStructMemberUnwinding(rValue, assignment, stmtIt, currentBlock);
|
||||
if(rValueUnwinding == null) {
|
||||
throw new CompileError("Incompatible struct assignment " + assignment.toString(getProgram(), false), assignment);
|
||||
}
|
||||
@ -236,8 +237,8 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
return true;
|
||||
List<RValue> lValueUnwoundPlaceholder = new ArrayList<>();
|
||||
for(String memberName : lValueUnwinding.getMemberNames()) {
|
||||
RValueUnwinding lValueMemberUnwinding = lValueUnwinding.getMemberUnwinding(memberName);
|
||||
RValueUnwinding rValueMemberUnwinding = rValueUnwinding.getMemberUnwinding(memberName);
|
||||
RValueUnwinding lValueMemberUnwinding = lValueUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
RValueUnwinding rValueMemberUnwinding = rValueUnwinding.getMemberUnwinding(memberName, getScope());
|
||||
unwindAssignment(lValueMemberUnwinding, rValueMemberUnwinding, lValueUnwoundPlaceholder, stmtIt, initialAssignment, source);
|
||||
}
|
||||
StructUnwoundPlaceholder unwoundPlaceholder = new StructUnwoundPlaceholder(lValueStructType, lValueUnwoundPlaceholder);
|
||||
@ -329,14 +330,14 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
if(value instanceof VariableRef) {
|
||||
Variable variable = getScope().getVariable((VariableRef) value);
|
||||
if(variable.isStructClassic()) {
|
||||
return new StructVariableValueUnwinding(variable);
|
||||
return new RValueUnwindingStructVariable(variable);
|
||||
}
|
||||
}
|
||||
if(value instanceof StructZero) {
|
||||
return new ZeroValueUnwinding(valueType, null);
|
||||
return new RValueUnwindingZero(valueType, null);
|
||||
}
|
||||
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
|
||||
* @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) {
|
||||
SymbolType valueType = SymbolTypeInference.inferType(getScope(), value);
|
||||
if(valueType instanceof SymbolTypeStruct) {
|
||||
@ -365,7 +366,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
if(numMembers != valueList.getList().size()) {
|
||||
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)
|
||||
value = ((CastValue) value).getValue();
|
||||
@ -373,21 +374,21 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
if(value instanceof VariableRef) {
|
||||
Variable variable = getScope().getVariable((VariableRef) value);
|
||||
if(variable.isStructUnwind()) {
|
||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
||||
return structUnwinding.getVariableUnwinding((VariableRef) value);
|
||||
StructVariableMemberUnwinding structVariableMemberUnwinding = getProgram().getStructVariableMemberUnwinding();
|
||||
return structVariableMemberUnwinding.getVariableUnwinding((VariableRef) value);
|
||||
} 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) {
|
||||
return POSTPONE_UNWINDING;
|
||||
} 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) {
|
||||
return new StructMemberUnwindingPointerDerefIndexed((PointerDereferenceIndexed) value, structDefinition, stmtIt, currentBlock, currentStmt);
|
||||
return new StructUnwindingPointerDerefIndexed((PointerDereferenceIndexed) value, structDefinition, stmtIt, currentBlock, currentStmt);
|
||||
} else if(value instanceof ConstantStructValue) {
|
||||
return new StructMemberUnwindingConstantValue((ConstantStructValue) value, structDefinition);
|
||||
return new StructUnwindingConstant((ConstantStructValue) value, structDefinition);
|
||||
} else if(value instanceof StructZero) {
|
||||
return new StructMemberUnwindingZero((StructZero) value, structDefinition);
|
||||
return new StructUnwindingZero((StructZero) value, structDefinition);
|
||||
} else {
|
||||
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. */
|
||||
private static final StructMemberUnwinding POSTPONE_UNWINDING = new StructMemberUnwinding() {
|
||||
private static final StructUnwinding POSTPONE_UNWINDING = new StructUnwinding() {
|
||||
|
||||
@Override
|
||||
public List<String> getMemberNames() {
|
||||
@ -405,7 +406,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
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.Scope;
|
||||
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;
|
||||
|
||||
/** 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 {
|
||||
|
||||
@ -19,8 +19,8 @@ public class Pass1UnwindStructVariables extends Pass1Base {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
if(getProgram().getStructUnwinding() == null) {
|
||||
getProgram().setStructUnwinding(new StructUnwinding());
|
||||
if(getProgram().getStructVariableMemberUnwinding() == null) {
|
||||
getProgram().setStructVariableMemberUnwinding(new StructVariableMemberUnwinding());
|
||||
}
|
||||
// Iterate through all scopes generating member-variables for each struct
|
||||
return unwindStructVariables();
|
||||
@ -36,14 +36,14 @@ public class Pass1UnwindStructVariables extends Pass1Base {
|
||||
// Iterate through all scopes generating member-variables for each struct
|
||||
for(Variable variable : getScope().getAllVariables(true)) {
|
||||
if(variable.isStructUnwind()) {
|
||||
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
|
||||
if(structUnwinding.getVariableUnwinding(variable.getRef()) == null) {
|
||||
StructVariableMemberUnwinding structVariableMemberUnwinding = getProgram().getStructVariableMemberUnwinding();
|
||||
if(structVariableMemberUnwinding.getVariableUnwinding(variable.getRef()) == null) {
|
||||
// A non-volatile struct variable
|
||||
Scope scope = variable.getScope();
|
||||
if(!(scope instanceof StructDefinition)) {
|
||||
// Not inside another struct
|
||||
StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope());
|
||||
StructUnwinding.VariableUnwinding variableUnwinding = structUnwinding.createVariableUnwinding(variable.getRef(), structDefinition);
|
||||
StructVariableMemberUnwinding.VariableUnwinding variableUnwinding = structVariableMemberUnwinding.createVariableUnwinding(variable.getRef(), structDefinition);
|
||||
for(Variable member : structDefinition.getAllVars(false)) {
|
||||
boolean isParameter = scope instanceof Procedure && ((Procedure) scope).getParameters().contains(variable);
|
||||
Variable memberVariable = Variable.createStructMemberUnwound(variable, member, isParameter);
|
||||
|
@ -10,12 +10,12 @@ import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
/** Unwinding a constant value. */
|
||||
public class ConstantValueUnwinding implements RValueUnwinding {
|
||||
public class RValueUnwindingConstant implements RValueUnwinding {
|
||||
private final SymbolType symbolType;
|
||||
private final ArraySpec arraySpec;
|
||||
private final ConstantValue value;
|
||||
|
||||
public ConstantValueUnwinding(SymbolType symbolType, ArraySpec arraySpec, ConstantValue value) {
|
||||
public RValueUnwindingConstant(SymbolType symbolType, ArraySpec arraySpec, ConstantValue value) {
|
||||
this.symbolType = symbolType;
|
||||
this.arraySpec = arraySpec;
|
||||
this.value = value;
|
@ -7,12 +7,12 @@ import dk.camelot64.kickc.model.values.LValue;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
|
||||
/** Value unwinding that just returns a non-unwindable RValue. */
|
||||
class SimpleRValueUnwinding implements RValueUnwinding {
|
||||
class RValueUnwindingSimple implements RValueUnwinding {
|
||||
private final SymbolType type;
|
||||
private final ArraySpec arraySpec;
|
||||
private final RValue memberValue;
|
||||
|
||||
public SimpleRValueUnwinding(SymbolType type, ArraySpec arraySpec, RValue memberValue) {
|
||||
public RValueUnwindingSimple(SymbolType type, ArraySpec arraySpec, RValue memberValue) {
|
||||
this.type = type;
|
||||
this.arraySpec = arraySpec;
|
||||
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.*;
|
||||
|
||||
/** Value unwinding for a variable. */
|
||||
public class StructVariableValueUnwinding implements RValueUnwinding {
|
||||
public class RValueUnwindingStructVariable implements RValueUnwinding {
|
||||
|
||||
private final Variable variable;
|
||||
|
||||
public StructVariableValueUnwinding(Variable variable) {
|
||||
public RValueUnwindingStructVariable(Variable variable) {
|
||||
this.variable = variable;
|
||||
}
|
||||
|
||||
@ -29,8 +29,7 @@ public class StructVariableValueUnwinding implements RValueUnwinding {
|
||||
|
||||
@Override
|
||||
public RValue getUnwinding(ProgramScope programScope) {
|
||||
ConstantSymbolPointer pointer = new ConstantSymbolPointer(variable.getRef());
|
||||
return pointer;
|
||||
return new ConstantSymbolPointer(variable.getRef());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -41,8 +40,7 @@ public class StructVariableValueUnwinding implements RValueUnwinding {
|
||||
@Override
|
||||
public LValue getBulkLValue(ProgramScope scope) {
|
||||
ConstantSymbolPointer pointer = new ConstantSymbolPointer(variable.getRef());
|
||||
LValue pointerDeref = new PointerDereferenceSimple(pointer);
|
||||
return pointerDeref;
|
||||
return new PointerDereferenceSimple(pointer);
|
||||
}
|
||||
|
||||
private ConstantValue getByteSize(ProgramScope scope) {
|
||||
@ -56,5 +54,4 @@ public class StructVariableValueUnwinding implements RValueUnwinding {
|
||||
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.*;
|
||||
|
||||
/** Assignment unwinding for a zero value. */
|
||||
public class ZeroValueUnwinding implements RValueUnwinding {
|
||||
public class RValueUnwindingZero implements RValueUnwinding {
|
||||
private final SymbolType symbolType;
|
||||
private final ArraySpec arraySpec;
|
||||
|
||||
public ZeroValueUnwinding(SymbolType symbolType, ArraySpec arraySpec) {
|
||||
public RValueUnwindingZero(SymbolType symbolType, ArraySpec arraySpec) {
|
||||
this.symbolType = symbolType;
|
||||
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;
|
||||
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** 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
|
||||
@ -16,8 +18,9 @@ public interface StructMemberUnwinding {
|
||||
* Get the RValue unwinding to use for copying a single member of the struct
|
||||
*
|
||||
* @param memberName The member name
|
||||
* @param programScope
|
||||
* @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;
|
||||
|
||||
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;
|
||||
@ -12,11 +13,11 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/** Member unwinding for constant struct value. */
|
||||
public class StructMemberUnwindingConstantValue implements StructMemberUnwinding {
|
||||
public class StructUnwindingConstant implements StructUnwinding {
|
||||
private final ConstantStructValue constantStructValue;
|
||||
private final StructDefinition structDefinition;
|
||||
|
||||
public StructMemberUnwindingConstantValue(ConstantStructValue constantStructValue, StructDefinition structDefinition) {
|
||||
public StructUnwindingConstant(ConstantStructValue constantStructValue, StructDefinition structDefinition) {
|
||||
this.constantStructValue = constantStructValue;
|
||||
this.structDefinition = structDefinition;
|
||||
}
|
||||
@ -32,12 +33,12 @@ public class StructMemberUnwindingConstantValue implements StructMemberUnwinding
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
final Variable member = structDefinition.getMember(memberName);
|
||||
final SymbolType type = member.getType();
|
||||
final ArraySpec arraySpec = member.getArraySpec();
|
||||
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;
|
||||
|
||||
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;
|
||||
@ -12,12 +13,12 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/** Member unwinding for a struct valueList. */
|
||||
public class StructMemberUnwindingValueList implements StructMemberUnwinding {
|
||||
public class StructUnwindingValueList implements StructUnwinding {
|
||||
|
||||
private final StructDefinition structDefinition;
|
||||
private final ValueList valueList;
|
||||
|
||||
public StructMemberUnwindingValueList(ValueList valueList, StructDefinition structDefinition) {
|
||||
public StructUnwindingValueList(ValueList valueList, StructDefinition structDefinition) {
|
||||
this.valueList = valueList;
|
||||
this.structDefinition = structDefinition;
|
||||
}
|
||||
@ -33,12 +34,12 @@ public class StructMemberUnwindingValueList implements StructMemberUnwinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
final SymbolType type = structDefinition.getMember(memberName).getType();
|
||||
final ArraySpec arraySpec = structDefinition.getMember(memberName).getArraySpec();
|
||||
int memberIndex = getMemberNames().indexOf(memberName);
|
||||
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;
|
||||
|
||||
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.values.StructZero;
|
||||
@ -9,11 +10,11 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/** Unwinding for StructZero */
|
||||
public class StructMemberUnwindingZero implements StructMemberUnwinding {
|
||||
public class StructUnwindingZero implements StructUnwinding {
|
||||
private StructZero structZero;
|
||||
private StructDefinition structDefinition;
|
||||
|
||||
public StructMemberUnwindingZero(StructZero structZero, StructDefinition structDefinition) {
|
||||
public StructUnwindingZero(StructZero structZero, StructDefinition structDefinition) {
|
||||
this.structZero = structZero;
|
||||
this.structDefinition = structDefinition;
|
||||
}
|
||||
@ -29,9 +30,9 @@ public class StructMemberUnwindingZero implements StructMemberUnwinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValueUnwinding getMemberUnwinding(String memberName) {
|
||||
public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) {
|
||||
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