venus
venus copied to clipboard
Error executing step-by-step code when encountering "ecall" instruction
--------------------
[ERROR] An uncaught error has occurred! Here are the details that may help solve this issue.
Error:
`SimulatorError: The heap has grown into the stack.
ID:
'step'!
`
Data:
{"venus":"true","trace_format":"%output%%0%\t%1%\t%2%\t%3%\t%4%\t%5%\t%6%\t%7%\t%8%\t%9%\t%10%\t%11%\t%12%\t%13%\t%14%\t%15%\t%16%\t%17%\t%18%\t%19%\t%20%\t%21%\t%22%\t%23%\t%24%\t%25%\t%26%\t%27%\t%28%\t%29%\t%30%\t%31%\t%line%\t%pc%\t%inst%\n","trace_base":"2","trace_totCommands":"-1","trace_maxSteps":"-1","trace_instFirst":"false","trace_wordAddressed":"false","trace_TwoStage":"false","history_limit":"-1","text_begin":"0","aligned_memory":"false","mutable_text":"true","ecall_exit_only":"false","set_regs_on_init":"true","simargs":"","enableCallingConvention":"false","prog":"# Compiled ChocoPy Program to RISC-V assembly\n# Execute (run or step-through) using the 'Simulator' tab above \n# Output will appear on the bottom-left of the simulator\n .equiv @sbrk, 9\n .equiv @print_string, 4\n .equiv @print_char, 11\n .equiv @print_int, 1\n .equiv @exit2, 17\n .equiv @read_string, 8\n .equiv @fill_line_buffer, 18\n .equiv @.__obj_size__, 4\n .equiv @.__len__, 12\n .equiv @.__int__, 12\n .equiv @.__bool__, 12\n .equiv @.__str__, 16\n .equiv @.__elts__, 16\n .equiv @error_div_zero, 2\n .equiv @error_arg, 1\n .equiv @error_oob, 3\n .equiv @error_none, 4\n .equiv @error_oom, 5\n .equiv @error_nyi, 6\n .equiv @listHeaderWords, 4\n .equiv @strHeaderWords, 4\n .equiv @bool.True, const_1\n .equiv @bool.False, const_0\n\n.data\n\n.globl $object$prototype\n$object$prototype:\n .word 0 # Type tag for class: object\n .word 3 # Object size\n .word $object$dispatchTable # Pointer to dispatch table\n .align 2\n\n.globl $int$prototype\n$int$prototype:\n .word 1 # Type tag for class: int\n .word 4 # Object size\n .word $int$dispatchTable # Pointer to dispatch table\n .word 0 # Initial value of attribute: __int__\n .align 2\n\n.globl $bool$prototype\n$bool$prototype:\n .word 2 # Type tag for class: bool\n .word 4 # Object size\n .word $bool$dispatchTable # Pointer to dispatch table\n .word 0 # Initial value of attribute: __bool__\n .align 2\n\n.globl $str$prototype\n$str$prototype:\n .word 3 # Type tag for class: str\n .word 5 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 0 # Initial value of attribute: __len__\n .word 0 # Initial value of attribute: __str__\n .align 2\n\n.globl $.list$prototype\n$.list$prototype:\n .word -1 # Type tag for class: .list\n .word 4 # Object size\n .word 0 # Pointer to dispatch table\n .word 0 # Initial value of attribute: __len__\n .align 2\n\n.globl $object$dispatchTable\n$object$dispatchTable:\n .word $object.__init__ # Implementation for method: object.__init__\n\n.globl $int$dispatchTable\n$int$dispatchTable:\n .word $object.__init__ # Implementation for method: int.__init__\n\n.globl $bool$dispatchTable\n$bool$dispatchTable:\n .word $object.__init__ # Implementation for method: bool.__init__\n\n.globl $str$dispatchTable\n$str$dispatchTable:\n .word $object.__init__ # Implementation for method: str.__init__\n\n.text\n\n.globl main\nmain:\n lui a0, 8192 # Initialize heap size (in multiples of 4KB)\n add s11, s11, a0 # Save heap size\n jal heap.init # Call heap.init routine\n mv gp, a0 # Initialize heap pointer\n mv s10, gp # Set beginning of heap\n add s11, s10, s11 # Set end of heap (= start of heap + heap size)\n mv ra, zero # No normal return from main program.\n mv fp, zero # No preceding frame.\n mv fp, zero # Top saved FP is 0.\n mv ra, zero # No function return from top level.\n addi sp, sp, [email protected] # Reserve space for stack frame.\n sw ra, @..main.size-4(sp) # return address\n sw fp, @..main.size-8(sp) # control link\n addi fp, sp, @..main.size # New fp is at old SP.\n jal initchars # Initialize one-character strings.\n li a0, 4 # Load integer literal 4\n sw a0, -28(fp) # Push argument 5 from last.\n li a0, 8 # Load integer literal 8\n sw a0, -32(fp) # Push argument 4 from last.\n li a0, 15 # Load integer literal 15\n sw a0, -36(fp) # Push argument 3 from last.\n li a0, 16 # Load integer literal 16\n sw a0, -40(fp) # Push argument 2 from last.\n li a0, 23 # Load integer literal 23\n sw a0, -44(fp) # Push argument 1 from last.\n li a0, 5 # Pass list length\n sw a0, -48(fp) # Push argument 0 from last.\n addi sp, fp, -48 # Set SP to last argument.\n jal conslist # Move values to new list object\n addi sp, fp, [email protected] # Set SP to stack frame top.\n sw a0, -12(fp) # Push argument 1 from last.\n li a0, 15 # Load integer literal 15\n sw a0, -16(fp) # Push argument 0 from last.\n addi sp, fp, -16 # Set SP to last argument.\n jal $contains # Invoke function: contains\n addi sp, fp, [email protected] # Set SP to stack frame top.\n beqz a0, label_2 # Branch on false.\n la a0, const_2 # Load string literal\n sw a0, -16(fp) # Push argument 0 from last.\n addi sp, fp, -16 # Set SP to last argument.\n jal $print # Invoke function: print\n addi sp, fp, [email protected] # Set SP to stack frame top.\n j label_1 # Then body complete; jump to end-if\nlabel_2: # Else body\n la a0, const_3 # Load string literal\n sw a0, -16(fp) # Push argument 0 from last.\n addi sp, fp, -16 # Set SP to last argument.\n jal $print # Invoke function: print\n addi sp, fp, [email protected] # Set SP to stack frame top.\nlabel_1: # End of if-else statement\n .equiv @..main.size, 48\nlabel_0: # End of program\n li a0, 10 # Code for ecall: exit\n ecall\n\n.globl $object.__init__\n$object.__init__:\n# Init method for type object.\t\n mv a0, zero # `None` constant\n jr ra # Return\n\n.globl $print\n$print:\n# Function print\n lw a0, 0(sp) # Load arg\n beq a0, zero, print_6 # None is an illegal argument\n lw t0, 0(a0) # Get type tag of arg\n li t1, 1 # Load type tag of `int`\n beq t0, t1, print_7 # Go to print(int)\n li t1, 3 # Load type tag of `str`\n beq t0, t1, print_8 # Go to print(str)\n li t1, 2 # Load type tag of `bool`\n beq t0, t1, print_9 # Go to print(bool)\nprint_6: # Invalid argument\n li a0, 1 # Exit code for: Invalid argument\n la a1, const_4 # Load error message as str\n addi a1, a1, @.__str__ # Load address of attribute __str__\n j abort # Abort\n\n# Printing bools\nprint_9: # Print bool object in A0\n lw a0, @.__bool__(a0) # Load attribute __bool__\n beq a0, zero, print_10 # Go to: print(False)\n la a0, const_5 # String representation: True\n j print_8 # Go to: print(str)\nprint_10: # Print False object in A0\n la a0, const_6 # String representation: False\n j print_8 # Go to: print(str)\n\n# Printing strs.\nprint_8: # Print str object in A0\n addi a1, a0, @.__str__ # Load address of attribute __str__\n j print_11 # Print the null-terminated string is now in A1\n mv a0, zero # Load None\n j print_5 # Go to return\nprint_11: # Print null-terminated string in A1\n li a0, @print_string # Code for ecall: print_string\n ecall # Print string\n li a1, 10 # Load newline character\n li a0, @print_char # Code for ecall: print_char\n ecall # Print character\n j print_5 # Go to return\n\n# Printing ints.\nprint_7: # Print int object in A0\n lw a1, @.__int__(a0) # Load attribute __int__\n li a0, @print_int # Code for ecall: print_int\n ecall # Print integer\n li a1, 10 # Load newline character\n li a0, 11 # Code for ecall: print_char\n ecall # Print character\n\nprint_5: # End of function\n mv a0, zero # Load None\n jr ra # Return to caller\n\n.globl $len\n$len:\n# Function len\n # We do not save/restore fp/ra for this function\n # because we know that it does not use the stack or does not\n # call other functions.\n\n lw a0, 0(sp) # Load arg\n beq a0, zero, len_12 # None is an illegal argument\n lw t0, 0(a0) # Get type tag of arg\n li t1, 3 # Load type tag of `str`\n beq t0, t1, len_13 # Go to len(str)\n li t1, -1 # Load type tag for list objects\n beq t0, t1, len_13 # Go to len(list)\nlen_12: # Invalid argument\n li a0, @error_arg # Exit code for: Invalid argument\n la a1, const_4 # Load error message as str\n addi a1, a1, @.__str__ # Load address of attribute __str__\n j abort # Abort\nlen_13: # Get length of string\n lw a0, @.__len__(a0) # Load attribute: __len__\n jr ra # Return to caller\n\n.globl $input\n$input:\n\n addi sp, sp, -16\n sw ra, 12(sp)\n sw fp, 8(sp)\n sw s1, 4(sp)\n addi fp, sp, 16\n li a0, @fill_line_buffer\n ecall\n bgez a0, input_nonempty\n la a0, $str$prototype\n j input_done\ninput_nonempty:\n mv s1, a0\n addi t0, s1, 5\n addi t0, t0, @.__str__\n srli a1, t0, 2\n la a0, $str$prototype\n jal ra, alloc2\n sw s1, @.__len__(a0)\n mv a2, s1\n mv s1, a0\n addi a1, a0, @.__str__\n li a0, @read_string\n ecall\n addi a0, a0, 1\n sw a0, @.__len__(s1)\n add t0, a0, s1\n li t1, 10\n sb t1, @.__str__-1(t0)\n sb zero, @.__str__(t0)\n mv a0, s1\ninput_done:\n lw s1, -12(fp)\n lw ra, -4(fp)\n lw fp, -8(fp)\n addi sp, sp, 16\n jr ra\n\n.globl $contains\n$contains:\n addi sp, sp, [email protected] # Reserve space for stack frame.\n sw ra, @contains.size-4(sp) # return address\n sw fp, @contains.size-8(sp) # control link\n addi fp, sp, @contains.size # New fp is at old SP.\n li a0, 0 # Load integer literal 0\n sw a0, -12(fp) # local variable i\n j label_6 # Jump to loop test\nlabel_5: # Top of while loop\n lw a0, 4(fp) # Load var: contains.items\n sw a0, -16(fp) # Push on stack slot 4\n lw a0, -12(fp) # Load var: contains.i\n lw a1, -16(fp) # Pop stack slot 4\n bnez a1, label_8 # Ensure not None\n j error.None # Go to error handler\nlabel_8: # Not None\n lw t0, 12(a1) # Load attribute: __len__\n bltu a0, t0, label_9 # Ensure 0 <= index < len\n j error.OOB # Go to error handler\nlabel_9: # Index within bounds\n addi a0, a0, 4 # Compute list element offset in words\n li t0, 4 # Word size in bytes\n mul a0, a0, t0 # Compute list element offset in bytes\n add a0, a1, a0 # Pointer to list element\n lw a0, 0(a0) # Get list element\n sw a0, -16(fp) # Push on stack slot 4\n lw a0, 0(fp) # Load var: contains.x\n lw t0, -16(fp) # Pop stack slot 4\n bne t0, a0, label_7 # Branch on not ==\n li a0, 1 # Load boolean literal: true\n j label_4 # Go to return\nlabel_7: # End of if-else statement\n lw a0, -12(fp) # Load var: contains.i\n sw a0, -16(fp) # Push on stack slot 4\n li a0, 1 # Load integer literal 1\n lw t0, -16(fp) # Pop stack slot 4\n add a0, t0, a0 # Operator +\n sw a0, -12(fp) # Assign var: contains.i\nlabel_6: # Test loop condition\n lw a0, -12(fp) # Load var: contains.i\n sw a0, -16(fp) # Push on stack slot 4\n lw a0, 4(fp) # Load var: contains.items\n sw a0, -32(fp) # Push argument 0 from last.\n addi sp, fp, -32 # Set SP to last argument.\n jal $len # Invoke function: len\n addi sp, fp, [email protected] # Set SP to stack frame top.\n lw t0, -16(fp) # Pop stack slot 4\n blt t0, a0, label_5 # Branch on <\n li a0, 0 # Load boolean literal: false\n j label_4 # Go to return\n mv a0, zero # Load None\n j label_4 # Jump to function epilogue\nlabel_4: # Epilogue\n .equiv @contains.size, 32\n lw ra, -4(fp) # Get return address\n lw fp, -8(fp) # Use control link to restore caller's fp\n addi sp, sp, @contains.size # Restore stack pointer\n jr ra # Return to caller\n\n.globl alloc\nalloc:\n# Runtime support function alloc.\n # Prototype address is in a0.\n lw a1, 4(a0) # Get size of object in words\n j alloc2 # Allocate object with exact size\n\n.globl alloc2\nalloc2:\n# Runtime support function alloc2 (realloc).\n # Prototype address is in a0.\n # Number of words to allocate is in a1.\n li a2, 4 # Word size in bytes\n mul a2, a1, a2 # Calculate number of bytes to allocate\n add a2, gp, a2 # Estimate where GP will move\n bgeu a2, s11, alloc2_15 # Go to OOM handler if too large\n lw t0, @.__obj_size__(a0) # Get size of object in words\n mv t2, a0 # Initialize src ptr\n mv t3, gp # Initialize dest ptr\nalloc2_16: # Copy-loop header\n lw t1, 0(t2) # Load next word from src\n sw t1, 0(t3) # Store next word to dest\n addi t2, t2, 4 # Increment src\n addi t3, t3, 4 # Increment dest\n addi t0, t0, -1 # Decrement counter\n bne t0, zero, alloc2_16 # Loop if more words left to copy\n mv a0, gp # Save new object's address to return\n sw a1, @.__obj_size__(a0) # Set size of new object in words\n # (same as requested size)\n mv gp, a2 # Set next free slot in the heap\n jr ra # Return to caller\nalloc2_15: # OOM handler\n li a0, @error_oom # Exit code for: Out of memory\n la a1, const_7 # Load error message as str\n addi a1, a1, @.__str__ # Load address of attribute __str__\n j abort # Abort\n\n.globl abort\nabort:\n# Runtime support function abort (does not return).\n mv t0, a0 # Save exit code in temp\n li a0, @print_string # Code for print_string ecall\n ecall # Print error message in a1\n li a1, 10 # Load newline character\n li a0, @print_char # Code for print_char ecall\n ecall # Print newline\n mv a1, t0 # Move exit code to a1\n li a0, @exit2 # Code for exit2 ecall\n ecall # Exit with code\nabort_17: # Infinite loop\n j abort_17 # Prevent fallthrough\n\n.globl heap.init\nheap.init:\n# Runtime support function heap.init.\n mv a1, a0 # Move requested size to A1\n li a0, @sbrk # Code for ecall: sbrk\n ecall # Request A1 bytes\n jr ra # Return to caller\n\n.globl concat\nconcat:\n\n addi sp, sp, -32\n sw ra, 28(sp)\n sw fp, 24(sp)\n addi fp, sp, 32\n\tsw s1, -12(fp)\n sw s2, -16(fp)\n sw s3, -20(fp)\n\tsw s4, -24(fp)\n sw s5, -28(fp)\n lw t0, 4(fp)\n lw t1, 0(fp)\n beqz t0, concat_none\n beqz t1, concat_none\n lw t0, @.__len__(t0)\n lw t1, @.__len__(t1)\n add s5, t0, t1\n addi a1, s5, @listHeaderWords\n la a0, $.list$prototype\n jal alloc2\n sw s5, @.__len__(a0)\n\tmv s5, a0\n addi s3, s5, @.__elts__\n lw s1, 4(fp)\n\tlw s2, @.__len__(s1)\n addi s1, s1, @.__elts__\n\tlw s4, 12(fp)\nconcat_1:\n beqz s2, concat_2\n lw a0, 0(s1)\n\tjalr ra, s4, 0\n sw a0, 0(s3)\n addi s2, s2, -1\n addi s1, s1, 4\n addi s3, s3, 4\n j concat_1\nconcat_2:\n lw s1, 0(fp)\n lw s2, @.__len__(s1)\n addi s1, s1, @.__elts__\n\tlw s4, 8(fp)\nconcat_3:\n beqz s2, concat_4\n lw a0, 0(s1)\n\tjalr ra, s4, 0\n sw a0, 0(s3)\n addi s2, s2, -1\n addi s1, s1, 4\n addi s3, s3, 4\n j concat_3\nconcat_4:\n\tmv a0, s5\n lw s1, -12(fp)\n lw s2, -16(fp)\n lw s3, -20(fp)\n\tlw s4, -24(fp)\n lw s5, -28(fp)\n lw ra, -4(fp)\n lw fp, -8(fp)\n addi sp, sp, 32\n jr ra\nconcat_none:\n j error.None\n\n\n.globl conslist\nconslist:\n\n addi sp, sp, -8\n sw ra, 4(sp)\n sw fp, 0(sp)\n addi fp, sp, 8\n lw a1, 0(fp)\n la a0, $.list$prototype\n beqz a1, conslist_done\n addi a1, a1, @listHeaderWords\n jal alloc2\n lw t0, 0(fp)\n sw t0, @.__len__(a0)\n slli t1, t0, 2\n add t1, t1, fp\n addi t2, a0, @.__elts__\nconslist_1:\n lw t3, 0(t1)\n sw t3, 0(t2)\n addi t1, t1, -4\n addi t2, t2, 4\n addi t0, t0, -1\n bnez t0, conslist_1\nconslist_done:\n lw ra, -4(fp)\n lw fp, -8(fp)\n addi sp, sp, 8\n jr ra\n\n\n.globl strcat\nstrcat:\n\n addi sp, sp, -12\n sw ra, 8(sp)\n sw fp, 4(sp)\n addi fp, sp, 12\n lw t0, 4(fp)\n lw t1, 0(fp)\n lw t0, @.__len__(t0)\n beqz t0, strcat_4\n lw t1, @.__len__(t1)\n beqz t1, strcat_5\n add t1, t0, t1\n sw t1, -12(fp)\n addi t1, t1, 4\n srli t1, t1, 2\n addi a1, t1, @listHeaderWords\n la a0, $str$prototype\n jal alloc2\n lw t0, -12(fp)\n sw t0, @.__len__(a0)\n addi t2, a0, 16\n lw t0, 4(fp)\n lw t1, @.__len__(t0)\n addi t0, t0, @.__str__\nstrcat_1:\n beqz t1, strcat_2\n lbu t3, 0(t0)\n sb t3, 0(t2)\n addi t1, t1, -1\n addi t0, t0, 1\n addi t2, t2, 1\n j strcat_1\nstrcat_2:\n lw t0, 0(fp)\n lw t1, 12(t0)\n addi t0, t0, 16\nstrcat_3:\n beqz t1, strcat_6\n lbu t3, 0(t0)\n sb t3, 0(t2)\n addi t1, t1, -1\n addi t0, t0, 1\n addi t2, t2, 1\n j strcat_3\nstrcat_4:\n lw a0, 0(fp)\n j strcat_7\nstrcat_5:\n lw a0, 4(fp)\n j strcat_7\nstrcat_6:\n sb zero, 0(t2)\nstrcat_7:\n lw ra, -4(fp)\n lw fp, -8(fp)\n addi sp, sp, 12\n jr ra\n\n\n.globl streql\nstreql:\n\n addi sp, sp, -8\n sw ra, 4(sp)\n sw fp, 0(sp)\n addi fp, sp, 8\n lw a1, 4(fp)\n lw a2, 0(fp)\n lw t0, @.__len__(a1)\n lw t1, @.__len__(a2)\n bne t0, t1, streql_no\nstreql_1:\n lbu t2, @.__str__(a1)\n lbu t3, @.__str__(a2)\n bne t2, t3, streql_no\n addi a1, a1, 1\n addi a2, a2, 1\n addi t0, t0, -1\n bgtz t0, streql_1\n li a0, 1\n j streql_end\nstreql_no:\n xor a0, a0, a0\nstreql_end:\n lw ra, -4(fp)\n lw fp, -8(fp)\n addi sp, sp, 8\n jr ra\n\n\n.globl strneql\nstrneql:\n\n addi sp, sp, -8\n sw ra, 4(sp)\n sw fp, 0(sp)\n addi fp, sp, 8\n lw a1, 4(fp)\n lw a2, 0(fp)\n lw t0, @.__len__(a1)\n lw t1, @.__len__(a2)\n bne t0, t1, strneql_yes\nstrneql_1:\n lbu t2, @.__str__(a1)\n lbu t3, @.__str__(a2)\n bne t2, t3, strneql_yes\n addi a1, a1, 1\n addi a2, a2, 1\n addi t0, t0, -1\n bgtz t0, strneql_1\n xor a0, a0, a0\n j strneql_end\nstrneql_yes:\n li a0, 1\nstrneql_end:\n lw ra, -4(fp)\n lw fp, -8(fp)\n addi sp, sp, 8\n jr ra\n\n\n.globl makeint\nmakeint:\n\n addi sp, sp, -8\n sw ra, 4(sp)\n sw a0, 0(sp)\n la a0, $int$prototype\n jal ra, alloc\n lw t0, 0(sp)\n sw t0, @.__int__(a0)\n lw ra, 4(sp)\n addi sp, sp, 8\n jr ra\n\n\n.globl makebool\nmakebool:\n\n\tslli a0, a0, 4\n la t0, @bool.False\n add a0, a0, t0\n\tjr ra\n\n\n.globl noconv\nnoconv:\n\n jr ra\n\n\n.globl initchars\ninitchars:\n\n jr ra\n\n\n.globl error.None\nerror.None:\n li a0, 4 # Exit code for: Operation on None\n la a1, const_8 # Load error message as str\n addi a1, a1, 16 # Load address of attribute __str__\n j abort # Abort\n\n.globl error.Div\nerror.Div:\n li a0, 2 # Exit code for: Division by zero\n la a1, const_9 # Load error message as str\n addi a1, a1, 16 # Load address of attribute __str__\n j abort # Abort\n\n.globl error.OOB\nerror.OOB:\n li a0, 3 # Exit code for: Index out of bounds\n la a1, const_10 # Load error message as str\n addi a1, a1, 16 # Load address of attribute __str__\n j abort # Abort\n\n.data\n\n.globl const_0\nconst_0:\n .word 2 # Type tag for class: bool\n .word 4 # Object size\n .word $bool$dispatchTable # Pointer to dispatch table\n .word 0 # Constant value of attribute: __bool__\n .align 2\n\n.globl const_1\nconst_1:\n .word 2 # Type tag for class: bool\n .word 4 # Object size\n .word $bool$dispatchTable # Pointer to dispatch table\n .word 1 # Constant value of attribute: __bool__\n .align 2\n\n.globl const_3\nconst_3:\n .word 3 # Type tag for class: str\n .word 8 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 15 # Constant value of attribute: __len__\n .string \"Item not found.\" # Constant value of attribute: __str__\n .align 2\n\n.globl const_9\nconst_9:\n .word 3 # Type tag for class: str\n .word 9 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 16 # Constant value of attribute: __len__\n .string \"Division by zero\" # Constant value of attribute: __str__\n .align 2\n\n.globl const_7\nconst_7:\n .word 3 # Type tag for class: str\n .word 8 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 13 # Constant value of attribute: __len__\n .string \"Out of memory\" # Constant value of attribute: __str__\n .align 2\n\n.globl const_10\nconst_10:\n .word 3 # Type tag for class: str\n .word 9 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 19 # Constant value of attribute: __len__\n .string \"Index out of bounds\" # Constant value of attribute: __str__\n .align 2\n\n.globl const_5\nconst_5:\n .word 3 # Type tag for class: str\n .word 6 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 4 # Constant value of attribute: __len__\n .string \"True\" # Constant value of attribute: __str__\n .align 2\n\n.globl const_8\nconst_8:\n .word 3 # Type tag for class: str\n .word 9 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 17 # Constant value of attribute: __len__\n .string \"Operation on None\" # Constant value of attribute: __str__\n .align 2\n\n.globl const_2\nconst_2:\n .word 3 # Type tag for class: str\n .word 7 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 11 # Constant value of attribute: __len__\n .string \"Item found!\" # Constant value of attribute: __str__\n .align 2\n\n.globl const_4\nconst_4:\n .word 3 # Type tag for class: str\n .word 9 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 16 # Constant value of attribute: __len__\n .string \"Invalid argument\" # Constant value of attribute: __str__\n .align 2\n\n.globl const_6\nconst_6:\n .word 3 # Type tag for class: str\n .word 6 # Object size\n .word $str$dispatchTable # Pointer to dispatch table\n .word 5 # Constant value of attribute: __len__\n .string \"False\" # Constant value of attribute: __str__\n .align 2\n","cache_levels":"1","cache_current_level":"1","cache_L1_associativity":"1","cache_L1_cacheBlockSize":"4","cache_L1_numberOfBlocks":"1","cache_L1_placementPol":"DIRECT_MAPPING","cache_L1_blockRepPolicy":"LRU","cache_L1_seed":"-7788879576802893459","cache_L1_attach":"false","activeFileinEditor":"","active_abs_file_name":"n","active_abs_file_path":"n","fileExplorerCurrentLocation":"","terminalCurrentLocation":""}
# Compiled ChocoPy Program to RISC-V assembly
# Execute (run or step-through) using the 'Simulator' tab above
# Output will appear on the bottom-left of the simulator
.equiv @sbrk, 9
.equiv @print_string, 4
.equiv @print_char, 11
.equiv @print_int, 1
.equiv @exit2, 17
.equiv @read_string, 8
.equiv @fill_line_buffer, 18
.equiv @.__obj_size__, 4
.equiv @.__len__, 12
.equiv @.__int__, 12
.equiv @.__bool__, 12
.equiv @.__str__, 16
.equiv @.__elts__, 16
.equiv @error_div_zero, 2
.equiv @error_arg, 1
.equiv @error_oob, 3
.equiv @error_none, 4
.equiv @error_oom, 5
.equiv @error_nyi, 6
.equiv @listHeaderWords, 4
.equiv @strHeaderWords, 4
.equiv @bool.True, const_1
.equiv @bool.False, const_0
.data
.globl $object$prototype
$object$prototype:
.word 0 # Type tag for class: object
.word 3 # Object size
.word $object$dispatchTable # Pointer to dispatch table
.align 2
.globl $int$prototype
$int$prototype:
.word 1 # Type tag for class: int
.word 4 # Object size
.word $int$dispatchTable # Pointer to dispatch table
.word 0 # Initial value of attribute: __int__
.align 2
.globl $bool$prototype
$bool$prototype:
.word 2 # Type tag for class: bool
.word 4 # Object size
.word $bool$dispatchTable # Pointer to dispatch table
.word 0 # Initial value of attribute: __bool__
.align 2
.globl $str$prototype
$str$prototype:
.word 3 # Type tag for class: str
.word 5 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 0 # Initial value of attribute: __len__
.word 0 # Initial value of attribute: __str__
.align 2
.globl $.list$prototype
$.list$prototype:
.word -1 # Type tag for class: .list
.word 4 # Object size
.word 0 # Pointer to dispatch table
.word 0 # Initial value of attribute: __len__
.align 2
.globl $object$dispatchTable
$object$dispatchTable:
.word $object.__init__ # Implementation for method: object.__init__
.globl $int$dispatchTable
$int$dispatchTable:
.word $object.__init__ # Implementation for method: int.__init__
.globl $bool$dispatchTable
$bool$dispatchTable:
.word $object.__init__ # Implementation for method: bool.__init__
.globl $str$dispatchTable
$str$dispatchTable:
.word $object.__init__ # Implementation for method: str.__init__
.text
.globl main
main:
lui a0, 8192 # Initialize heap size (in multiples of 4KB)
add s11, s11, a0 # Save heap size
jal heap.init # Call heap.init routine
mv gp, a0 # Initialize heap pointer
mv s10, gp # Set beginning of heap
add s11, s10, s11 # Set end of heap (= start of heap + heap size)
mv ra, zero # No normal return from main program.
mv fp, zero # No preceding frame.
mv fp, zero # Top saved FP is 0.
mv ra, zero # No function return from top level.
addi sp, sp, [email protected] # Reserve space for stack frame.
sw ra, @..main.size-4(sp) # return address
sw fp, @..main.size-8(sp) # control link
addi fp, sp, @..main.size # New fp is at old SP.
jal initchars # Initialize one-character strings.
li a0, 4 # Load integer literal 4
sw a0, -28(fp) # Push argument 5 from last.
li a0, 8 # Load integer literal 8
sw a0, -32(fp) # Push argument 4 from last.
li a0, 15 # Load integer literal 15
sw a0, -36(fp) # Push argument 3 from last.
li a0, 16 # Load integer literal 16
sw a0, -40(fp) # Push argument 2 from last.
li a0, 23 # Load integer literal 23
sw a0, -44(fp) # Push argument 1 from last.
li a0, 5 # Pass list length
sw a0, -48(fp) # Push argument 0 from last.
addi sp, fp, -48 # Set SP to last argument.
jal conslist # Move values to new list object
addi sp, fp, [email protected] # Set SP to stack frame top.
sw a0, -12(fp) # Push argument 1 from last.
li a0, 15 # Load integer literal 15
sw a0, -16(fp) # Push argument 0 from last.
addi sp, fp, -16 # Set SP to last argument.
jal $contains # Invoke function: contains
addi sp, fp, [email protected] # Set SP to stack frame top.
beqz a0, label_2 # Branch on false.
la a0, const_2 # Load string literal
sw a0, -16(fp) # Push argument 0 from last.
addi sp, fp, -16 # Set SP to last argument.
jal $print # Invoke function: print
addi sp, fp, [email protected] # Set SP to stack frame top.
j label_1 # Then body complete; jump to end-if
label_2: # Else body
la a0, const_3 # Load string literal
sw a0, -16(fp) # Push argument 0 from last.
addi sp, fp, -16 # Set SP to last argument.
jal $print # Invoke function: print
addi sp, fp, [email protected] # Set SP to stack frame top.
label_1: # End of if-else statement
.equiv @..main.size, 48
label_0: # End of program
li a0, 10 # Code for ecall: exit
ecall
.globl $object.__init__
$object.__init__:
# Init method for type object.
mv a0, zero # `None` constant
jr ra # Return
.globl $print
$print:
# Function print
lw a0, 0(sp) # Load arg
beq a0, zero, print_6 # None is an illegal argument
lw t0, 0(a0) # Get type tag of arg
li t1, 1 # Load type tag of `int`
beq t0, t1, print_7 # Go to print(int)
li t1, 3 # Load type tag of `str`
beq t0, t1, print_8 # Go to print(str)
li t1, 2 # Load type tag of `bool`
beq t0, t1, print_9 # Go to print(bool)
print_6: # Invalid argument
li a0, 1 # Exit code for: Invalid argument
la a1, const_4 # Load error message as str
addi a1, a1, @.__str__ # Load address of attribute __str__
j abort # Abort
# Printing bools
print_9: # Print bool object in A0
lw a0, @.__bool__(a0) # Load attribute __bool__
beq a0, zero, print_10 # Go to: print(False)
la a0, const_5 # String representation: True
j print_8 # Go to: print(str)
print_10: # Print False object in A0
la a0, const_6 # String representation: False
j print_8 # Go to: print(str)
# Printing strs.
print_8: # Print str object in A0
addi a1, a0, @.__str__ # Load address of attribute __str__
j print_11 # Print the null-terminated string is now in A1
mv a0, zero # Load None
j print_5 # Go to return
print_11: # Print null-terminated string in A1
li a0, @print_string # Code for ecall: print_string
ecall # Print string
li a1, 10 # Load newline character
li a0, @print_char # Code for ecall: print_char
ecall # Print character
j print_5 # Go to return
# Printing ints.
print_7: # Print int object in A0
lw a1, @.__int__(a0) # Load attribute __int__
li a0, @print_int # Code for ecall: print_int
ecall # Print integer
li a1, 10 # Load newline character
li a0, 11 # Code for ecall: print_char
ecall # Print character
print_5: # End of function
mv a0, zero # Load None
jr ra # Return to caller
.globl $len
$len:
# Function len
# We do not save/restore fp/ra for this function
# because we know that it does not use the stack or does not
# call other functions.
lw a0, 0(sp) # Load arg
beq a0, zero, len_12 # None is an illegal argument
lw t0, 0(a0) # Get type tag of arg
li t1, 3 # Load type tag of `str`
beq t0, t1, len_13 # Go to len(str)
li t1, -1 # Load type tag for list objects
beq t0, t1, len_13 # Go to len(list)
len_12: # Invalid argument
li a0, @error_arg # Exit code for: Invalid argument
la a1, const_4 # Load error message as str
addi a1, a1, @.__str__ # Load address of attribute __str__
j abort # Abort
len_13: # Get length of string
lw a0, @.__len__(a0) # Load attribute: __len__
jr ra # Return to caller
.globl $input
$input:
addi sp, sp, -16
sw ra, 12(sp)
sw fp, 8(sp)
sw s1, 4(sp)
addi fp, sp, 16
li a0, @fill_line_buffer
ecall
bgez a0, input_nonempty
la a0, $str$prototype
j input_done
input_nonempty:
mv s1, a0
addi t0, s1, 5
addi t0, t0, @.__str__
srli a1, t0, 2
la a0, $str$prototype
jal ra, alloc2
sw s1, @.__len__(a0)
mv a2, s1
mv s1, a0
addi a1, a0, @.__str__
li a0, @read_string
ecall
addi a0, a0, 1
sw a0, @.__len__(s1)
add t0, a0, s1
li t1, 10
sb t1, @.__str__-1(t0)
sb zero, @.__str__(t0)
mv a0, s1
input_done:
lw s1, -12(fp)
lw ra, -4(fp)
lw fp, -8(fp)
addi sp, sp, 16
jr ra
.globl $contains
$contains:
addi sp, sp, [email protected] # Reserve space for stack frame.
sw ra, @contains.size-4(sp) # return address
sw fp, @contains.size-8(sp) # control link
addi fp, sp, @contains.size # New fp is at old SP.
li a0, 0 # Load integer literal 0
sw a0, -12(fp) # local variable i
j label_6 # Jump to loop test
label_5: # Top of while loop
lw a0, 4(fp) # Load var: contains.items
sw a0, -16(fp) # Push on stack slot 4
lw a0, -12(fp) # Load var: contains.i
lw a1, -16(fp) # Pop stack slot 4
bnez a1, label_8 # Ensure not None
j error.None # Go to error handler
label_8: # Not None
lw t0, 12(a1) # Load attribute: __len__
bltu a0, t0, label_9 # Ensure 0 <= index < len
j error.OOB # Go to error handler
label_9: # Index within bounds
addi a0, a0, 4 # Compute list element offset in words
li t0, 4 # Word size in bytes
mul a0, a0, t0 # Compute list element offset in bytes
add a0, a1, a0 # Pointer to list element
lw a0, 0(a0) # Get list element
sw a0, -16(fp) # Push on stack slot 4
lw a0, 0(fp) # Load var: contains.x
lw t0, -16(fp) # Pop stack slot 4
bne t0, a0, label_7 # Branch on not ==
li a0, 1 # Load boolean literal: true
j label_4 # Go to return
label_7: # End of if-else statement
lw a0, -12(fp) # Load var: contains.i
sw a0, -16(fp) # Push on stack slot 4
li a0, 1 # Load integer literal 1
lw t0, -16(fp) # Pop stack slot 4
add a0, t0, a0 # Operator +
sw a0, -12(fp) # Assign var: contains.i
label_6: # Test loop condition
lw a0, -12(fp) # Load var: contains.i
sw a0, -16(fp) # Push on stack slot 4
lw a0, 4(fp) # Load var: contains.items
sw a0, -32(fp) # Push argument 0 from last.
addi sp, fp, -32 # Set SP to last argument.
jal $len # Invoke function: len
addi sp, fp, [email protected] # Set SP to stack frame top.
lw t0, -16(fp) # Pop stack slot 4
blt t0, a0, label_5 # Branch on <
li a0, 0 # Load boolean literal: false
j label_4 # Go to return
mv a0, zero # Load None
j label_4 # Jump to function epilogue
label_4: # Epilogue
.equiv @contains.size, 32
lw ra, -4(fp) # Get return address
lw fp, -8(fp) # Use control link to restore caller's fp
addi sp, sp, @contains.size # Restore stack pointer
jr ra # Return to caller
.globl alloc
alloc:
# Runtime support function alloc.
# Prototype address is in a0.
lw a1, 4(a0) # Get size of object in words
j alloc2 # Allocate object with exact size
.globl alloc2
alloc2:
# Runtime support function alloc2 (realloc).
# Prototype address is in a0.
# Number of words to allocate is in a1.
li a2, 4 # Word size in bytes
mul a2, a1, a2 # Calculate number of bytes to allocate
add a2, gp, a2 # Estimate where GP will move
bgeu a2, s11, alloc2_15 # Go to OOM handler if too large
lw t0, @.__obj_size__(a0) # Get size of object in words
mv t2, a0 # Initialize src ptr
mv t3, gp # Initialize dest ptr
alloc2_16: # Copy-loop header
lw t1, 0(t2) # Load next word from src
sw t1, 0(t3) # Store next word to dest
addi t2, t2, 4 # Increment src
addi t3, t3, 4 # Increment dest
addi t0, t0, -1 # Decrement counter
bne t0, zero, alloc2_16 # Loop if more words left to copy
mv a0, gp # Save new object's address to return
sw a1, @.__obj_size__(a0) # Set size of new object in words
# (same as requested size)
mv gp, a2 # Set next free slot in the heap
jr ra # Return to caller
alloc2_15: # OOM handler
li a0, @error_oom # Exit code for: Out of memory
la a1, const_7 # Load error message as str
addi a1, a1, @.__str__ # Load address of attribute __str__
j abort # Abort
.globl abort
abort:
# Runtime support function abort (does not return).
mv t0, a0 # Save exit code in temp
li a0, @print_string # Code for print_string ecall
ecall # Print error message in a1
li a1, 10 # Load newline character
li a0, @print_char # Code for print_char ecall
ecall # Print newline
mv a1, t0 # Move exit code to a1
li a0, @exit2 # Code for exit2 ecall
ecall # Exit with code
abort_17: # Infinite loop
j abort_17 # Prevent fallthrough
.globl heap.init
heap.init:
# Runtime support function heap.init.
mv a1, a0 # Move requested size to A1
li a0, @sbrk # Code for ecall: sbrk
ecall # Request A1 bytes
jr ra # Return to caller
.globl concat
concat:
addi sp, sp, -32
sw ra, 28(sp)
sw fp, 24(sp)
addi fp, sp, 32
sw s1, -12(fp)
sw s2, -16(fp)
sw s3, -20(fp)
sw s4, -24(fp)
sw s5, -28(fp)
lw t0, 4(fp)
lw t1, 0(fp)
beqz t0, concat_none
beqz t1, concat_none
lw t0, @.__len__(t0)
lw t1, @.__len__(t1)
add s5, t0, t1
addi a1, s5, @listHeaderWords
la a0, $.list$prototype
jal alloc2
sw s5, @.__len__(a0)
mv s5, a0
addi s3, s5, @.__elts__
lw s1, 4(fp)
lw s2, @.__len__(s1)
addi s1, s1, @.__elts__
lw s4, 12(fp)
concat_1:
beqz s2, concat_2
lw a0, 0(s1)
jalr ra, s4, 0
sw a0, 0(s3)
addi s2, s2, -1
addi s1, s1, 4
addi s3, s3, 4
j concat_1
concat_2:
lw s1, 0(fp)
lw s2, @.__len__(s1)
addi s1, s1, @.__elts__
lw s4, 8(fp)
concat_3:
beqz s2, concat_4
lw a0, 0(s1)
jalr ra, s4, 0
sw a0, 0(s3)
addi s2, s2, -1
addi s1, s1, 4
addi s3, s3, 4
j concat_3
concat_4:
mv a0, s5
lw s1, -12(fp)
lw s2, -16(fp)
lw s3, -20(fp)
lw s4, -24(fp)
lw s5, -28(fp)
lw ra, -4(fp)
lw fp, -8(fp)
addi sp, sp, 32
jr ra
concat_none:
j error.None
.globl conslist
conslist:
addi sp, sp, -8
sw ra, 4(sp)
sw fp, 0(sp)
addi fp, sp, 8
lw a1, 0(fp)
la a0, $.list$prototype
beqz a1, conslist_done
addi a1, a1, @listHeaderWords
jal alloc2
lw t0, 0(fp)
sw t0, @.__len__(a0)
slli t1, t0, 2
add t1, t1, fp
addi t2, a0, @.__elts__
conslist_1:
lw t3, 0(t1)
sw t3, 0(t2)
addi t1, t1, -4
addi t2, t2, 4
addi t0, t0, -1
bnez t0, conslist_1
conslist_done:
lw ra, -4(fp)
lw fp, -8(fp)
addi sp, sp, 8
jr ra
.globl strcat
strcat:
addi sp, sp, -12
sw ra, 8(sp)
sw fp, 4(sp)
addi fp, sp, 12
lw t0, 4(fp)
lw t1, 0(fp)
lw t0, @.__len__(t0)
beqz t0, strcat_4
lw t1, @.__len__(t1)
beqz t1, strcat_5
add t1, t0, t1
sw t1, -12(fp)
addi t1, t1, 4
srli t1, t1, 2
addi a1, t1, @listHeaderWords
la a0, $str$prototype
jal alloc2
lw t0, -12(fp)
sw t0, @.__len__(a0)
addi t2, a0, 16
lw t0, 4(fp)
lw t1, @.__len__(t0)
addi t0, t0, @.__str__
strcat_1:
beqz t1, strcat_2
lbu t3, 0(t0)
sb t3, 0(t2)
addi t1, t1, -1
addi t0, t0, 1
addi t2, t2, 1
j strcat_1
strcat_2:
lw t0, 0(fp)
lw t1, 12(t0)
addi t0, t0, 16
strcat_3:
beqz t1, strcat_6
lbu t3, 0(t0)
sb t3, 0(t2)
addi t1, t1, -1
addi t0, t0, 1
addi t2, t2, 1
j strcat_3
strcat_4:
lw a0, 0(fp)
j strcat_7
strcat_5:
lw a0, 4(fp)
j strcat_7
strcat_6:
sb zero, 0(t2)
strcat_7:
lw ra, -4(fp)
lw fp, -8(fp)
addi sp, sp, 12
jr ra
.globl streql
streql:
addi sp, sp, -8
sw ra, 4(sp)
sw fp, 0(sp)
addi fp, sp, 8
lw a1, 4(fp)
lw a2, 0(fp)
lw t0, @.__len__(a1)
lw t1, @.__len__(a2)
bne t0, t1, streql_no
streql_1:
lbu t2, @.__str__(a1)
lbu t3, @.__str__(a2)
bne t2, t3, streql_no
addi a1, a1, 1
addi a2, a2, 1
addi t0, t0, -1
bgtz t0, streql_1
li a0, 1
j streql_end
streql_no:
xor a0, a0, a0
streql_end:
lw ra, -4(fp)
lw fp, -8(fp)
addi sp, sp, 8
jr ra
.globl strneql
strneql:
addi sp, sp, -8
sw ra, 4(sp)
sw fp, 0(sp)
addi fp, sp, 8
lw a1, 4(fp)
lw a2, 0(fp)
lw t0, @.__len__(a1)
lw t1, @.__len__(a2)
bne t0, t1, strneql_yes
strneql_1:
lbu t2, @.__str__(a1)
lbu t3, @.__str__(a2)
bne t2, t3, strneql_yes
addi a1, a1, 1
addi a2, a2, 1
addi t0, t0, -1
bgtz t0, strneql_1
xor a0, a0, a0
j strneql_end
strneql_yes:
li a0, 1
strneql_end:
lw ra, -4(fp)
lw fp, -8(fp)
addi sp, sp, 8
jr ra
.globl makeint
makeint:
addi sp, sp, -8
sw ra, 4(sp)
sw a0, 0(sp)
la a0, $int$prototype
jal ra, alloc
lw t0, 0(sp)
sw t0, @.__int__(a0)
lw ra, 4(sp)
addi sp, sp, 8
jr ra
.globl makebool
makebool:
slli a0, a0, 4
la t0, @bool.False
add a0, a0, t0
jr ra
.globl noconv
noconv:
jr ra
.globl initchars
initchars:
jr ra
.globl error.None
error.None:
li a0, 4 # Exit code for: Operation on None
la a1, const_8 # Load error message as str
addi a1, a1, 16 # Load address of attribute __str__
j abort # Abort
.globl error.Div
error.Div:
li a0, 2 # Exit code for: Division by zero
la a1, const_9 # Load error message as str
addi a1, a1, 16 # Load address of attribute __str__
j abort # Abort
.globl error.OOB
error.OOB:
li a0, 3 # Exit code for: Index out of bounds
la a1, const_10 # Load error message as str
addi a1, a1, 16 # Load address of attribute __str__
j abort # Abort
.data
.globl const_0
const_0:
.word 2 # Type tag for class: bool
.word 4 # Object size
.word $bool$dispatchTable # Pointer to dispatch table
.word 0 # Constant value of attribute: __bool__
.align 2
.globl const_1
const_1:
.word 2 # Type tag for class: bool
.word 4 # Object size
.word $bool$dispatchTable # Pointer to dispatch table
.word 1 # Constant value of attribute: __bool__
.align 2
.globl const_3
const_3:
.word 3 # Type tag for class: str
.word 8 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 15 # Constant value of attribute: __len__
.string "Item not found." # Constant value of attribute: __str__
.align 2
.globl const_9
const_9:
.word 3 # Type tag for class: str
.word 9 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 16 # Constant value of attribute: __len__
.string "Division by zero" # Constant value of attribute: __str__
.align 2
.globl const_7
const_7:
.word 3 # Type tag for class: str
.word 8 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 13 # Constant value of attribute: __len__
.string "Out of memory" # Constant value of attribute: __str__
.align 2
.globl const_10
const_10:
.word 3 # Type tag for class: str
.word 9 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 19 # Constant value of attribute: __len__
.string "Index out of bounds" # Constant value of attribute: __str__
.align 2
.globl const_5
const_5:
.word 3 # Type tag for class: str
.word 6 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 4 # Constant value of attribute: __len__
.string "True" # Constant value of attribute: __str__
.align 2
.globl const_8
const_8:
.word 3 # Type tag for class: str
.word 9 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 17 # Constant value of attribute: __len__
.string "Operation on None" # Constant value of attribute: __str__
.align 2
.globl const_2
const_2:
.word 3 # Type tag for class: str
.word 7 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 11 # Constant value of attribute: __len__
.string "Item found!" # Constant value of attribute: __str__
.align 2
.globl const_4
const_4:
.word 3 # Type tag for class: str
.word 9 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 16 # Constant value of attribute: __len__
.string "Invalid argument" # Constant value of attribute: __str__
.align 2
.globl const_6
const_6:
.word 3 # Type tag for class: str
.word 6 # Object size
.word $str$dispatchTable # Pointer to dispatch table
.word 5 # Constant value of attribute: __len__
.string "False" # Constant value of attribute: __str__
.align 2