mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-23 23:32:55 +00:00
Eliminated VariableUnversioned.
This commit is contained in:
parent
51d3d8e7d5
commit
5d0fe66906
@ -80,12 +80,12 @@ public class AsmFragmentTemplate {
|
|||||||
// Generate a dummy instance to find clobber & cycles
|
// Generate a dummy instance to find clobber & cycles
|
||||||
ProgramScope scope = new ProgramScope();
|
ProgramScope scope = new ProgramScope();
|
||||||
LinkedHashMap<String, Value> bindings = new LinkedHashMap<>();
|
LinkedHashMap<String, Value> bindings = new LinkedHashMap<>();
|
||||||
Variable v1 = new Variable("$tmp1", scope, SymbolType.BYTE, null, false, true);
|
Variable v1 = new Variable("$tmp1", scope, SymbolType.BYTE, null, true, false, false);
|
||||||
Variable v2 = new Variable("$tmp2", scope, SymbolType.BYTE, null, false, true);
|
Variable v2 = new Variable("$tmp2", scope, SymbolType.BYTE, null, true, false, false);
|
||||||
Variable v3 = new Variable("$tmp3", scope, SymbolType.BYTE, null, false, true);
|
Variable v3 = new Variable("$tmp3", scope, SymbolType.BYTE, null, true, false, false);
|
||||||
Variable v4 = new Variable("$tmp4", scope, SymbolType.BYTE, null, false, true);
|
Variable v4 = new Variable("$tmp4", scope, SymbolType.BYTE, null, true, false, false);
|
||||||
Variable v5 = new Variable("$tmp5", scope, SymbolType.BYTE, null, false, true);
|
Variable v5 = new Variable("$tmp5", scope, SymbolType.BYTE, null, true, false, false);
|
||||||
Variable v6 = new Variable("$tmp6", scope, SymbolType.BYTE, null, false, true);
|
Variable v6 = new Variable("$tmp6", scope, SymbolType.BYTE, null, true, false, false);
|
||||||
v1.setAllocation(new Registers.RegisterZpByte(2));
|
v1.setAllocation(new Registers.RegisterZpByte(2));
|
||||||
v2.setAllocation(new Registers.RegisterZpByte(4));
|
v2.setAllocation(new Registers.RegisterZpByte(4));
|
||||||
v3.setAllocation(new Registers.RegisterZpByte(6));
|
v3.setAllocation(new Registers.RegisterZpByte(6));
|
||||||
|
@ -99,26 +99,26 @@ public abstract class Scope implements Symbol, Serializable {
|
|||||||
symbols.remove(symbol.getLocalName());
|
symbols.remove(symbol.getLocalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariableUnversioned addVariable(String name, SymbolType type, String dataSegment) {
|
public Variable addVariablePhiMaster(String name, SymbolType type, String dataSegment) {
|
||||||
return add(new VariableUnversioned(name, this, type, dataSegment));
|
return add(new Variable(name, this, type, dataSegment, false, false, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Variable addVariableIntermediate() {
|
public Variable addVariableIntermediate() {
|
||||||
String name = allocateIntermediateVariableName();
|
String name = allocateIntermediateVariableName();
|
||||||
return add(new Variable(name, this, SymbolType.VAR, getSegmentData(), true, false));
|
return add(new Variable(name, this, SymbolType.VAR, getSegmentData(), true, false, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all versions of an unversioned variable
|
* Get all versions of a PHI-master variable
|
||||||
*
|
*
|
||||||
* @param unversioned The unversioned variable
|
* @param unversioned The unversioned PHI-master variable
|
||||||
* @return All versions of the variable
|
* @return All versions of the variable
|
||||||
*/
|
*/
|
||||||
public Collection<Variable> getVersions(VariableUnversioned unversioned) {
|
public Collection<Variable> getVersions(Variable unversioned) {
|
||||||
LinkedHashSet<Variable> versions = new LinkedHashSet<>();
|
LinkedHashSet<Variable> versions = new LinkedHashSet<>();
|
||||||
for(Symbol symbol : symbols.values()) {
|
for(Symbol symbol : symbols.values()) {
|
||||||
if(symbol instanceof Variable) {
|
if(symbol instanceof Variable) {
|
||||||
if(((Variable) symbol).isVersioned()) {
|
if(((Variable) symbol).isPhiVersion()) {
|
||||||
if(((Variable) symbol).getVersionOf().equals(unversioned)) {
|
if(((Variable) symbol).getVersionOf().equals(unversioned)) {
|
||||||
versions.add((Variable) symbol);
|
versions.add((Variable) symbol);
|
||||||
}
|
}
|
||||||
|
@ -1,47 +1,70 @@
|
|||||||
package dk.camelot64.kickc.model.symbols;
|
package dk.camelot64.kickc.model.symbols;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.InternalError;
|
||||||
import dk.camelot64.kickc.model.Registers;
|
import dk.camelot64.kickc.model.Registers;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.values.VariableRef;
|
import dk.camelot64.kickc.model.values.VariableRef;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/** A Variable (or a Constant) */
|
/** A Variable in the program.
|
||||||
|
*
|
||||||
|
* There are several types of variables
|
||||||
|
*
|
||||||
|
* - Intermediate: A variable added by the compiler to hold some intermediate value. Intermediate variables are names $1, $2, ...
|
||||||
|
* - PHI-variable: A variable with storage strategy PHI is turned into versions. The variable itself is never used directly in the program.
|
||||||
|
* - PHI-versions: A variable with storage strategy PHI is turned into versions. Versions of the PHI-variable name are named name#1, name#2, name#3
|
||||||
|
* - Memory: A variable with storage strategy memory is used directly in the program.
|
||||||
|
* */
|
||||||
public class Variable extends SymbolVariable {
|
public class Variable extends SymbolVariable {
|
||||||
|
|
||||||
/** true if the variable is intermediate. */
|
/** true if the variable is intermediate. */
|
||||||
private boolean isIntermediate;
|
private boolean isIntermediate;
|
||||||
|
|
||||||
/* true if the variable is a PHI version. (the variable has storage strategy PHI)*/
|
/* true if the variable is a PHI master variable that is turned into versions. (the variable has storage strategy PHI)*/
|
||||||
private boolean isVersion;
|
private boolean isPhiMaster;
|
||||||
|
|
||||||
|
/** The number of the next version (only used for PHI masters)*/
|
||||||
|
private Integer nextVersionNumber;
|
||||||
|
|
||||||
|
/* true if the variable is a PHI version. (the "master" variable has storage strategy PHI)*/
|
||||||
|
private boolean isPhiVersion;
|
||||||
|
|
||||||
/** If the variable is assigned to a specific "register", this contains the register. If null the variable has no allocation (yet). Constants are never assigned to registers. */
|
/** If the variable is assigned to a specific "register", this contains the register. If null the variable has no allocation (yet). Constants are never assigned to registers. */
|
||||||
private Registers.Register allocation;
|
private Registers.Register allocation;
|
||||||
|
|
||||||
public Variable(String name, Scope scope, SymbolType type, String dataSegment, boolean isIntermediate, boolean isVersion) {
|
public Variable(String name, Scope scope, SymbolType type, String dataSegment, boolean isIntermediate, boolean isPhiVersion, boolean isPhiMaster) {
|
||||||
super(name, scope, type, dataSegment);
|
super(name, scope, type, dataSegment);
|
||||||
this.isIntermediate = isIntermediate;
|
this.isIntermediate = isIntermediate;
|
||||||
this.isVersion = isVersion;
|
this.isPhiVersion = isPhiVersion;
|
||||||
|
this.isPhiMaster = isPhiMaster;
|
||||||
|
if(isPhiMaster)
|
||||||
|
this.nextVersionNumber = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Variable(VariableUnversioned versionOf, int version) {
|
/**
|
||||||
super(versionOf.getName()+"#"+version, versionOf.getScope(), versionOf.getType(), versionOf.getDataSegment());
|
* Create a version of a PHI master variable
|
||||||
this.setDeclaredAlignment(versionOf.getDeclaredAlignment());
|
* @param phiMaster The PHI master variable.
|
||||||
this.setDeclaredAsRegister(versionOf.isDeclaredAsRegister());
|
* @param version The version number
|
||||||
this.setDeclaredAsMemory(versionOf.isDeclaredAsMemory());
|
*/
|
||||||
this.setDeclaredRegister(versionOf.getDeclaredRegister());
|
public Variable(Variable phiMaster, int version) {
|
||||||
this.setDeclaredMemoryAddress(versionOf.getDeclaredMemoryAddress());
|
super(phiMaster.getName()+"#"+version, phiMaster.getScope(), phiMaster.getType(), phiMaster.getDataSegment());
|
||||||
this.setStorageStrategy(versionOf.getStorageStrategy());
|
this.setDeclaredAlignment(phiMaster.getDeclaredAlignment());
|
||||||
this.setDeclaredVolatile(versionOf.isDeclaredVolatile());
|
this.setDeclaredAsRegister(phiMaster.isDeclaredAsRegister());
|
||||||
this.setDeclaredExport(versionOf.isDeclaredExport());
|
this.setDeclaredAsMemory(phiMaster.isDeclaredAsMemory());
|
||||||
this.setInferedVolatile(versionOf.isInferedVolatile());
|
this.setDeclaredRegister(phiMaster.getDeclaredRegister());
|
||||||
this.setInferredType(versionOf.isInferredType());
|
this.setDeclaredMemoryAddress(phiMaster.getDeclaredMemoryAddress());
|
||||||
this.setComments(versionOf.getComments());
|
this.setStorageStrategy(phiMaster.getStorageStrategy());
|
||||||
|
this.setDeclaredVolatile(phiMaster.isDeclaredVolatile());
|
||||||
|
this.setDeclaredExport(phiMaster.isDeclaredExport());
|
||||||
|
this.setInferedVolatile(phiMaster.isInferedVolatile());
|
||||||
|
this.setInferredType(phiMaster.isInferredType());
|
||||||
|
this.setComments(phiMaster.getComments());
|
||||||
|
this.isPhiMaster = false;
|
||||||
|
this.isPhiVersion = true;
|
||||||
this.isIntermediate = false;
|
this.isIntermediate = false;
|
||||||
this.isVersion = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Registers.Register getAllocation() {
|
public Registers.Register getAllocation() {
|
||||||
return allocation;
|
return allocation;
|
||||||
}
|
}
|
||||||
@ -50,23 +73,39 @@ public class Variable extends SymbolVariable {
|
|||||||
this.allocation = allocation;
|
this.allocation = allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isVersioned() {
|
public boolean isPhiMaster() {
|
||||||
return isVersion;
|
return isPhiMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPhiVersion() {
|
||||||
|
return isPhiVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIntermediate() {
|
public boolean isIntermediate() {
|
||||||
return isIntermediate;
|
return isIntermediate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new PHI-version from a PHI-master
|
||||||
|
* @return The new version of the PHI master
|
||||||
|
*/
|
||||||
|
public Variable createVersion() {
|
||||||
|
if(!isPhiMaster)
|
||||||
|
throw new InternalError("Cannot version non-PHI variable");
|
||||||
|
Variable version = new Variable(this, nextVersionNumber++);
|
||||||
|
getScope().add(version);
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the variable is a version of a variable returns the original variable.
|
* If the variable is a version of a variable returns the original variable.
|
||||||
* @return The original variable. Null if this is not a version.
|
* @return The original variable. Null if this is not a version.
|
||||||
*/
|
*/
|
||||||
public VariableUnversioned getVersionOf() {
|
public Variable getVersionOf() {
|
||||||
if(isVersioned()) {
|
if(isPhiVersion()) {
|
||||||
String name = getName();
|
String name = getName();
|
||||||
String versionOfName = name.substring(0, name.indexOf("#"));
|
String versionOfName = name.substring(0, name.indexOf("#"));
|
||||||
return (VariableUnversioned) getScope().getVariable(versionOfName);
|
return getScope().getVariable(versionOfName);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -83,12 +122,12 @@ public class Variable extends SymbolVariable {
|
|||||||
if(!super.equals(o)) return false;
|
if(!super.equals(o)) return false;
|
||||||
Variable variable = (Variable) o;
|
Variable variable = (Variable) o;
|
||||||
return isIntermediate == variable.isIntermediate &&
|
return isIntermediate == variable.isIntermediate &&
|
||||||
isVersion == variable.isVersion &&
|
isPhiVersion == variable.isPhiVersion &&
|
||||||
Objects.equals(allocation, variable.allocation);
|
Objects.equals(allocation, variable.allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), isIntermediate, isVersion, allocation);
|
return Objects.hash(super.hashCode(), isIntermediate, isPhiVersion, allocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
package dk.camelot64.kickc.model.symbols;
|
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Symbol (variable, jump label, etc.)
|
|
||||||
*/
|
|
||||||
public class VariableUnversioned extends Variable {
|
|
||||||
|
|
||||||
/** The number of the next version */
|
|
||||||
private Integer nextVersionNumber;
|
|
||||||
|
|
||||||
public VariableUnversioned( String name, Scope scope, SymbolType type, String dataSegment) {
|
|
||||||
super(name, scope, type, dataSegment, false, false);
|
|
||||||
this.nextVersionNumber = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the version number of the next version. (if anyone versions the symbol).
|
|
||||||
*/
|
|
||||||
int getNextVersionNumber() {
|
|
||||||
return nextVersionNumber++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Variable createVersion() {
|
|
||||||
Variable version = new Variable(this, this.getNextVersionNumber());
|
|
||||||
getScope().add(version);
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
}
|
|
@ -199,9 +199,9 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
procedure.setComments(ensureUnusedComments(getCommentsSymbol(ctx)));
|
procedure.setComments(ensureUnusedComments(getCommentsSymbol(ctx)));
|
||||||
scopeStack.push(procedure);
|
scopeStack.push(procedure);
|
||||||
Label procExit = procedure.addLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
|
Label procExit = procedure.addLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
|
||||||
VariableUnversioned returnVar = null;
|
Variable returnVar = null;
|
||||||
if(!SymbolType.VOID.equals(type)) {
|
if(!SymbolType.VOID.equals(type)) {
|
||||||
returnVar = procedure.addVariable("return", type, procedure.getSegmentData());
|
returnVar = procedure.addVariablePhiMaster("return", type, procedure.getSegmentData());
|
||||||
}
|
}
|
||||||
List<Variable> parameterList = new ArrayList<>();
|
List<Variable> parameterList = new ArrayList<>();
|
||||||
if(ctx.parameterListDecl() != null) {
|
if(ctx.parameterListDecl() != null) {
|
||||||
@ -260,7 +260,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
this.visitDeclTypes(ctx.declTypes());
|
this.visitDeclTypes(ctx.declTypes());
|
||||||
SymbolType type = declVarType;
|
SymbolType type = declVarType;
|
||||||
List<Directive> directives = declVarDirectives;
|
List<Directive> directives = declVarDirectives;
|
||||||
VariableUnversioned param = new VariableUnversioned(ctx.NAME().getText(), getCurrentScope(), type, currentDataSegment);
|
Variable param = new Variable(ctx.NAME().getText(), getCurrentScope(), type, currentDataSegment, false, false, true);
|
||||||
// Set initial storage strategy
|
// Set initial storage strategy
|
||||||
param.setStorageStrategy(SymbolVariable.StorageStrategy.PHI_REGISTER);
|
param.setStorageStrategy(SymbolVariable.StorageStrategy.PHI_REGISTER);
|
||||||
// Add directives
|
// Add directives
|
||||||
@ -554,7 +554,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
@Override
|
@Override
|
||||||
public Object visitDeclVariableInitExpr(KickCParser.DeclVariableInitExprContext ctx) {
|
public Object visitDeclVariableInitExpr(KickCParser.DeclVariableInitExprContext ctx) {
|
||||||
String varName = ctx.NAME().getText();
|
String varName = ctx.NAME().getText();
|
||||||
VariableUnversioned lValue = visitDeclVariableInit(varName, ctx);
|
Variable lValue = visitDeclVariableInit(varName, ctx);
|
||||||
SymbolType type = declVarType;
|
SymbolType type = declVarType;
|
||||||
List<Comment> comments = declVarComments;
|
List<Comment> comments = declVarComments;
|
||||||
KickCParser.ExprContext initializer = ctx.expr();
|
KickCParser.ExprContext initializer = ctx.expr();
|
||||||
@ -579,7 +579,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
@Override
|
@Override
|
||||||
public Object visitDeclVariableInitKasm(KickCParser.DeclVariableInitKasmContext ctx) {
|
public Object visitDeclVariableInitKasm(KickCParser.DeclVariableInitKasmContext ctx) {
|
||||||
String varName = ctx.NAME().getText();
|
String varName = ctx.NAME().getText();
|
||||||
VariableUnversioned lValue = visitDeclVariableInit(varName, ctx);
|
Variable lValue = visitDeclVariableInit(varName, ctx);
|
||||||
SymbolType type = this.declVarType;
|
SymbolType type = this.declVarType;
|
||||||
List<Comment> comments = this.declVarComments;
|
List<Comment> comments = this.declVarComments;
|
||||||
if(!(type instanceof SymbolTypeArray)) {
|
if(!(type instanceof SymbolTypeArray)) {
|
||||||
@ -608,14 +608,14 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private VariableUnversioned visitDeclVariableInit(String varName, KickCParser.DeclVariableInitContext ctx) {
|
private Variable visitDeclVariableInit(String varName, KickCParser.DeclVariableInitContext ctx) {
|
||||||
List<Directive> directives = declVarDirectives;
|
List<Directive> directives = declVarDirectives;
|
||||||
SymbolType type = declVarType;
|
SymbolType type = declVarType;
|
||||||
List<Comment> comments = declVarComments;
|
List<Comment> comments = declVarComments;
|
||||||
|
|
||||||
VariableUnversioned lValue;
|
Variable lValue;
|
||||||
try {
|
try {
|
||||||
lValue = getCurrentScope().addVariable(varName, type, currentDataSegment);
|
lValue = getCurrentScope().addVariablePhiMaster(varName, type, currentDataSegment);
|
||||||
} catch(CompileError e) {
|
} catch(CompileError e) {
|
||||||
throw new CompileError(e.getMessage(), new StatementSource(ctx));
|
throw new CompileError(e.getMessage(), new StatementSource(ctx));
|
||||||
}
|
}
|
||||||
@ -1202,7 +1202,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
Variable lValue;
|
Variable lValue;
|
||||||
if(varType != null) {
|
if(varType != null) {
|
||||||
try {
|
try {
|
||||||
lValue = getCurrentScope().addVariable(varName, varType, currentDataSegment);
|
lValue = getCurrentScope().addVariablePhiMaster(varName, varType, currentDataSegment);
|
||||||
} catch(CompileError e) {
|
} catch(CompileError e) {
|
||||||
throw new CompileError(e.getMessage(), statementSource);
|
throw new CompileError(e.getMessage(), statementSource);
|
||||||
}
|
}
|
||||||
@ -1627,7 +1627,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
scopeStack.push(typedefScope);
|
scopeStack.push(typedefScope);
|
||||||
SymbolType type = (SymbolType) this.visit(ctx.typeDecl());
|
SymbolType type = (SymbolType) this.visit(ctx.typeDecl());
|
||||||
String typedefName = ctx.NAME().getText();
|
String typedefName = ctx.NAME().getText();
|
||||||
typedefScope.addVariable(typedefName, type, currentDataSegment);
|
typedefScope.addVariablePhiMaster(typedefName, type, currentDataSegment);
|
||||||
scopeStack.pop();
|
scopeStack.pop();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -76,9 +76,9 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
|||||||
private void versionAssignment(VariableRef lValueRef, ProgramValue programLValue, StatementSource source) {
|
private void versionAssignment(VariableRef lValueRef, ProgramValue programLValue, StatementSource source) {
|
||||||
Collection<VariableRef> earlyIdentifiedConstants = getProgram().getEarlyIdentifiedConstants();
|
Collection<VariableRef> earlyIdentifiedConstants = getProgram().getEarlyIdentifiedConstants();
|
||||||
Variable assignedVar = getScope().getVariable(lValueRef);
|
Variable assignedVar = getScope().getVariable(lValueRef);
|
||||||
if(assignedVar instanceof VariableUnversioned) {
|
if(assignedVar.isPhiMaster()) {
|
||||||
// Assignment to a non-versioned non-intermediary variable
|
// Assignment to a non-versioned non-intermediary variable
|
||||||
VariableUnversioned assignedSymbol = (VariableUnversioned) assignedVar;
|
Variable assignedSymbol = assignedVar;
|
||||||
Variable version;
|
Variable version;
|
||||||
if(assignedSymbol.isDeclaredConstant() || earlyIdentifiedConstants.contains(assignedSymbol.getRef())) {
|
if(assignedSymbol.isDeclaredConstant() || earlyIdentifiedConstants.contains(assignedSymbol.getRef())) {
|
||||||
Collection<Variable> versions = assignedVar.getScope().getVersions(assignedSymbol);
|
Collection<Variable> versions = assignedVar.getScope().getVersions(assignedSymbol);
|
||||||
@ -100,9 +100,9 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
|||||||
private void versionAllUses() {
|
private void versionAllUses() {
|
||||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||||
// Newest version of variables in the block.
|
// Newest version of variables in the block.
|
||||||
Map<VariableUnversioned, Variable> blockVersions = new LinkedHashMap<>();
|
Map<Variable, Variable> blockVersions = new LinkedHashMap<>();
|
||||||
// New phi functions introduced in the block to create versions of variables.
|
// New phi functions introduced in the block to create versions of variables.
|
||||||
Map<VariableUnversioned, Variable> blockNewPhis = new LinkedHashMap<>();
|
Map<Variable, Variable> blockNewPhis = new LinkedHashMap<>();
|
||||||
ProgramValueIterator.execute(block, (programValue, currentStmt, stmtIt, currentBlock) -> {
|
ProgramValueIterator.execute(block, (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||||
if(programValue instanceof ProgramValue.ProgramValueParamValue) {
|
if(programValue instanceof ProgramValue.ProgramValueParamValue) {
|
||||||
// Call parameter values should not be versioned
|
// Call parameter values should not be versioned
|
||||||
@ -146,16 +146,16 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Add new Phi functions to block
|
// Add new Phi functions to block
|
||||||
for(VariableUnversioned symbol : blockNewPhis.keySet()) {
|
for(Variable symbol : blockNewPhis.keySet()) {
|
||||||
block.getPhiBlock().addPhiVariable(blockNewPhis.get(symbol).getRef());
|
block.getPhiBlock().addPhiVariable(blockNewPhis.get(symbol).getRef());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBlockVersions(VariableRef lValue, Map<VariableUnversioned, Variable> blockVersions) {
|
private void updateBlockVersions(VariableRef lValue, Map<Variable, Variable> blockVersions) {
|
||||||
VariableRef lValueRef = lValue;
|
VariableRef lValueRef = lValue;
|
||||||
Variable variable = Pass1GenerateSingleStaticAssignmentForm.this.getScope().getVariable(lValueRef);
|
Variable variable = Pass1GenerateSingleStaticAssignmentForm.this.getScope().getVariable(lValueRef);
|
||||||
if(variable.isVersioned()) {
|
if(variable.isPhiVersion()) {
|
||||||
blockVersions.put(variable.getVersionOf(), variable);
|
blockVersions.put(variable.getVersionOf(), variable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,15 +171,15 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
|||||||
*/
|
*/
|
||||||
private Variable findOrCreateVersion(
|
private Variable findOrCreateVersion(
|
||||||
Value rValue,
|
Value rValue,
|
||||||
Map<VariableUnversioned, Variable> blockVersions,
|
Map<Variable, Variable> blockVersions,
|
||||||
Map<VariableUnversioned, Variable> blockNewPhis) {
|
Map<Variable, Variable> blockNewPhis) {
|
||||||
Collection<VariableRef> earlyIdentifiedConstants = getProgram().getEarlyIdentifiedConstants();
|
Collection<VariableRef> earlyIdentifiedConstants = getProgram().getEarlyIdentifiedConstants();
|
||||||
Variable version = null;
|
Variable version = null;
|
||||||
if(rValue instanceof VariableRef) {
|
if(rValue instanceof VariableRef) {
|
||||||
Variable rValueVar = getScope().getVariable((VariableRef) rValue);
|
Variable rValueVar = getScope().getVariable((VariableRef) rValue);
|
||||||
if(rValueVar instanceof VariableUnversioned) {
|
if(rValueVar.isPhiMaster()) {
|
||||||
// rValue needs versioning - look for version in statements
|
// rValue needs versioning - look for version in statements
|
||||||
VariableUnversioned rSymbol = (VariableUnversioned) rValueVar;
|
Variable rSymbol = rValueVar;
|
||||||
if(rSymbol.isDeclaredConstant() || earlyIdentifiedConstants.contains(rSymbol.getRef())) {
|
if(rSymbol.isDeclaredConstant() || earlyIdentifiedConstants.contains(rSymbol.getRef())) {
|
||||||
// A constant - find the single created version
|
// A constant - find the single created version
|
||||||
Scope scope = rSymbol.getScope();
|
Scope scope = rSymbol.getScope();
|
||||||
@ -213,8 +213,8 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
|||||||
* false if new phis were added, meaning another iteration is needed.
|
* false if new phis were added, meaning another iteration is needed.
|
||||||
*/
|
*/
|
||||||
private boolean completePhiFunctions() {
|
private boolean completePhiFunctions() {
|
||||||
Map<LabelRef, Map<VariableUnversioned, Variable>> newPhis = new LinkedHashMap<>();
|
Map<LabelRef, Map<Variable, Variable>> newPhis = new LinkedHashMap<>();
|
||||||
Map<LabelRef, Map<VariableUnversioned, Variable>> symbolMap = buildSymbolMap();
|
Map<LabelRef, Map<Variable, Variable>> symbolMap = buildSymbolMap();
|
||||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||||
for(Statement statement : block.getStatements()) {
|
for(Statement statement : block.getStatements()) {
|
||||||
|
|
||||||
@ -224,18 +224,18 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
|||||||
if(phiVariable.isEmpty()) {
|
if(phiVariable.isEmpty()) {
|
||||||
VariableRef phiLValVarRef = phiVariable.getVariable();
|
VariableRef phiLValVarRef = phiVariable.getVariable();
|
||||||
Variable versioned = getScope().getVariable(phiLValVarRef);
|
Variable versioned = getScope().getVariable(phiLValVarRef);
|
||||||
VariableUnversioned unversioned = versioned.getVersionOf();
|
Variable unversioned = versioned.getVersionOf();
|
||||||
List<ControlFlowBlock> predecessors = getPhiPredecessors(block, getProgram());
|
List<ControlFlowBlock> predecessors = getPhiPredecessors(block, getProgram());
|
||||||
for(ControlFlowBlock predecessor : predecessors) {
|
for(ControlFlowBlock predecessor : predecessors) {
|
||||||
LabelRef predecessorLabel = predecessor.getLabel();
|
LabelRef predecessorLabel = predecessor.getLabel();
|
||||||
Map<VariableUnversioned, Variable> predecessorMap = symbolMap.get(predecessorLabel);
|
Map<Variable, Variable> predecessorMap = symbolMap.get(predecessorLabel);
|
||||||
Variable previousSymbol = null;
|
Variable previousSymbol = null;
|
||||||
if(predecessorMap != null) {
|
if(predecessorMap != null) {
|
||||||
previousSymbol = predecessorMap.get(unversioned);
|
previousSymbol = predecessorMap.get(unversioned);
|
||||||
}
|
}
|
||||||
if(previousSymbol == null) {
|
if(previousSymbol == null) {
|
||||||
// No previous symbol found in predecessor block. Look in new phi functions.
|
// No previous symbol found in predecessor block. Look in new phi functions.
|
||||||
Map<VariableUnversioned, Variable> predecessorNewPhis = newPhis.get(predecessorLabel);
|
Map<Variable, Variable> predecessorNewPhis = newPhis.get(predecessorLabel);
|
||||||
if(predecessorNewPhis == null) {
|
if(predecessorNewPhis == null) {
|
||||||
predecessorNewPhis = new LinkedHashMap<>();
|
predecessorNewPhis = new LinkedHashMap<>();
|
||||||
newPhis.put(predecessorLabel, predecessorNewPhis);
|
newPhis.put(predecessorLabel, predecessorNewPhis);
|
||||||
@ -256,9 +256,9 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
|||||||
}
|
}
|
||||||
// Ads new phi functions to blocks
|
// Ads new phi functions to blocks
|
||||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||||
Map<VariableUnversioned, Variable> blockNewPhis = newPhis.get(block.getLabel());
|
Map<Variable, Variable> blockNewPhis = newPhis.get(block.getLabel());
|
||||||
if(blockNewPhis != null) {
|
if(blockNewPhis != null) {
|
||||||
for(VariableUnversioned symbol : blockNewPhis.keySet()) {
|
for(Variable symbol : blockNewPhis.keySet()) {
|
||||||
StatementPhiBlock phiBlock = block.getPhiBlock();
|
StatementPhiBlock phiBlock = block.getPhiBlock();
|
||||||
phiBlock.addPhiVariable(blockNewPhis.get(symbol).getRef());
|
phiBlock.addPhiVariable(blockNewPhis.get(symbol).getRef());
|
||||||
}
|
}
|
||||||
@ -297,8 +297,8 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
|||||||
* Builds a map of all which versions each symbol has in each block.
|
* Builds a map of all which versions each symbol has in each block.
|
||||||
* Maps Control Flow Block Label -> ( Unversioned Symbol -> Versioned Symbol) for all relevant symbols.
|
* Maps Control Flow Block Label -> ( Unversioned Symbol -> Versioned Symbol) for all relevant symbols.
|
||||||
*/
|
*/
|
||||||
private Map<LabelRef, Map<VariableUnversioned, Variable>> buildSymbolMap() {
|
private Map<LabelRef, Map<Variable, Variable>> buildSymbolMap() {
|
||||||
Map<LabelRef, Map<VariableUnversioned, Variable>> symbolMap = new LinkedHashMap<>();
|
Map<LabelRef, Map<Variable, Variable>> symbolMap = new LinkedHashMap<>();
|
||||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||||
for(Statement statement : block.getStatements()) {
|
for(Statement statement : block.getStatements()) {
|
||||||
if(statement instanceof StatementLValue) {
|
if(statement instanceof StatementLValue) {
|
||||||
@ -315,14 +315,14 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
|||||||
return symbolMap;
|
return symbolMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSymbolToMap(LValue lValue, ControlFlowBlock block, Map<LabelRef, Map<VariableUnversioned, Variable>> symbolMap) {
|
private void addSymbolToMap(LValue lValue, ControlFlowBlock block, Map<LabelRef, Map<Variable, Variable>> symbolMap) {
|
||||||
if(lValue instanceof VariableRef) {
|
if(lValue instanceof VariableRef) {
|
||||||
Variable lValueVar = getScope().getVariable((VariableRef) lValue);
|
Variable lValueVar = getScope().getVariable((VariableRef) lValue);
|
||||||
if(lValueVar.isVersioned()) {
|
if(lValueVar.isPhiVersion()) {
|
||||||
Variable versioned = lValueVar;
|
Variable versioned = lValueVar;
|
||||||
LabelRef label = block.getLabel();
|
LabelRef label = block.getLabel();
|
||||||
VariableUnversioned unversioned = versioned.getVersionOf();
|
Variable unversioned = versioned.getVersionOf();
|
||||||
Map<VariableUnversioned, Variable> blockMap = symbolMap.get(label);
|
Map<Variable, Variable> blockMap = symbolMap.get(label);
|
||||||
if(blockMap == null) {
|
if(blockMap == null) {
|
||||||
blockMap = new LinkedHashMap<>();
|
blockMap = new LinkedHashMap<>();
|
||||||
symbolMap.put(label, blockMap);
|
symbolMap.put(label, blockMap);
|
||||||
|
@ -300,7 +300,7 @@ public class Pass1ProcedureInline extends Pass1Base {
|
|||||||
if(procSymbol instanceof Variable) {
|
if(procSymbol instanceof Variable) {
|
||||||
Variable procVar = (Variable) procSymbol;
|
Variable procVar = (Variable) procSymbol;
|
||||||
String inlineVarName = getInlineSymbolName(procedure, procSymbol, serial);
|
String inlineVarName = getInlineSymbolName(procedure, procSymbol, serial);
|
||||||
VariableUnversioned inlineVar = callScope.addVariable(inlineVarName, procSymbol.getType(), procVar.getDataSegment());
|
Variable inlineVar = callScope.addVariablePhiMaster(inlineVarName, procSymbol.getType(), procVar.getDataSegment());
|
||||||
inlineVar.setInferredType(procVar.isInferredType());
|
inlineVar.setInferredType(procVar.isInferredType());
|
||||||
inlineVar.setDeclaredAlignment(procVar.getDeclaredAlignment());
|
inlineVar.setDeclaredAlignment(procVar.getDeclaredAlignment());
|
||||||
inlineVar.setDeclaredConstant(procVar.isDeclaredConstant());
|
inlineVar.setDeclaredConstant(procVar.isDeclaredConstant());
|
||||||
|
@ -67,10 +67,10 @@ public class Pass1UnwindBlockScopes extends Pass1Base {
|
|||||||
Label unwound = procedure.addLabel(name);
|
Label unwound = procedure.addLabel(name);
|
||||||
unwoundSymbols.put(symbol.getRef(), unwound.getRef());
|
unwoundSymbols.put(symbol.getRef(), unwound.getRef());
|
||||||
}
|
}
|
||||||
} else if(symbol instanceof VariableUnversioned) {
|
} else if(symbol instanceof Variable && ((Variable) symbol).isPhiMaster()) {
|
||||||
String name = findLocalName(procedure, symbol);
|
String name = findLocalName(procedure, symbol);
|
||||||
VariableUnversioned var = (VariableUnversioned) symbol;
|
Variable var = (Variable) symbol;
|
||||||
VariableUnversioned unwound = procedure.addVariable(name, symbol.getType(), var.getDataSegment());
|
Variable unwound = procedure.addVariablePhiMaster(name, symbol.getType(), var.getDataSegment());
|
||||||
unwound.setDeclaredAlignment(var.getDeclaredAlignment());
|
unwound.setDeclaredAlignment(var.getDeclaredAlignment());
|
||||||
unwound.setDeclaredConstant(var.isDeclaredConstant());
|
unwound.setDeclaredConstant(var.isDeclaredConstant());
|
||||||
unwound.setDeclaredVolatile(var.isDeclaredVolatile());
|
unwound.setDeclaredVolatile(var.isDeclaredVolatile());
|
||||||
|
@ -212,9 +212,9 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
|||||||
for(Variable member : structDefinition.getAllVariables(false)) {
|
for(Variable member : structDefinition.getAllVariables(false)) {
|
||||||
Variable memberVariable;
|
Variable memberVariable;
|
||||||
if(variable.getRef().isIntermediate()) {
|
if(variable.getRef().isIntermediate()) {
|
||||||
memberVariable = scope.add(new Variable(variable.getLocalName() + "_" + member.getLocalName(), scope, member.getType(), variable.getDataSegment(), true, false));
|
memberVariable = scope.add(new Variable(variable.getLocalName() + "_" + member.getLocalName(), scope, member.getType(), variable.getDataSegment(), true, false, false));
|
||||||
} else {
|
} else {
|
||||||
memberVariable = scope.addVariable(variable.getLocalName() + "_" + member.getLocalName(), member.getType(), variable.getDataSegment());
|
memberVariable = scope.addVariablePhiMaster(variable.getLocalName() + "_" + member.getLocalName(), member.getType(), variable.getDataSegment());
|
||||||
}
|
}
|
||||||
memberVariable.setDeclaredVolatile(variable.isDeclaredVolatile());
|
memberVariable.setDeclaredVolatile(variable.isDeclaredVolatile());
|
||||||
memberVariable.setInferedVolatile(variable.isInferedVolatile());
|
memberVariable.setInferedVolatile(variable.isInferedVolatile());
|
||||||
|
@ -43,7 +43,7 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
|
|||||||
Collection<Symbol> tableSymbols = getScope().getAllSymbols(true);
|
Collection<Symbol> tableSymbols = getScope().getAllSymbols(true);
|
||||||
|
|
||||||
for(Symbol tableSymbol : tableSymbols) {
|
for(Symbol tableSymbol : tableSymbols) {
|
||||||
if(tableSymbol instanceof VariableUnversioned) continue;
|
if(tableSymbol instanceof Variable && ((Variable) tableSymbol).isPhiMaster()) continue;
|
||||||
if(tableSymbol instanceof ConstantVar) continue;
|
if(tableSymbol instanceof ConstantVar) continue;
|
||||||
if(tableSymbol instanceof StructDefinition) continue;
|
if(tableSymbol instanceof StructDefinition) continue;
|
||||||
if(tableSymbol instanceof EnumDefinition) continue;
|
if(tableSymbol instanceof EnumDefinition) continue;
|
||||||
|
@ -263,7 +263,7 @@ public class Pass4CodeGeneration {
|
|||||||
signature.append(" ").append(procedure.getLocalName()).append("(");
|
signature.append(" ").append(procedure.getLocalName()).append("(");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(Variable parameter : procedure.getParameters()) {
|
for(Variable parameter : procedure.getParameters()) {
|
||||||
List<Variable> versions = new ArrayList<>(procedure.getVersions((VariableUnversioned) parameter));
|
List<Variable> versions = new ArrayList<>(procedure.getVersions(parameter));
|
||||||
if(versions.size() > 0) {
|
if(versions.size() > 0) {
|
||||||
Variable param = versions.get(0);
|
Variable param = versions.get(0);
|
||||||
Registers.Register allocation = param.getAllocation();
|
Registers.Register allocation = param.getAllocation();
|
||||||
|
@ -33,10 +33,10 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
|
|||||||
|
|
||||||
// Add all versions of volatile variables to the same equivalence class
|
// Add all versions of volatile variables to the same equivalence class
|
||||||
for(Variable variable : getSymbols().getAllVariables(true)) {
|
for(Variable variable : getSymbols().getAllVariables(true)) {
|
||||||
if(variable.isVersioned() && variable.isVolatile()) {
|
if(variable.isPhiVersion() && variable.isVolatile()) {
|
||||||
// Found a volatile non-versioned variable
|
// Found a volatile non-versioned variable
|
||||||
for(Variable otherVariable : variable.getScope().getAllVariables(false)) {
|
for(Variable otherVariable : variable.getScope().getAllVariables(false)) {
|
||||||
if(otherVariable.isVersioned()) {
|
if(otherVariable.isPhiVersion()) {
|
||||||
if((otherVariable).getVersionOf().equals((variable).getVersionOf())) {
|
if((otherVariable).getVersionOf().equals((variable).getVersionOf())) {
|
||||||
// They share the same main variable
|
// They share the same main variable
|
||||||
LiveRangeEquivalenceClass varEC = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(variable.getRef());
|
LiveRangeEquivalenceClass varEC = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(variable.getRef());
|
||||||
|
Loading…
Reference in New Issue
Block a user