1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-26 12:49:21 +00:00

Added NULL pointer to standard library. Closes #647

This commit is contained in:
jespergravgaard 2021-08-02 22:30:04 +02:00
parent 8b69a1f583
commit bc0fcc50fd
17 changed files with 705 additions and 3 deletions

View File

@ -15573,3 +15573,188 @@ sta {z1}
bcc !+
inc {z1}+1
!:
//FRAGMENT vbum1=vbum2_rol_5
lda {m2}
asl
asl
asl
asl
asl
sta {m1}
//FRAGMENT vbum1=vbum2_rol_1
lda {m2}
asl
sta {m1}
//FRAGMENT _deref_pssc1=pssc2_derefidx_vbum1_memcpy_vbuc3
ldx {m1}
ldy #0
!:
lda {c2},x
sta {c1},y
inx
iny
cpy #{c3}
bne !-
//FRAGMENT pbuc1_derefidx_vbum1=_deref_pbuc2
lda {c2}
ldy {m1}
sta {c1},y
//FRAGMENT vbum1=vbuaa_rol_5
asl
asl
asl
asl
asl
sta {m1}
//FRAGMENT vbum1=vbuxx_rol_5
txa
asl
asl
asl
asl
asl
sta {m1}
//FRAGMENT vbum1=vbuyy_rol_5
tya
asl
asl
asl
asl
asl
sta {m1}
//FRAGMENT vbuaa=vbum1_rol_5
lda {m1}
asl
asl
asl
asl
asl
//FRAGMENT vbuaa=vbuaa_rol_5
asl
asl
asl
asl
asl
//FRAGMENT vbuaa=vbuxx_rol_5
txa
asl
asl
asl
asl
asl
//FRAGMENT vbuaa=vbuyy_rol_5
tya
asl
asl
asl
asl
asl
//FRAGMENT vbuxx=vbum1_rol_5
lda {m1}
asl
asl
asl
asl
asl
tax
//FRAGMENT vbuxx=vbuaa_rol_5
asl
asl
asl
asl
asl
tax
//FRAGMENT vbuxx=vbuxx_rol_5
txa
asl
asl
asl
asl
asl
tax
//FRAGMENT vbuxx=vbuyy_rol_5
tya
asl
asl
asl
asl
asl
tax
//FRAGMENT vbuyy=vbum1_rol_5
lda {m1}
asl
asl
asl
asl
asl
tay
//FRAGMENT vbuyy=vbuaa_rol_5
asl
asl
asl
asl
asl
tay
//FRAGMENT vbuyy=vbuxx_rol_5
txa
asl
asl
asl
asl
asl
tay
//FRAGMENT vbuyy=vbuyy_rol_5
tya
asl
asl
asl
asl
asl
tay
//FRAGMENT vbum1=vbuaa_rol_1
asl
sta {m1}
//FRAGMENT vbum1=vbuxx_rol_1
txa
asl
sta {m1}
//FRAGMENT vbum1=vbuyy_rol_1
tya
asl
sta {m1}
//FRAGMENT vbuaa=vbum1_rol_1
lda {m1}
asl
//FRAGMENT vbuxx=vbum1_rol_1
lda {m1}
asl
tax
//FRAGMENT vbuyy=vbum1_rol_1
lda {m1}
asl
tay
//FRAGMENT pbuz1=qbuz2_derefidx_vbuc1
ldy #{c1}
lda ({z2}),y
sta {z1}
iny
lda ({z2}),y
sta {z1}+1
//FRAGMENT vwuz1=pwuz2_derefidx_vbuc1
ldy #{c1}
lda ({z2}),y
sta {z1}
iny
lda ({z2}),y
sta {z1}+1
//FRAGMENT _deref_(_deref_qbuz1)=vbuc1
lda #{c1}
pha
ldy #1
lda ({z1}),y
sta $ff
dey
lda ({z1}),y
sta $fe
pla
sta ($fe),y

View File

