From a231b7495ff2e288c8fbdfe03f8ebf847fe0b68d Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Thu, 6 Feb 2020 19:22:56 +0100 Subject: [PATCH] Collecting SIZEOF/INDEXOF constants in one class. Dropping defunct struct pointer rewrite pass. --- .../java/dk/camelot64/kickc/Compiler.java | 2 - .../kickc/model/operators/OperatorSizeOf.java | 55 ------ .../Pass0GenerateStatementSequence.java | 3 +- .../kickc/passes/Pass1PointerSizeofFix.java | 14 +- .../kickc/passes/Pass1StructTypeSizeFix.java | 4 +- .../kickc/passes/Pass4CodeGeneration.java | 4 +- .../passes/PassNSizeOfSimplification.java | 16 +- .../passes/PassNStructPointerRewriting.java | 179 ------------------ .../passes/unwinding/ValueSourceBase.java | 4 +- .../ValueSourcePointerDereferenceIndexed.java | 4 +- .../ValueSourcePointerDereferenceSimple.java | 4 +- .../passes/unwinding/ValueSourceVariable.java | 4 +- .../kickc/passes/utils/SizeOfConstants.java | 96 ++++++++++ 13 files changed, 125 insertions(+), 264 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNStructPointerRewriting.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/utils/SizeOfConstants.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 88ff0411f..8570c8d43 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -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)); diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java index 3a4a58e29..ad449cb55 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java @@ -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(" ", "_"); - } - } - } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 149d4a687..e739e80c2 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -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 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())); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1StructTypeSizeFix.java b/src/main/java/dk/camelot64/kickc/passes/Pass1StructTypeSizeFix.java index b64717547..0471b5ed7 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1StructTypeSizeFix.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1StructTypeSizeFix.java @@ -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); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 26e3cc51d..c3c2258ac 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -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); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java index 19925349f..1249ae066 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNSizeOfSimplification.java @@ -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); } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNStructPointerRewriting.java b/src/main/java/dk/camelot64/kickc/passes/PassNStructPointerRewriting.java deleted file mode 100644 index b6f502861..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/PassNStructPointerRewriting.java +++ /dev/null @@ -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(); - } - - -} diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceBase.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceBase.java index c645c0838..994eac145 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceBase.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceBase.java @@ -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 diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourcePointerDereferenceIndexed.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourcePointerDereferenceIndexed.java index 1a8cf7585..a9f7eba11 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourcePointerDereferenceIndexed.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourcePointerDereferenceIndexed.java @@ -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) { diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourcePointerDereferenceSimple.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourcePointerDereferenceSimple.java index 7d411bb18..da63677d9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourcePointerDereferenceSimple.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourcePointerDereferenceSimple.java @@ -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) { diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceVariable.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceVariable.java index 61818bbe8..60247a122 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceVariable.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceVariable.java @@ -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 diff --git a/src/main/java/dk/camelot64/kickc/passes/utils/SizeOfConstants.java b/src/main/java/dk/camelot64/kickc/passes/utils/SizeOfConstants.java new file mode 100644 index 000000000..8e9ec0468 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/utils/SizeOfConstants.java @@ -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(); + } +}