1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-07 07:29:49 +00:00

Implemented most of stack based parameter fetching inside procedures. #316

This commit is contained in:
jespergravgaard 2019-09-19 08:22:54 +02:00
parent 51d1e6f41f
commit 25742f1654
11 changed files with 182 additions and 20 deletions

View File

@ -35,7 +35,7 @@ public class CompileLog {
/**
* Should Memory usage be verbose
*/
private boolean verboseMemoryUsage = false;
private boolean verboseSizeInfo = false;
/**
* Should loop unrolling be verbose.
@ -101,17 +101,17 @@ public class CompileLog {
return log;
}
public CompileLog verboseMemoryUsage() {
setVerboseMemoryUsage(true);
public CompileLog verboseSizeInfo() {
setVerboseSizeInfo(true);
return this;
}
public boolean isVerboseMemoryUsage() {
return verboseMemoryUsage;
public boolean isVerboseSizeInfo() {
return verboseSizeInfo;
}
public void setVerboseMemoryUsage(boolean verboseMemoryUsage) {
this.verboseMemoryUsage = verboseMemoryUsage;
public void setVerboseSizeInfo(boolean verboseSizeInfo) {
this.verboseSizeInfo = verboseSizeInfo;
}
public CompileLog verboseSsaSourceCode() {

View File

@ -321,7 +321,7 @@ public class Compiler {
private void pass2Optimize() {
if(getLog().isVerboseMemoryUsage()) {
if(getLog().isVerboseSizeInfo()) {
getLog().append(program.getSizeInfo());
}
@ -373,7 +373,7 @@ public class Compiler {
private void pass2InlineConstants() {
if(getLog().isVerboseMemoryUsage()) {
if(getLog().isVerboseSizeInfo()) {
getLog().append(program.getSizeInfo());
}
@ -445,7 +445,7 @@ public class Compiler {
private void pass3Analysis() {
if(getLog().isVerboseMemoryUsage()) {
if(getLog().isVerboseSizeInfo()) {
getLog().append(program.getSizeInfo());
}
@ -485,6 +485,10 @@ public class Compiler {
new PassNBlockSequencePlanner(program).step();
new Pass3AddNopBeforeCallOns(program).generate();
new PassNStatementIndices(program).execute();
// Handle calling convention stack
new PassNCallingConventionStack(program).execute();
program.clearCallGraph();
program.clearStatementInfos();
program.clearVariableReferenceInfos();
@ -499,7 +503,7 @@ public class Compiler {
private void pass4RegisterAllocation() {
if(getLog().isVerboseMemoryUsage()) {
if(getLog().isVerboseSizeInfo()) {
getLog().append(program.getSizeInfo());
}
@ -554,7 +558,7 @@ public class Compiler {
} while(change);
getLog().append(program.getRegisterPotentials().toString());
if(getLog().isVerboseMemoryUsage()) {
if(getLog().isVerboseSizeInfo()) {
getLog().append(program.getSizeInfo());
}

View File

@ -90,8 +90,8 @@ public class KickC implements Callable<Void> {
@CommandLine.Option(names = {"-voptimize"}, description = "Verbosity Option. Control Flow Graph Optimization.")
private boolean verboseSSAOptimize = false;
@CommandLine.Option(names = {"-vmemory"}, description = "Verbosity Option. Compiler Data Structure Sizes.")
private boolean verboseMemory = false;
@CommandLine.Option(names = {"-vsizeinfo"}, description = "Verbosity Option. Compiler Data Structure Size Information.")
private boolean verboseSizeInfo = false;
@CommandLine.Option(names = {"-vnonoptimize"}, description = "Verbosity Option. Choices not to optimize.")
private boolean verboseNonOptimization = false;
@ -380,8 +380,8 @@ public class KickC implements Callable<Void> {
compiler.getLog().setVerboseSSAOptimize(true);
compiler.getLog().setSysOut(true);
}
if(verboseMemory) {
compiler.getLog().setVerboseMemoryUsage(true);
if(verboseSizeInfo) {
compiler.getLog().setVerboseSizeInfo(true);
compiler.getLog().setSysOut(true);
}
if(verboseNonOptimization) {

View File

@ -233,7 +233,6 @@ public class AsmFragmentInstanceSpecFactory {
* @return The bound name of the value. If the value has already been bound the existing bound name is returned.
*/
public String bind(Value value, SymbolType castType) {
if(value instanceof CastValue) {
CastValue cast = (CastValue) value;
SymbolType toType = cast.getToType();
@ -357,8 +356,11 @@ public class AsmFragmentInstanceSpecFactory {
String name = "la" + nextLabelIdx++;
bind(name, value);
return name;
} else if(value instanceof ParamStackValue) {
// TODO: Handle different parameter types!
return "_stackbyte_"+bind(((ParamStackValue) value).getStackOffset());
}
throw new RuntimeException("Binding of value type not supported " + value);
throw new RuntimeException("Binding of value type not supported " + value.toString(program));
}
/**

View File

@ -775,6 +775,26 @@ public interface ProgramValue {
}
/** Value inside a parameter stack value . */
class ProgramValueParamStackValue implements ProgramValue {
private final ParamStackValue paramValue;
ProgramValueParamStackValue(ParamStackValue paramValue) {
this.paramValue = paramValue;
}
@Override
public Value get() {
return paramValue.getStackOffset();
}
@Override
public void set(Value val) {
paramValue.setStackOffset((ConstantRef) val);
}
}
/**
* Pointer inside a pointer derefence value.
*/

View File

@ -236,6 +236,8 @@ public class ProgramValueIterator {
subValues.add(new ProgramValue.ProgramValueLValueIntermediateVariable((LvalueIntermediate) value));
} else if(value instanceof ParamValue) {
subValues.add(new ProgramValue.ProgramValueParamValue((ParamValue) value));
} else if(value instanceof ParamStackValue) {
subValues.add(new ProgramValue.ProgramValueParamStackValue((ParamStackValue) value));
} else if(value == null ||
value instanceof VariableRef ||
value instanceof VariableVersion ||

View File

@ -116,6 +116,8 @@ public class SymbolTypeInference {
return ((StructZero)rValue).getTypeStruct();
} else if(rValue instanceof ParamValue) {
return inferType(symbols, ((ParamValue) rValue).getParameter());
} else if(rValue instanceof ParamStackValue) {
return SymbolType.BYTE;
} else if(rValue instanceof StructUnwoundPlaceholder) {
return ((StructUnwoundPlaceholder) rValue).getTypeStruct();
}

View File

@ -77,7 +77,7 @@ public class SymbolTypeStruct implements SymbolType {
} else {
return memberType.getSizeBytes();
}
throw new InternalError("Memeber type not handled "+memberType);
throw new InternalError("Member type not handled "+memberType);
}
@Override

View File

@ -0,0 +1,28 @@
package dk.camelot64.kickc.model.values;
import dk.camelot64.kickc.model.Program;
/** The value passed into a function for a specific parameter using the stack. */
public class ParamStackValue implements RValue {
/** The constant holding the stack offset of the parameter. */
private ConstantRef stackOffset;
public ParamStackValue(ConstantRef stackOffset) {
this.stackOffset = stackOffset;
}
public ConstantRef getStackOffset() {
return stackOffset;
}
public void setStackOffset(ConstantRef stackOffset) {
this.stackOffset = stackOffset;
}
@Override
public String toString(Program program) {
return "paramstack("+stackOffset+")";
}
}

View File

@ -8,7 +8,7 @@ import dk.camelot64.kickc.model.Program;
public class ParamValue implements RValue {
/** The (unversioned) parameter variable. */
VariableRef parameter;
private VariableRef parameter;
public ParamValue(VariableRef parameter) {
this.parameter = parameter;

View File

@ -0,0 +1,104 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.*;
import java.util.HashMap;
import java.util.Map;
/** Handle calling convention {@link Procedure.CallingConvension#STACK_CALL} by converting the making control flow graph and symbols calling convention specific. */
public class PassNCallingConventionStack extends Pass2SsaOptimization {
public PassNCallingConventionStack(Program program) {
super(program);
}
@Override
public boolean step() {
// Offset-constants for all stack-call parameters
Map<VariableRef, ConstantRef> offsetConstants = new HashMap<>();
// Introduce STACK_OFFSET constants
for(Procedure procedure : getScope().getAllProcedures(true)) {
if(Procedure.CallingConvension.STACK_CALL.equals(procedure.getCallingConvension())) {
for(Variable parameter : procedure.getParameters()) {
ConstantRef parameterOffsetConstant = getParameterOffsetConstant(procedure, parameter, getScope());
offsetConstants.put(parameter.getRef(), parameterOffsetConstant);
}
}
}
//TODO: Add global STACK_BASE constant
if(offsetConstants.size() > 0) {
// Convert ParamValue to ParamStackValue
ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
if(programValue.get() instanceof ParamValue) {
// Convert ParamValues to calling-convention specific param-value
ParamValue paramValue = (ParamValue) programValue.get();
VariableRef parameterRef = paramValue.getParameter();
if(offsetConstants.containsKey(parameterRef)) {
ParamStackValue paramStackValue = new ParamStackValue(offsetConstants.get(parameterRef));
programValue.set(paramStackValue);
getLog().append("Calling convention " + Procedure.CallingConvension.STACK_CALL + " replacing " + paramValue.toString(getProgram()) + " with " + paramStackValue.toString(getProgram()));
}
}
});
}
return false;
}
/**
* Get the constant variable containing the (byte) index of a parameter on the stack
*
* @param procedure The procedure
* @param procedure The parameter
* @param programScope The program scope (used for finding/adding the constant).
* @return The constant variable
*/
public static ConstantRef getParameterOffsetConstant(Procedure procedure, Variable parameter, ProgramScope programScope) {
String paramOffsetConstantName = getParameterOffsetConstantName(parameter.getName());
ConstantVar paramOffsetConstant = procedure.getConstant(paramOffsetConstantName);
if(paramOffsetConstant == null) {
// Constant not found - create it
long paramByteOffset = getParameterByteOffset(procedure, parameter, programScope);
paramOffsetConstant = new ConstantVar(paramOffsetConstantName, procedure, SymbolType.BYTE, new ConstantInteger(paramByteOffset & 0xff, SymbolType.BYTE), Scope.SEGMENT_DATA_DEFAULT);
procedure.add(paramOffsetConstant);
}
return paramOffsetConstant.getRef();
}
/**
* Get the name of the constant variable containing the (byte) offset of a specific parameter on the stack
*
* @param parameterName The name of the struct member
* @return The name of the constant
*/
private static String getParameterOffsetConstantName(String parameterName) {
// TODO: Maybe use asmName?
return "OFFSET_STACK_" + parameterName.toUpperCase();
}
/**
* Get the number of bytes that a parameter is offset on the stack
*
* @param parameter The parameter to find offset for
* @return The byte offset of the start of the member data
*/
public static long getParameterByteOffset(Procedure procedure, Variable parameter, ProgramScope programScope) {
long byteOffset = 0;
for(Variable procedureParameter : procedure.getParameters()) {
if(parameter.equals(procedureParameter)) {
break;
} else {
// TODO: Consider hos passing a struct should handle inline arrays byteOffset += SymbolTypeStruct.getMemberSizeBytes(parameter.getType(), programScope);
byteOffset += parameter.getType().getSizeBytes();
}
}
return byteOffset;
}
}