1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-27 09:31:18 +00:00

Collecting SIZEOF/INDEXOF constants in one class. Dropping defunct struct pointer rewrite pass.

This commit is contained in:
jespergravgaard 2020-02-06 19:22:56 +01:00
parent 13ab7e8da3
commit a231b7495f
13 changed files with 125 additions and 264 deletions

View File

@ -195,7 +195,6 @@ public class Compiler {
new Pass1ConstantifyRValue(program).execute();
new Pass1UnwindStructVariables(program).execute();
new Pass1UnwindStructValues(program).execute();
new PassNStructPointerRewriting(program).execute();
new PassNAddBooleanCasts(program).execute();
new PassNAddTypeConversionAssignment(program, false).execute();
@ -301,7 +300,6 @@ public class Compiler {
optimizations.add(new Pass2ConditionalJumpSimplification(program));
optimizations.add(new Pass2ConditionalAndOrRewriting(program));
optimizations.add(new PassNAddBooleanCasts(program));
optimizations.add(new PassNStructPointerRewriting(program));
optimizations.add(new PassNStructUnwoundPlaceholderRemoval(program));
optimizations.add(new PassNArrayElementAddressOfRewriting(program));
optimizations.add(new Pass2ConditionalJumpSequenceImprovement(program));

View File

@ -1,15 +1,9 @@
package dk.camelot64.kickc.model.operators;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.Scope;
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.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantLiteral;
import dk.camelot64.kickc.model.values.ConstantRef;
import java.util.Locale;
/** SizeOf operator sizeof(expr). Will be resolved into a constant as soon as the expression has been resolved enough. */
public class OperatorSizeOf extends OperatorUnary {
@ -29,53 +23,4 @@ public class OperatorSizeOf extends OperatorUnary {
return SymbolType.BYTE;
}
/**
* Get the constant variable containing the size of a specific type
*
* @param programScope The program scope (used for finding/adding the constant).
* @param type The type to get the variable for
* @return The constant variable
*/
public static ConstantRef getSizeOfConstantVar(ProgramScope programScope, SymbolType type) {
String typeConstName = getSizeofConstantName(type);
Variable typeSizeConstant = programScope.getConstant(typeConstName);
if(typeSizeConstant == null) {
// Constant not found - create it
long typeSize = type.getSizeBytes();
typeSizeConstant = Variable.createConstant(typeConstName, SymbolType.BYTE, programScope, null, new ConstantInteger(typeSize&0xff, SymbolType.BYTE), Scope.SEGMENT_DATA_DEFAULT);
programScope.add(typeSizeConstant);
}
return typeSizeConstant.getConstantRef();
}
/**
* Fix the size value of the constant variable if needed.
* Sizes for structs and other complex types is not known until late in Pass1, so they may need fixing.
* @param programScope The program scope (used for finding/adding the constant).
* @param type The type to get the variable for
*/
public static void fixSizeOfConstantVar(ProgramScope programScope, SymbolType type) {
String typeConstName = getSizeofConstantName(type);
Variable typeSizeConstant = programScope.getConstant(typeConstName);
if(typeSizeConstant != null) {
// Constant found - update it
long typeSize = type.getSizeBytes();
typeSizeConstant.setInitValue(new ConstantInteger(typeSize&0xff, SymbolType.BYTE));
}
}
/**
* Get the name of the constant variable containing the size of a specific type
*
* @param type The type to get the variable for
* @return The name of the constant
*/
public static String getSizeofConstantName(SymbolType type) {
if(type instanceof SymbolTypePointer) {
return "SIZEOF_POINTER";
} else {
return "SIZEOF_" + type.getTypeName().toUpperCase(Locale.ENGLISH).replace(" ", "_");
}
}
}

View File

@ -14,6 +14,7 @@ import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.parser.CParser;
import dk.camelot64.kickc.parser.KickCParser;
import dk.camelot64.kickc.parser.KickCParserBaseVisitor;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import org.antlr.v4.runtime.BufferedTokenStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.ParserRuleContext;
@ -1723,7 +1724,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
if(ctx.typeDecl() != null) {
// sizeof(type) - add directly
SymbolType type = (SymbolType) this.visit(ctx.typeDecl());
return OperatorSizeOf.getSizeOfConstantVar(program.getScope(), type);
return SizeOfConstants.getSizeOfConstantVar(program.getScope(), type);
} else {
// sizeof(expression) - add a unary expression to be resolved later
RValue child = (RValue) this.visit(ctx.expr());

View File

@ -5,7 +5,6 @@ import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.OperatorSizeOf;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
@ -17,6 +16,7 @@ import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import java.util.LinkedHashMap;
import java.util.ListIterator;
@ -57,7 +57,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
SymbolTypePointer pointerType = getPointerType(binary.getLeft());
if(pointerType!=null && pointerType.getElementType().getSizeBytes() > 1) {
getLog().append("Fixing constant pointer addition " + binary.toString(getProgram()));
ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
ConstantRef sizeOfTargetType = SizeOfConstants.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
binary.setRight(new ConstantBinary(binary.getRight(), Operators.MULTIPLY, sizeOfTargetType));
}
}
@ -72,7 +72,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
if(idx2VarRef == null) {
Variable idx2Var = getScope().getScope(currentBlock.getScope()).addVariableIntermediate();
idx2Var.setType(SymbolTypeInference.inferType(getScope(), deref.getIndex()));
ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
ConstantRef sizeOfTargetType = SizeOfConstants.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
StatementAssignment idx2 = new StatementAssignment((LValue) idx2Var.getRef(), deref.getIndex(), Operators.MULTIPLY, sizeOfTargetType, true, currentStmt.getSource(), Comment.NO_COMMENTS);
stmtIt.previous();
stmtIt.add(idx2);
@ -116,7 +116,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
Variable tmpVar = getScope().getScope(block.getScope()).addVariableIntermediate();
tmpVar.setType(SymbolTypeInference.inferType(getScope(), assignment.getlValue()));
assignment.setlValue((LValue) tmpVar.getRef());
ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
ConstantRef sizeOfTargetType = SizeOfConstants.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
stmtIt.add(new StatementAssignment(lValue, tmpVar.getRef(), Operators.DIVIDE, sizeOfTargetType, assignment.isInitialAssignment(), assignment.getSource(), Comment.NO_COMMENTS));
}
}
@ -128,7 +128,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
Variable tmpVar = getScope().getScope(block.getScope()).addVariableIntermediate();
tmpVar.setType(SymbolTypeInference.inferType(getScope(), assignment.getrValue2()));
stmtIt.remove();
ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
ConstantRef sizeOfTargetType = SizeOfConstants.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
stmtIt.add(new StatementAssignment((LValue) tmpVar.getRef(), assignment.getrValue2(), Operators.MULTIPLY, sizeOfTargetType, true, assignment.getSource(), Comment.NO_COMMENTS));
stmtIt.add(assignment);
assignment.setrValue2(tmpVar.getRef());
@ -159,13 +159,13 @@ public class Pass1PointerSizeofFix extends Pass1Base {
getLog().append("Fixing pointer increment " + assignment.toString(getProgram(), false));
assignment.setrValue1(assignment.getrValue2());
assignment.setOperator(Operators.PLUS);
assignment.setrValue2(OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()));
assignment.setrValue2(SizeOfConstants.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()));
} else if(Operators.DECREMENT.equals(assignment.getOperator())) {
// Pointer Decrement - add sizeof(type) instead
getLog().append("Fixing pointer decrement " + assignment.toString(getProgram(), false));
assignment.setrValue1(assignment.getrValue2());
assignment.setOperator(Operators.MINUS);
assignment.setrValue2(OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()));
assignment.setrValue2(SizeOfConstants.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()));
}
}
}