@ -18,6 +18,7 @@ import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeConversion;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.utils.VarAssignments;
@ -57,7 +58,10 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
continue;
}
if(!SymbolTypeConversion.assignmentTypeMatch(variableType, valueType)) {
if(variableType instanceof SymbolTypePointer && constVal instanceof ConstantInteger && ((ConstantInteger) constVal).getInteger().equals(0L))
// NULL pointer assigment is OK
;
else if(!SymbolTypeConversion.assignmentTypeMatch(variableType, valueType)) {
ConstantLiteral constantLiteral = null;
try {
constantLiteral = constVal.calculateLiteral(getScope());

View File

@ -9,8 +9,11 @@ import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeConversion;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.values.AssignmentRValue;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.RValue;
/**
* Asserts that types match in all assignments and calculations
@ -52,6 +55,14 @@ public class PassNAssertTypeMatch extends Pass2SsaAssertion {
private void checkAssignment(StatementAssignment statement) {
LValue lValue = statement.getlValue();
SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
// Test NULL pointer assignment
if(lValueType instanceof SymbolTypePointer) {
final RValue rValue = statement.getrValue2();
if(rValue instanceof ConstantInteger && ((ConstantInteger) rValue).getInteger().equals(0L))
// A null-pointer assignment is OK!
return;
}
SymbolType rValueType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(statement));
if(SymbolTypeConversion.assignmentTypeMatch(lValueType, rValueType)) return;
// Types do not match

View File

@ -0,0 +1,9 @@
#ifndef _HAVE_NULL
/// NULL pointer
#define NULL 0
#define _HAVE_NULL
#endif
/// The unsigned integral type that is the result of the sizeof keyword.
typedef unsigned int size_t ;

View File

@ -1,4 +1,5 @@
/// @file
/// Functions for performing input and output.
#include <stddef.h>
#include <printf.h>

View File

@ -2,6 +2,7 @@
/// C standard library stdlib.h
///
/// Implementation of functions found int C stdlib.h / stdlib.c
#include <stddef.h>
#include <string.h>
/// Allocates a block of size chars of memory, returning a pointer to the beginning of the block.

View File

@ -2,8 +2,7 @@
/// C standard library string.h
///
/// Functions to manipulate C strings and arrays.
typedef unsigned int size_t ;
#include <stddef.h>
/// Copy block of memory (forwards)
/// Copies the values of num chars from the location pointed to by source directly to the memory block pointed to by destination.

View File

@ -14,6 +14,11 @@ public class TestProgramsFast extends TestPrograms {
// compileAndCompare("shadow-variable-error-1.c");
//}
@Test
public void testNullConstant() throws IOException {
compileAndCompare("null-constant.c");
}
@Test
public void testBlockError2() throws IOException {
compileAndCompare("block-error-2.c");

View File

@ -0,0 +1,16 @@
// Test the NULL pointer
#include <stddef.h>
char * screen = NULL;
char * ptrs[] = { (char*)0x400, (char*)0x450, (char*)0x4a0, NULL };
void main() {
for(char ** ptr = ptrs; *ptr; ptr++) {
**ptr = 'a';
screen = *ptr;
screen[1] = 'b';
}
}

View File

@ -0,0 +1,64 @@
// Test the NULL pointer
// Commodore 64 PRG executable file
.file [name="null-constant.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.const SIZEOF_POINTER = 2
.label screen = 4
.segment Code
main: {
.label ptr = 2
lda #<ptrs
sta.z ptr
lda #>ptrs
sta.z ptr+1
__b1:
// for(char ** ptr = ptrs; *ptr; ptr++)
ldy #0
tya
cmp (ptr),y
bne __b2
iny
cmp (ptr),y
bne __b2
// }
rts
__b2:
// **ptr = 'a'
lda #'a'
pha
ldy #1
lda (ptr),y
sta.z $ff
dey
lda (ptr),y
sta.z $fe
pla
sta ($fe),y
// screen = *ptr
ldy #0
lda (ptr),y
sta.z screen
iny
lda (ptr),y
sta.z screen+1
// screen[1] = 'b'
lda #'b'
ldy #1
sta (screen),y
// for(char ** ptr = ptrs; *ptr; ptr++)
lda #SIZEOF_POINTER
clc
adc.z ptr
sta.z ptr
bcc !+
inc.z ptr+1
!:
jmp __b1
}
.segment Data
ptrs: .word $400, $450, $4a0, 0

View File

@ -0,0 +1,18 @@
void main()
main: scope:[main] from
[0] phi()
to:main::@1
main::@1: scope:[main] from main main::@2
[1] main::ptr#2 = phi( main/ptrs, main::@2/main::ptr#1 )
[2] if((byte*)0!=*main::ptr#2) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[3] return
to:@return
main::@2: scope:[main] from main::@1
[4] *(*main::ptr#2) = 'a'
[5] screen#0 = *main::ptr#2
[6] screen#0[1] = 'b'
[7] main::ptr#1 = main::ptr#2 + SIZEOF_POINTER
to:main::@1

View File

@ -0,0 +1,372 @@
Inlined call call __init
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start::@1
screen#10 = phi( __start::@1/screen#9 )
main::ptr#0 = ptrs
to:main::@1
main::@1: scope:[main] from main main::@2
screen#8 = phi( main/screen#10, main::@2/screen#0 )
main::ptr#2 = phi( main/main::ptr#0, main::@2/main::ptr#1 )
main::$0 = (byte*)0 != *main::ptr#2
if(main::$0) goto main::@2
to:main::@return
main::@2: scope:[main] from main::@1
main::ptr#3 = phi( main::@1/main::ptr#2 )
*(*main::ptr#3) = 'a'
screen#0 = *main::ptr#3
screen#0[1] = 'b'
main::ptr#1 = main::ptr#3 + SIZEOF_POINTER
to:main::@1
main::@return: scope:[main] from main::@1
screen#5 = phi( main::@1/screen#8 )
screen#1 = screen#5
return
to:@return
void __start()
__start: scope:[__start] from
to:__start::__init1
__start::__init1: scope:[__start] from __start
screen#2 = 0
to:__start::@1
__start::@1: scope:[__start] from __start::__init1
screen#9 = phi( __start::__init1/screen#2 )
call main
to:__start::@2
__start::@2: scope:[__start] from __start::@1
screen#6 = phi( __start::@1/screen#1 )
screen#3 = screen#6
to:__start::@return
__start::@return: scope:[__start] from __start::@2
screen#7 = phi( __start::@2/screen#3 )
screen#4 = screen#7
return
to:@return
SYMBOL TABLE SSA
constant byte SIZEOF_POINTER = 2
void __start()
void main()
bool~ main::$0
byte** main::ptr
byte** main::ptr#0
byte** main::ptr#1
byte** main::ptr#2
byte** main::ptr#3
constant byte** ptrs[] = { (byte*)$400, (byte*)$450, (byte*)$4a0, 0 }
byte* screen
byte* screen#0
byte* screen#1
byte* screen#10
byte* screen#2
byte* screen#3
byte* screen#4
byte* screen#5
byte* screen#6
byte* screen#7
byte* screen#8
byte* screen#9
Adding number conversion cast (unumber) 1 in screen#0[1] = 'b'
Adding number conversion cast (unumber) 0 in screen#2 = 0
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast screen#2 = (unumber)0
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant pointer cast (byte*) 1104
Simplifying constant pointer cast (byte*) 1184
Simplifying constant integer cast 1
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias main::ptr#2 = main::ptr#3
Alias screen#1 = screen#5 screen#8
Alias screen#2 = screen#9
Alias screen#3 = screen#6 screen#7 screen#4
Successful SSA optimization Pass2AliasElimination
Identical Phi Values screen#10 screen#2
Identical Phi Values screen#3 screen#1
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition main::$0 [4] if((byte*)0!=*main::ptr#2) goto main::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant main::ptr#0 = ptrs
Constant screen#2 = 0
Successful SSA optimization Pass2ConstantIdentification
Eliminating unused variable - keeping the phi block screen#1
Successful SSA optimization PassNEliminateUnusedVars
Eliminating unused constant screen#2
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::__init1
Removing unused procedure block __start::@1
Removing unused procedure block __start::@2
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Inlining constant with var siblings main::ptr#0
Constant inlined main::ptr#0 = ptrs
Successful SSA optimization Pass2ConstantInlining
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Adding NOP phi() at start of main
CALL GRAPH
Created 1 initial phi equivalence classes
Coalesced [8] main::ptr#4 = main::ptr#1
Coalesced down to 1 phi equivalence classes
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] phi()
to:main::@1
main::@1: scope:[main] from main main::@2
[1] main::ptr#2 = phi( main/ptrs, main::@2/main::ptr#1 )
[2] if((byte*)0!=*main::ptr#2) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[3] return
to:@return
main::@2: scope:[main] from main::@1
[4] *(*main::ptr#2) = 'a'
[5] screen#0 = *main::ptr#2
[6] screen#0[1] = 'b'
[7] main::ptr#1 = main::ptr#2 + SIZEOF_POINTER
to:main::@1
VARIABLE REGISTER WEIGHTS
void main()
byte** main::ptr
byte** main::ptr#1 22.0
byte** main::ptr#2 11.0
byte* screen
byte* screen#0 22.0
Initial phi equivalence classes
[ main::ptr#2 main::ptr#1 ]
Added variable screen#0 to live range equivalence class [ screen#0 ]
Complete equivalence classes
[ main::ptr#2 main::ptr#1 ]
[ screen#0 ]
Allocated zp[2]:2 [ main::ptr#2 main::ptr#1 ]
Allocated zp[2]:4 [ screen#0 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [2] if((byte*)0!=*main::ptr#2) goto main::@2 [ main::ptr#2 ] ( [ main::ptr#2 ] { } ) always clobbers reg byte a reg byte y
Statement [4] *(*main::ptr#2) = 'a' [ main::ptr#2 ] ( [ main::ptr#2 ] { } ) always clobbers reg byte a reg byte y
Statement [5] screen#0 = *main::ptr#2 [ main::ptr#2 screen#0 ] ( [ main::ptr#2 screen#0 ] { } ) always clobbers reg byte a reg byte y
Statement [6] screen#0[1] = 'b' [ main::ptr#2 ] ( [ main::ptr#2 ] { } ) always clobbers reg byte a reg byte y
Statement [7] main::ptr#1 = main::ptr#2 + SIZEOF_POINTER [ main::ptr#1 ] ( [ main::ptr#1 ] { } ) always clobbers reg byte a
Potential registers zp[2]:2 [ main::ptr#2 main::ptr#1 ] : zp[2]:2 ,
Potential registers zp[2]:4 [ screen#0 ] : zp[2]:4 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 33: zp[2]:2 [ main::ptr#2 main::ptr#1 ]
Uplift Scope [] 22: zp[2]:4 [ screen#0 ]
Uplifting [main] best 1281 combination zp[2]:2 [ main::ptr#2 main::ptr#1 ]
Uplifting [] best 1281 combination zp[2]:4 [ screen#0 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test the NULL pointer
// Upstart
// Commodore 64 PRG executable file
.file [name="null-constant.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.const SIZEOF_POINTER = 2
.label screen = 4
.segment Code
// main
main: {
.label ptr = 2
// [1] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
// [1] phi main::ptr#2 = ptrs [phi:main->main::@1#0] -- qbuz1=qbuc1
lda #<ptrs
sta.z ptr
lda #>ptrs
sta.z ptr+1
jmp __b1
// main::@1
__b1:
// [2] if((byte*)0!=*main::ptr#2) goto main::@2 -- pbuc1_neq__deref_qbuz1_then_la1
ldy #0
lda #<0
cmp (ptr),y
bne __b2
iny
lda #>0
cmp (ptr),y
bne __b2
jmp __breturn
// main::@return
__breturn:
// [3] return
rts
// main::@2
__b2:
// [4] *(*main::ptr#2) = 'a' -- _deref_(_deref_qbuz1)=vbuc1
lda #'a'
pha
ldy #1
lda (ptr),y
sta.z $ff
dey
lda (ptr),y
sta.z $fe
pla
sta ($fe),y
// [5] screen#0 = *main::ptr#2 -- pbuz1=_deref_qbuz2
ldy #0
lda (ptr),y
sta.z screen
iny
lda (ptr),y
sta.z screen+1
// [6] screen#0[1] = 'b' -- pbuz1_derefidx_vbuc1=vbuc2
lda #'b'
ldy #1
sta (screen),y
// [7] main::ptr#1 = main::ptr#2 + SIZEOF_POINTER -- qbuz1=qbuz1_plus_vbuc1
lda #SIZEOF_POINTER
clc
adc.z ptr
sta.z ptr
bcc !+
inc.z ptr+1
!:
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
__b1_from___b2:
// [1] phi main::ptr#2 = main::ptr#1 [phi:main::@2->main::@1#0] -- register_copy
jmp __b1
}
// File Data
.segment Data
ptrs: .word $400, $450, $4a0, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing instruction lda #<0 with TYA
Removing instruction lda #>0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Removing instruction __b1_from_main:
Removing instruction __breturn:
Removing instruction __b1_from___b2:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
constant byte SIZEOF_POINTER = 2
void main()
byte** main::ptr
byte** main::ptr#1 ptr zp[2]:2 22.0
byte** main::ptr#2 ptr zp[2]:2 11.0
constant byte** ptrs[] = { (byte*) 1024, (byte*) 1104, (byte*) 1184, 0 }
byte* screen
byte* screen#0 screen zp[2]:4 22.0
zp[2]:2 [ main::ptr#2 main::ptr#1 ]
zp[2]:4 [ screen#0 ]
FINAL ASSEMBLER
Score: 1201
// File Comments
// Test the NULL pointer
// Upstart
// Commodore 64 PRG executable file
.file [name="null-constant.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.const SIZEOF_POINTER = 2
.label screen = 4
.segment Code
// main
main: {
.label ptr = 2
// [1] phi from main to main::@1 [phi:main->main::@1]
// [1] phi main::ptr#2 = ptrs [phi:main->main::@1#0] -- qbuz1=qbuc1
lda #<ptrs
sta.z ptr
lda #>ptrs
sta.z ptr+1
// main::@1
__b1:
// for(char ** ptr = ptrs; *ptr; ptr++)
// [2] if((byte*)0!=*main::ptr#2) goto main::@2 -- pbuc1_neq__deref_qbuz1_then_la1
ldy #0
tya
cmp (ptr),y
bne __b2
iny
cmp (ptr),y
bne __b2
// main::@return
// }
// [3] return
rts
// main::@2
__b2:
// **ptr = 'a'
// [4] *(*main::ptr#2) = 'a' -- _deref_(_deref_qbuz1)=vbuc1
lda #'a'
pha
ldy #1
lda (ptr),y
sta.z $ff
dey
lda (ptr),y
sta.z $fe
pla
sta ($fe),y
// screen = *ptr
// [5] screen#0 = *main::ptr#2 -- pbuz1=_deref_qbuz2
ldy #0
lda (ptr),y
sta.z screen
iny
lda (ptr),y
sta.z screen+1
// screen[1] = 'b'
// [6] screen#0[1] = 'b' -- pbuz1_derefidx_vbuc1=vbuc2
lda #'b'
ldy #1
sta (screen),y
// for(char ** ptr = ptrs; *ptr; ptr++)
// [7] main::ptr#1 = main::ptr#2 + SIZEOF_POINTER -- qbuz1=qbuz1_plus_vbuc1
lda #SIZEOF_POINTER
clc
adc.z ptr
sta.z ptr
bcc !+
inc.z ptr+1
!:
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
// [1] phi main::ptr#2 = main::ptr#1 [phi:main::@2->main::@1#0] -- register_copy
jmp __b1
}
// File Data
.segment Data
ptrs: .word $400, $450, $4a0, 0

View File

@ -0,0 +1,11 @@
constant byte SIZEOF_POINTER = 2
void main()
byte** main::ptr
byte** main::ptr#1 ptr zp[2]:2 22.0
byte** main::ptr#2 ptr zp[2]:2 11.0
constant byte** ptrs[] = { (byte*) 1024, (byte*) 1104, (byte*) 1184, 0 }
byte* screen
byte* screen#0 screen zp[2]:4 22.0
zp[2]:2 [ main::ptr#2 main::ptr#1 ]
zp[2]:4 [ screen#0 ]

View File

@ -3,6 +3,7 @@
/// C standard library string.h
///
/// Functions to manipulate C strings and arrays.
/// NULL pointer
// Commodore 16 / Plus/4 executable PRG file
.file [name="plus4-keyboard-test.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]

View File

@ -547,6 +547,7 @@ ASSEMBLER BEFORE OPTIMIZATION
/// C standard library string.h
///
/// Functions to manipulate C strings and arrays.
/// NULL pointer
// Upstart
// Commodore 16 / Plus/4 executable PRG file
.file [name="plus4-keyboard-test.prg", type="prg", segments="Program"]
@ -800,6 +801,7 @@ Score: 7354
/// C standard library string.h
///
/// Functions to manipulate C strings and arrays.
/// NULL pointer
// Upstart
// Commodore 16 / Plus/4 executable PRG file
.file [name="plus4-keyboard-test.prg", type="prg", segments="Program"]

View File

@ -2,6 +2,7 @@
/// C standard library string.h
///
/// Functions to manipulate C strings and arrays.
/// NULL pointer
// Commodore 64 PRG executable file
.file [name="sieve-min.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]

View File

@ -979,6 +979,7 @@ ASSEMBLER BEFORE OPTIMIZATION
/// C standard library string.h
///
/// Functions to manipulate C strings and arrays.
/// NULL pointer
// Upstart
// Commodore 64 PRG executable file
.file [name="sieve-min.prg", type="prg", segments="Program"]
@ -1469,6 +1470,7 @@ Score: 9717
/// C standard library string.h
///
/// Functions to manipulate C strings and arrays.
/// NULL pointer
// Upstart
// Commodore 64 PRG executable file
.file [name="sieve-min.prg", type="prg", segments="Program"]