1
0
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:
Jesper Gravgaard 2020-01-19 19:50:04 +01:00
parent a32f783b74
commit 7ea2453733
23 changed files with 495 additions and 398 deletions

View File

@ -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() {

View File

@ -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() {

View File

@ -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);

View File

@ -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;
}
};

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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!");
}
}

View File

@ -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!");
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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!");
}
};
}
}

View File

@ -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!");
}
};
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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());
}
}

View File

@ -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());
}
};
}
}
}