View File

@ -1,13 +1,13 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.OperatorSizeOf;
import dk.camelot64.kickc.model.symbols.Scope;
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.types.SymbolTypeStruct;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
/**
* Fixes byte-size of all struct types. (which may be a bit off if struct types are referenced before being parsed completely)
@ -36,7 +36,7 @@ public class Pass1StructTypeSizeFix extends Pass2SsaOptimization {
if(sizeBytes != typeStruct.getSizeBytes()) {
getLog().append("Fixing struct type SIZE_OF " + typeStruct.getTypeName() + " to " + sizeBytes);
typeStruct.setSizeBytes(sizeBytes);
OperatorSizeOf.fixSizeOfConstantVar(getScope(), typeStruct);
SizeOfConstants.fixSizeOfConstantVar(getScope(), typeStruct);
}
}
}

View File

@ -7,13 +7,13 @@ import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueHandler;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.OperatorSizeOf;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.*;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.calcs.PassNCalcVariableReferenceInfos;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import java.io.File;
import java.util.*;
@ -600,7 +600,7 @@ public class Pass4CodeGeneration {
}
} else if(value instanceof StructZero) {
final SymbolTypeStruct typeStruct = ((StructZero) value).getTypeStruct();
final ConstantRef structSize = OperatorSizeOf.getSizeOfConstantVar(getScope(), typeStruct);
final ConstantRef structSize = SizeOfConstants.getSizeOfConstantVar(getScope(), typeStruct);
String totalSizeBytesAsm = AsmFormat.getAsmConstant(program, structSize, 99, scopeRef);
int totalSizeBytes = typeStruct.getSizeBytes();
dataChunk.addDataFilled(AsmDataNumeric.Type.BYTE, totalSizeBytesAsm, totalSizeBytes, "0", null);

View File

@ -6,7 +6,6 @@ import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.OperatorSizeOf;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
@ -14,6 +13,7 @@ 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.utils.SizeOfConstants;
import java.util.concurrent.atomic.AtomicBoolean;
@ -41,7 +41,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
SymbolType symbolType = symbolVar.getType();
if(!(symbolVar.isArray())) {
getLog().append("Resolving sizeof() " + assignment.toString(getProgram(), false));
ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), symbolType);
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getScope(), symbolType);
assignment.setrValue2(sizeOfConstantVar);
assignment.setOperator(null);
modified.set(true);
@ -75,13 +75,13 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
ConstantValue arraySize = constant.getArraySize();
if(arraySize!=null) {
getLog().append("Resolving array sizeof() " + unary.toString(getProgram()));
ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType());
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getScope(), arrayType.getElementType());
programValue.set(new ConstantBinary((ConstantValue) arraySize, Operators.MULTIPLY, sizeOfConstantVar));
modified.set(true);
} else if(constant.getInitValue() instanceof ConstantArrayList) {
getLog().append("Resolving array sizeof() " + unary.toString(getProgram()));
int size = ((ConstantArrayList) constant.getInitValue()).getElements().size();
ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType());
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getScope(), arrayType.getElementType());
programValue.set(new ConstantBinary(new ConstantInteger((long) size), Operators.MULTIPLY, sizeOfConstantVar));
modified.set(true);
} else {
@ -96,7 +96,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
ConstantString constString = (ConstantString) stringLiteral;
int length = constString.getStringLength();
getLog().append("Resolving string sizeof() " + unary.toString(getProgram()));
ConstantRef sizeOfChar = OperatorSizeOf.getSizeOfConstantVar(getScope(), SymbolType.BYTE);
ConstantRef sizeOfChar = SizeOfConstants.getSizeOfConstantVar(getScope(), SymbolType.BYTE);
programValue.set(new ConstantBinary(new ConstantInteger((long) length), Operators.MULTIPLY, sizeOfChar));
modified.set(true);
} else {
@ -105,14 +105,14 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
}
} else if(symbolType instanceof SymbolTypePointer ){
getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), symbolType);
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getScope(), symbolType);
programValue.set(sizeOfConstantVar);
modified.set(true);
} else {
getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
ConstantLiteral literal = operand.calculateLiteral(getProgram().getScope());
SymbolType constType = literal.getType(getProgram().getScope());
ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), constType);
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getScope(), constType);
programValue.set(sizeOfConstantVar);
modified.set(true);
}
@ -120,7 +120,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
ConstantLiteral literal = operand.calculateLiteral(getProgram().getScope());
SymbolType constType = literal.getType(getProgram().getScope());
ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), constType);
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getScope(), constType);
programValue.set(sizeOfConstantVar);
modified.set(true);
}

View File

@ -1,179 +0,0 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.*;
import dk.camelot64.kickc.model.values.*;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Rewrite access to member of dereferenced struct (*ptr_struct).x to reference the member directly *((*typeof_x)(ptr_struct+OFFSET_STRUCT_AAA_X))
*/
public class PassNStructPointerRewriting extends Pass2SsaOptimization {
public PassNStructPointerRewriting(Program program) {
super(program);
}
@Override
public boolean step() {
AtomicBoolean modified = new AtomicBoolean(false);
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
if(programValue.get() instanceof StructMemberRef) {
StructMemberRef structMemberRef = (StructMemberRef) programValue.get();
RValue struct = structMemberRef.getStruct();
if(struct instanceof PointerDereferenceSimple) {
RValue structPointer = ((PointerDereferenceSimple) struct).getPointer();
// We have a match for (*ptr_struct).x
SymbolType structType = SymbolTypeInference.inferType(getScope(), struct);
if(!(structType instanceof SymbolTypeStruct)) {
throw new CompileError("Accessing member of a non-struct ", currentStmt.getSource());
}
StructDefinition structDefinition = ((SymbolTypeStruct) structType).getStructDefinition(getScope());
ConstantRef memberOffsetConstant = getMemberOffsetConstant(getScope(), structDefinition, structMemberRef.getMemberName());
SymbolType memberType = SymbolTypeInference.inferType(getScope(), structMemberRef);
Variable memberVar = structDefinition.getMember(structMemberRef.getMemberName());
getLog().append("Rewriting struct pointer member access " + programValue.get().toString(getProgram()));
if(memberVar.isArray() && memberVar.getArraySize()!=null) {
// Cast struct pointer to the type of the member
CastValue structTypedPointer = new CastValue(memberType, structPointer);
// Create temporary variable to hold pointer to member ($1)
Scope scope = getScope().getScope(currentBlock.getScope());
Variable memberAddress1 = scope.addVariableIntermediate();
memberAddress1.setType(memberType);
// Add statement $1 = ptr_struct + OFFSET_STRUCT_NAME_MEMBER
stmtIt.previous();
stmtIt.add(new StatementAssignment((LValue) memberAddress1.getRef(), structTypedPointer, Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
stmtIt.next();
// Replace (*ptr_struct).x with *($1)
programValue.set(memberAddress1.getRef());
} else {
// Cast struct pointer to the type of the member
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(memberType), structPointer);
// Create temporary variable to hold pointer to member ($1)
Scope scope = getScope().getScope(currentBlock.getScope());
Variable memberAddress = scope.addVariableIntermediate();
memberAddress.setType(new SymbolTypePointer(memberType));
// Add statement $1 = ptr_struct + OFFSET_STRUCT_NAME_MEMBER
stmtIt.previous();
stmtIt.add(new StatementAssignment((LValue) memberAddress.getRef(), structTypedPointer, Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
stmtIt.next();
// Replace (*ptr_struct).x with *($1)
programValue.set(new PointerDereferenceSimple(memberAddress.getRef()));
}
modified.set(true);
} else if(struct instanceof PointerDereferenceIndexed) {
RValue structPointer = ((PointerDereferenceIndexed) struct).getPointer();
// We have a match for ptr_struct[idx].x
SymbolType structType = SymbolTypeInference.inferType(getScope(), struct);
if(!(structType instanceof SymbolTypeStruct)) {
throw new CompileError("Accessing member of a non-struct ", currentStmt.getSource());
}
StructDefinition structDefinition = ((SymbolTypeStruct) structType).getStructDefinition(getScope());
ConstantRef memberOffsetConstant = getMemberOffsetConstant(getScope(), structDefinition, structMemberRef.getMemberName());
SymbolType memberType = SymbolTypeInference.inferType(getScope(), structMemberRef);
Variable memberVar = structDefinition.getMember(structMemberRef.getMemberName());
getLog().append("Rewriting struct pointer member access " + programValue.get().toString(getProgram()));
if(memberVar.isArray() && memberVar.getArraySize()!=null) {
// Cast struct pointer to the type of the member
CastValue structTypedPointer = new CastValue(memberType, structPointer);
// Create temporary variable to hold pointer to member ($1)
Scope scope = getScope().getScope(currentBlock.getScope());
Variable memberAddress1 = scope.addVariableIntermediate();
memberAddress1.setType(memberType);
Variable memberAddress2 = scope.addVariableIntermediate();
memberAddress2.setType(memberType);
// Add statement $1 = ptr_struct + OFFSET_STRUCT_NAME_MEMBER
stmtIt.previous();
stmtIt.add(new StatementAssignment((LValue) memberAddress1.getRef(), structTypedPointer, Operators.PLUS, ((PointerDereferenceIndexed) struct).getIndex(), true, currentStmt.getSource(), currentStmt.getComments()));
stmtIt.add(new StatementAssignment((LValue) memberAddress2.getRef(), memberAddress1.getRef(), Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
stmtIt.next();
// Replace ptr_struct[idx].x with ($1)[idx]
programValue.set(memberAddress2.getRef());
//throw new InternalError("Fixed size arrays not supported inside structs used through pointers/arrays", currentStmt);
} else {
// Cast struct pointer to the type of the member
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(memberType), structPointer);
// Create temporary variable to hold pointer to member ($1)
Scope scope = getScope().getScope(currentBlock.getScope());
Variable memberAddress = scope.addVariableIntermediate();
memberAddress.setType(new SymbolTypePointer(memberType));
// Add statement $1 = ptr_struct + OFFSET_STRUCT_NAME_MEMBER
stmtIt.previous();
stmtIt.add(new StatementAssignment((LValue) memberAddress.getRef(), structTypedPointer, Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
stmtIt.next();
// Replace ptr_struct[idx].x with ($1)[idx]
programValue.set(new PointerDereferenceIndexed(memberAddress.getRef(), ((PointerDereferenceIndexed) struct).getIndex()));
}
modified.set(true);
} else if(struct instanceof SymbolVariableRef) {
Variable structVar = getScope().getVar((SymbolVariableRef) struct);
if(structVar.isStructClassic()) {
SymbolType structType = SymbolTypeInference.inferType(getScope(), struct);
if(!(structType instanceof SymbolTypeStruct)) {
throw new CompileError("Accessing member of a non-struct ", currentStmt.getSource());
}
StructDefinition structDefinition = ((SymbolTypeStruct) structType).getStructDefinition(getScope());
ConstantRef memberOffsetConstant = getMemberOffsetConstant(getScope(), structDefinition, structMemberRef.getMemberName());
SymbolType memberType = SymbolTypeInference.inferType(getScope(), structMemberRef);
Variable memberVar = structDefinition.getMember(structMemberRef.getMemberName());
getLog().append("Rewriting struct member access " + programValue.get().toString(getProgram()));
// Cast struct pointer to the type of the member
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(memberType), new ConstantSymbolPointer(structVar.getRef()));
// Create temporary variable to hold pointer to member ($1)
Scope scope = getScope().getScope(currentBlock.getScope());
Variable memberAddress = scope.addVariableIntermediate();
memberAddress.setType(new SymbolTypePointer(memberType));
// Add statement $1 = ptr_struct + OFFSET_STRUCT_NAME_MEMBER
stmtIt.previous();
stmtIt.add(new StatementAssignment((LValue) memberAddress.getRef(), structTypedPointer, Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
stmtIt.next();
// Replace struct.x with *($1)
programValue.set(new PointerDereferenceSimple(memberAddress.getRef()));
}
}
}
});
return modified.get();
}
/**
* Get the constant variable containing the (byte) index of a specific member
*
* @param programScope The program scope (used for finding/adding the constant).
* @param structDefinition The struct
* @param memberName The name of the struct member
* @return The constant variable
*/
public static ConstantRef getMemberOffsetConstant(ProgramScope programScope, StructDefinition structDefinition, String memberName) {
String typeConstName = getMemberOffsetConstantName(structDefinition, memberName);
Variable memberOffsetConstant = programScope.getConstant(typeConstName);
if(memberOffsetConstant == null) {
// Constant not found - create it
Variable memberDef = structDefinition.getMember(memberName);
long memberByteOffset = structDefinition.getMemberByteOffset(memberDef, programScope);
memberOffsetConstant = Variable.createConstant(typeConstName, SymbolType.BYTE, programScope, null, new ConstantInteger(memberByteOffset & 0xff, SymbolType.BYTE), Scope.SEGMENT_DATA_DEFAULT);
programScope.add(memberOffsetConstant);
}
return memberOffsetConstant.getConstantRef();
}
/**
* Get the name of the constant variable containing the (byte) index of a specific member in a struct
*
* @param structDefinition The struct
* @param memberName The name of the struct member
* @return The name of the constant
*/
private static String getMemberOffsetConstantName(StructDefinition structDefinition, String memberName) {
return "OFFSET_" + structDefinition.getType().getTypeName().toUpperCase(Locale.ENGLISH).replace(" ", "_") + "_" + memberName.toUpperCase();
}
}

View File

@ -1,11 +1,11 @@
package dk.camelot64.kickc.passes.unwinding;
import dk.camelot64.kickc.model.operators.OperatorSizeOf;
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.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import java.util.ArrayList;
import java.util.Collection;
@ -36,7 +36,7 @@ public abstract class ValueSourceBase implements ValueSource {
}
protected ConstantValue getByteSize(ProgramScope scope) {
return getArraySpec() != null ? getArraySpec().getArraySize() : OperatorSizeOf.getSizeOfConstantVar(scope, getSymbolType());
return getArraySpec() != null ? getArraySpec().getArraySize() : SizeOfConstants.getSizeOfConstantVar(scope, getSymbolType());
}
@Override

View File

@ -11,7 +11,7 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.PassNStructPointerRewriting;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import java.util.ListIterator;
@ -72,7 +72,7 @@ public class ValueSourcePointerDereferenceIndexed extends ValueSourceBase {
StructDefinition structDefinition = ((SymbolTypeStruct) getSymbolType()).getStructDefinition(programScope);
final SymbolType memberType = structDefinition.getMember(memberName).getType();
final ArraySpec memberArraySpec = structDefinition.getMember(memberName).getArraySpec();
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
ConstantRef memberOffsetConstant = SizeOfConstants.getStructMemberOffsetConstant(programScope, structDefinition, memberName);
// Simple member value - unwind to value of member *((type*)&struct + OFFSET_MEMBER)
final RValue structPointer = pointerDereferenceIndexed.getPointer();
if(structPointer instanceof ConstantValue) {

View File

@ -10,7 +10,7 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.PassNStructPointerRewriting;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import java.util.ListIterator;
@ -65,7 +65,7 @@ public class ValueSourcePointerDereferenceSimple extends ValueSourceBase {
StructDefinition structDefinition = ((SymbolTypeStruct) getSymbolType()).getStructDefinition(programScope);
final SymbolType memberType = structDefinition.getMember(memberName).getType();
final ArraySpec memberArraySpec = structDefinition.getMember(memberName).getArraySpec();
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
ConstantRef memberOffsetConstant = SizeOfConstants.getStructMemberOffsetConstant(programScope, structDefinition, memberName);
// Simple member value - unwind to value of member *((type*)&struct + OFFSET_MEMBER)
final RValue structPointer = pointerDereference.getPointer();
if(structPointer instanceof ConstantValue) {

View File

@ -14,7 +14,7 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.PassNStructPointerRewriting;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import java.util.ListIterator;
@ -73,7 +73,7 @@ public class ValueSourceVariable extends ValueSourceBase {
StructDefinition structDefinition = ((SymbolTypeStruct) getSymbolType()).getStructDefinition(programScope);
SymbolType memberType = structDefinition.getMember(memberName).getType();
ArraySpec memberArraySpec = structDefinition.getMember(memberName).getArraySpec();
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
ConstantRef memberOffsetConstant = SizeOfConstants.getStructMemberOffsetConstant(programScope, structDefinition, memberName);
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(variable.getRef());
if(memberArraySpec != null) {
// Pointer to member element type (elmtype*)&struct

View File

@ -0,0 +1,96 @@
package dk.camelot64.kickc.passes.utils;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.Scope;
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.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantRef;
import java.util.Locale;
/** Handler for SIZEOF and OFFSET constants. */
public class SizeOfConstants {
/**
* Get the constant variable containing the size of a specific type
*
* @param programScope The program scope (used for finding/adding the constant).
* @param type The type to get the variable for
* @return The constant variable
*/
public static ConstantRef getSizeOfConstantVar(ProgramScope programScope, SymbolType type) {
String typeConstName = getSizeofConstantName(type);
Variable typeSizeConstant = programScope.getConstant(typeConstName);
if(typeSizeConstant == null) {
// Constant not found - create it
long typeSize = type.getSizeBytes();
typeSizeConstant = Variable.createConstant(typeConstName, SymbolType.BYTE, programScope, null, new ConstantInteger(typeSize&0xff, SymbolType.BYTE), Scope.SEGMENT_DATA_DEFAULT);
programScope.add(typeSizeConstant);
}
return typeSizeConstant.getConstantRef();
}
/**
* Fix the size value of the constant variable if needed.
* Sizes for structs and other complex types is not known until late in Pass1, so they may need fixing.
* @param programScope The program scope (used for finding/adding the constant).
* @param type The type to get the variable for
*/
public static void fixSizeOfConstantVar(ProgramScope programScope, SymbolType type) {
String typeConstName = getSizeofConstantName(type);
Variable typeSizeConstant = programScope.getConstant(typeConstName);
if(typeSizeConstant != null) {
// Constant found - update it
long typeSize = type.getSizeBytes();
typeSizeConstant.setInitValue(new ConstantInteger(typeSize&0xff, SymbolType.BYTE));
}
}
/**
* Get the name of the constant variable containing the size of a specific type
*
* @param type The type to get the variable for
* @return The name of the constant
*/
public static String getSizeofConstantName(SymbolType type) {
if(type instanceof SymbolTypePointer) {
return "SIZEOF_POINTER";
} else {
return "SIZEOF_" + type.getTypeName().toUpperCase(Locale.ENGLISH).replace(" ", "_");
}
}
/**
* Get the constant variable containing the (byte) index of a specific member
*
* @param programScope The program scope (used for finding/adding the constant).
* @param structDefinition The struct
* @param memberName The name of the struct member
* @return The constant variable
*/
public static ConstantRef getStructMemberOffsetConstant(ProgramScope programScope, StructDefinition structDefinition, String memberName) {
String typeConstName = getStructMemberOffsetConstantName(structDefinition, memberName);
Variable memberOffsetConstant = programScope.getConstant(typeConstName);
if(memberOffsetConstant == null) {
// Constant not found - create it
Variable memberDef = structDefinition.getMember(memberName);
long memberByteOffset = structDefinition.getMemberByteOffset(memberDef, programScope);
memberOffsetConstant = Variable.createConstant(typeConstName, SymbolType.BYTE, programScope, null, new ConstantInteger(memberByteOffset & 0xff, SymbolType.BYTE), Scope.SEGMENT_DATA_DEFAULT);
programScope.add(memberOffsetConstant);
}
return memberOffsetConstant.getConstantRef();
}
/**
* Get the name of the constant variable containing the (byte) index of a specific member in a struct
*
* @param structDefinition The struct
* @param memberName The name of the struct member
* @return The name of the constant
*/
private static String getStructMemberOffsetConstantName(StructDefinition structDefinition, String memberName) {
return "OFFSET_" + structDefinition.getType().getTypeName().toUpperCase(Locale.ENGLISH).replace(" ", "_") + "_" + memberName.toUpperCase();
}
}