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:
parent
13ab7e8da3
commit
a231b7495f
@ -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));
|
||||
|
@ -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(" ", "_");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user