diff --git a/src/main/java/dk/camelot64/kickc/model/Comment.java b/src/main/java/dk/camelot64/kickc/model/Comment.java index 8da6dd278..ec22c0c4b 100644 --- a/src/main/java/dk/camelot64/kickc/model/Comment.java +++ b/src/main/java/dk/camelot64/kickc/model/Comment.java @@ -14,9 +14,6 @@ public class Comment implements Serializable { /** Empty comments collection. */ public static final ArrayList NO_COMMENTS = new ArrayList<>(); - /** Special comment used for constructor calls in __init(). */ - public static final Comment CONSTRUCTOR = new Comment("#pragma constructor"); - /** The comment. */ private String comment; diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java b/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java index a1a4c6e8a..3951a05cf 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java @@ -32,6 +32,8 @@ public class Procedure extends Scope { private final String codeSegment; /** The list of constructor procedures for this procedure. The constructor procedures are called during program initialization. */ private final List constructorRefs; + /** Is this procedure declared as a constructor procedure. */ + private boolean isConstructor; /** The names of all legal intrinsic procedures. */ final public static List INTRINSIC_PROCEDURES = Collections.singletonList(Pass1PrintfIntrinsicRewrite.INTRINSIC_PRINTF_NAME); @@ -76,6 +78,7 @@ public class Procedure extends Scope { this.codeSegment = codeSegment; this.callingConvention = callingConvention; this.constructorRefs = new ArrayList<>(); + this.isConstructor = false; } public CallingConvention getCallingConvention() { @@ -205,6 +208,13 @@ public class Procedure extends Scope { return constructorRefs; } + public boolean isConstructor() { + return isConstructor; + } + + public void setConstructor(boolean constructor) { + isConstructor = constructor; + } /** The different types of supported interrupts. */ public enum InterruptType { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index bc8b14362..e9a48d7b1 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -150,7 +150,9 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor(), new StatementSource(pragmaConstructorFor), Collections.singletonList(Comment.CONSTRUCTOR))); + addStatement(new StatementCall(null, constructorProc.getLocalName(), new ArrayList<>(), new StatementSource(pragmaConstructorFor), Comment.NO_COMMENTS)); + // Mark the constructor procedure + constructorProc.setConstructor(true); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedConstructors.java b/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedConstructors.java index 94ae384ef..82f226133 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedConstructors.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedConstructors.java @@ -1,6 +1,5 @@ package dk.camelot64.kickc.passes; -import dk.camelot64.kickc.model.Comment; import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; @@ -36,11 +35,14 @@ public class PassNEliminateUnusedConstructors extends Pass2SsaOptimization { final List startProcBlocks = getGraph().getScopeBlocks(startProc.getRef()); for(ControlFlowBlock block : startProcBlocks) { for(Statement statement : block.getStatements()) { - if(statement instanceof StatementCalling && statement.getComments().size() == 1 && statement.getComments().get(0).equals(Comment.CONSTRUCTOR)) { - // This is a constructor call! - final ProcedureRef constructorRef = ((StatementCalling) statement).getProcedure(); - if(!allConstructors.contains(constructorRef)) { - unusedConstructors.add(constructorRef); + if(statement instanceof StatementCalling) { + final ProcedureRef procedureRef = ((StatementCalling) statement).getProcedure(); + final Procedure procedure = getScope().getProcedure(procedureRef); + if(procedure.isConstructor()) { + // This is a constructor call! + if(!allConstructors.contains(procedureRef)) { + unusedConstructors.add(procedureRef); + } } } } @@ -48,6 +50,7 @@ public class PassNEliminateUnusedConstructors extends Pass2SsaOptimization { // Remove all calls to unused constructors for(ProcedureRef unusedConstructor : unusedConstructors) { removeAllCalls(unusedConstructor, startProcBlocks); + optimized = true; } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 2b3031f24..73c6d056b 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -58,13 +58,13 @@ public class TestPrograms { } @Test - public void testLibraryConstructor2() throws IOException, URISyntaxException { - compileAndCompare("library-constructor-2.c"); + public void testLibraryConstructor3() throws IOException, URISyntaxException { + compileAndCompare("library-constructor-3.c"); } @Test - public void testLibraryConstructor3() throws IOException, URISyntaxException { - compileAndCompare("library-constructor-3.c", log()); + public void testLibraryConstructor2() throws IOException, URISyntaxException { + compileAndCompare("library-constructor-2.c"); } @Test diff --git a/src/test/ref/library-constructor-1.asm b/src/test/ref/library-constructor-1.asm index d277c9c05..955235414 100644 --- a/src/test/ref/library-constructor-1.asm +++ b/src/test/ref/library-constructor-1.asm @@ -10,7 +10,6 @@ __start: { lda #0 sta.z my_value // #pragma constructor_for(my_init, print) - //#pragma constructor jsr my_init jsr main rts diff --git a/src/test/ref/library-constructor-1.log b/src/test/ref/library-constructor-1.log index f661f5b4b..f739c8b52 100644 --- a/src/test/ref/library-constructor-1.log +++ b/src/test/ref/library-constructor-1.log @@ -162,7 +162,6 @@ __start: { lda #0 sta.z my_value // [2] call my_init - //#pragma constructor jsr my_init // [3] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] __b1_from___init1: @@ -254,7 +253,6 @@ __start: { lda #0 sta.z my_value // [2] call my_init - //#pragma constructor jsr my_init // [3] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] __b1_from___init1: @@ -363,7 +361,6 @@ __start: { sta.z my_value // #pragma constructor_for(my_init, print) // [2] call my_init - //#pragma constructor jsr my_init // [3] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] // __start::@1 diff --git a/src/test/ref/library-constructor-2.log b/src/test/ref/library-constructor-2.log index 9dee3238a..512cf92c4 100644 --- a/src/test/ref/library-constructor-2.log +++ b/src/test/ref/library-constructor-2.log @@ -62,6 +62,7 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions Simplifying expression containing zero SCREEN in [0] *((const nomodify byte*) SCREEN + (byte) 0) ← (byte) '*' Successful SSA optimization PassNSimplifyExpressionWithZero Removing call to constructor procedure [4] call my_init +Successful SSA optimization PassNEliminateUnusedConstructors Removing unused procedure my_init Removing unused procedure block my_init Removing unused procedure block my_init::@return diff --git a/src/test/ref/library-constructor-3.asm b/src/test/ref/library-constructor-3.asm index e78abbf52..a1f82061d 100644 --- a/src/test/ref/library-constructor-3.asm +++ b/src/test/ref/library-constructor-3.asm @@ -13,10 +13,8 @@ __start: { sta.z SCREEN sta.z SCREEN+1 // #pragma constructor_for(init_1, print) - //#pragma constructor jsr init_1 // #pragma constructor_for(init_2, print) - //#pragma constructor jsr init_2 jsr main rts diff --git a/src/test/ref/library-constructor-3.log b/src/test/ref/library-constructor-3.log index 46b706613..3e4f7107e 100644 --- a/src/test/ref/library-constructor-3.log +++ b/src/test/ref/library-constructor-3.log @@ -204,7 +204,6 @@ __start: { lda #>0 sta.z SCREEN+1 // [3] call init_1 - //#pragma constructor jsr init_1 // [4] phi from __start::__init1 to __start::@2 [phi:__start::__init1->__start::@2] __b2_from___init1: @@ -212,7 +211,6 @@ __start: { // __start::@2 __b2: // [5] call init_2 - //#pragma constructor jsr init_2 // [6] phi from __start::@2 to __start::@1 [phi:__start::@2->__start::@1] __b1_from___b2: @@ -328,7 +326,6 @@ __start: { lda #>0 sta.z SCREEN+1 // [3] call init_1 - //#pragma constructor jsr init_1 // [4] phi from __start::__init1 to __start::@2 [phi:__start::__init1->__start::@2] __b2_from___init1: @@ -336,7 +333,6 @@ __start: { // __start::@2 __b2: // [5] call init_2 - //#pragma constructor jsr init_2 // [6] phi from __start::@2 to __start::@1 [phi:__start::@2->__start::@1] __b1_from___b2: @@ -475,13 +471,11 @@ __start: { sta.z SCREEN+1 // #pragma constructor_for(init_1, print) // [3] call init_1 - //#pragma constructor jsr init_1 // [4] phi from __start::__init1 to __start::@2 [phi:__start::__init1->__start::@2] // __start::@2 // #pragma constructor_for(init_2, print) // [5] call init_2 - //#pragma constructor jsr init_2 // [6] phi from __start::@2 to __start::@1 [phi:__start::@2->__start::@1] // __start::@1