summaryrefslogtreecommitdiff
path: root/py/compile.c
AgeCommit message (Collapse)Author
2018-05-23py/emit: Combine load/store/delete subscr into one emit function.Damien George
Reduces code size by: bare-arm: -8 minimal x86: -104 unix x64: -312 unix nanbox: -120 stm32: -60 cc3200: -16 esp8266: -92 esp32: -24
2018-05-23py/emit: Combine name and global into one func for load/store/delete.Damien George
Reduces code size by: bare-arm: -56 minimal x86: -300 unix x64: -576 unix nanbox: -300 stm32: -164 cc3200: -56 esp8266: -236 esp32: -76
2018-05-23py/emit: Combine build tuple/list/map emit funcs into one.Damien George
Reduces code size by: bare-arm: -24 minimal x86: -192 unix x64: -288 unix nanbox: -184 stm32: -72 cc3200: -16 esp8266: -148 esp32: -32
2018-05-23py/emit: Combine yield value and yield-from emit funcs into one.Damien George
Reduces code size by: bare-arm: -24 minimal x86: -72 unix x64: -200 unix nanbox: -72 stm32: -52 cc3200: -32 esp8266: -84 esp32: -24
2018-05-23py/emit: Combine fast and deref into one function for load/store/delete.Damien George
Reduces code size by: bare-arm: -16 minimal x86: -208 unix x64: -408 unix nanbox: -248 stm32: -12 cc3200: -24 esp8266: -96 esp32: -44
2018-05-18py/compile: Change comment about ITER_BUF_NSLOTS to a static assertion.Damien George
2018-02-24py/compile: Adjust c_assign_atom_expr() to use return instead of goto.Damien George
Makes the flow of the function a little more obvious, and allows to reach 100% coverage of compile.c when using gcov.
2018-02-04py/compile: Combine compiler-opt of 2 and 3 tuple-to-tuple assignment.Damien George
This patch combines the compiler optimisation code for double and triple tuple-to-tuple assignment, taking it from two separate if-blocks to one combined if-block. This can be done because the code for both of these optimisations has a lot in common. Combining them together reduces code size for ports that have the triple-tuple optimisation enabled (and doesn't change code size for ports that have it disabled).
2017-12-11py: Convert all uses of alloca() to use new scoped allocation API.Damien George
2017-11-01py/compile: Use alloca instead of qstr_build when compiling import name.Damien George
The technique of using alloca is how dotted import names are composed in mp_import_from and mp_builtin___import__, so use the same technique in the compiler. This puts less pressure on the heap (only the stack is used if the qstr already exists, and if it doesn't exist then the standard qstr block memory is used for the new qstr rather than a separate chunk of the heap) and reduces overall code size.
2017-08-21py/compile: Remove unused pn_colon code when compiling func params.Damien George
2017-07-31all: Use the name MicroPython consistently in commentsAlexander Steffen
There were several different spellings of MicroPython present in comments, when there should be only one.
2017-07-09py/compile: Fix enum variable declaration.Damien George
2017-07-05py/compile: Use switch-case to match token and operator.Krzysztof Blazewicz
Reduces code size.
2017-07-05py/compile: Combine arith and bit-shift ops into 1 compile routine.Krzysztof Blazewicz
This refactoring saves code space.
2017-06-22py/compile: Optimise emitter label indices to save a word of heap.Damien George
Previous to this patch, a label with value "0" was used to indicate an invalid label, but that meant a wasted word (at slot 0) in the array of label offsets. This patch adjusts the label indices so the first one starts at 0, and the maximum value indicates an invalid label.
2017-06-22py/compile: Fix bug with break/continue in else of optimised for-range.Damien George
This patch fixes a bug whereby the Python stack was not correctly reset if there was a break/continue statement in the else black of an optimised for-range loop. For example, in the following code the "j" variable from the inner for loop was not being popped off the Python stack: for i in range(4): for j in range(4): pass else: continue This is now fixed with this patch.
2017-06-14py/compile: Raise SyntaxError if positional args are given after */**.Damien George
In CPython 3.4 this raises a SyntaxError. In CPython 3.5+ having a positional after * is allowed but uPy has the wrong semantics and passes the arguments in the incorrect order. To prevent incorrect use of a function going unnoticed it is important to raise the SyntaxError in uPy, until the behaviour is fixed to follow CPython 3.5+.
2017-05-29various: Spelling fixesVille Skyttä
2017-04-22py: Add LOAD_SUPER_METHOD bytecode to allow heap-free super meth calls.Damien George
This patch allows the following code to run without allocating on the heap: super().foo(...) Before this patch such a call would allocate a super object on the heap and then load the foo method and call it right away. The super object is only needed to perform the lookup of the method and not needed after that. This patch makes an optimisation to allocate the super object on the C stack and discard it right after use. Changes in code size due to this patch are: bare-arm: +128 minimal: +232 unix x64: +416 unix nanbox: +364 stmhal: +184 esp8266: +340 cc3200: +128
2017-04-22py/compile: Refactor handling of special super() call.Damien George
This patch refactors the handling of the special super() call within the compiler. It removes the need for a global (to the compiler) state variable which keeps track of whether the subject of an expression is super. The handling of super() is now done entirely within one function, which makes the compiler a bit cleaner and allows to easily add more optimisations to super calls. Changes to the code size are: bare-arm: +12 minimal: +0 unix x64: +48 unix nanbox: -16 stmhal: +4 cc3200: +0 esp8266: -56
2017-04-22py/compile: Don't do unnecessary check if iter parse node is a struct.Damien George
If we get to this point in the code then pn_iter is guaranteed to be a struct.
2017-04-22py/compile: Add COMP_RETURN_IF_EXPR option to enable return-if-else opt.Damien George
With this optimisation enabled the compiler optimises the if-else expression within a return statement. The optimisation reduces bytecode size by 2 bytes for each use of such a return-if-else statement. Since such a statement is not often used, and costs bytes for the code, the feature is disabled by default. For example the following code: def f(x): return 1 if x else 2 compiles to this bytecode with the optimisation disabled (left column is bytecode offset in bytes): 00 LOAD_FAST 0 01 POP_JUMP_IF_FALSE 8 04 LOAD_CONST_SMALL_INT 1 05 JUMP 9 08 LOAD_CONST_SMALL_INT 2 09 RETURN_VALUE and to this bytecode with the optimisation enabled: 00 LOAD_FAST 0 01 POP_JUMP_IF_FALSE 6 04 LOAD_CONST_SMALL_INT 1 05 RETURN_VALUE 06 LOAD_CONST_SMALL_INT 2 07 RETURN_VALUE So the JUMP to RETURN_VALUE is optimised and replaced by RETURN_VALUE, saving 2 bytes and making the code a bit faster.
2017-04-22py/compile: Extract parse-node kind at start of func for efficiency.Damien George
Otherwise the type of parse-node and its kind has to be re-extracted multiple times. This optimisation reduces code size by a bit (16 bytes on bare-arm).
2017-04-22py/compile: Don't do unnecessary check if parse node is a struct.Damien George
PN_atom_expr_normal parse nodes always have structs for their second sub-node, so simplify the check for the sub-node kind to save code size.
2017-04-05py: Raise a ValueError if range() step is zero.Damien George
Following CPython. Otherwise one gets either an infinite loop (if code is optimised by the uPy compiler) or possibly a divide-by-zero CPU exception.
2017-03-29py/compile: Provide terse error message for invalid dict/set literals.Damien George
2017-03-29py: Shorten a couple of error messages.Damien George
2017-03-29py/compile: Simplify syntax-error messages for illegal assignments.Damien George
With this patch all illegal assignments are reported as "can't assign to expression". Before the patch there were special cases for a literal on the LHS, and for augmented assignments (eg +=), but it seems a waste of bytes (and there are lots of bytes used in error messages) to spend on distinguishing such errors which a user will rarely encounter.
2017-03-27py/compile: When compiling super(), handle closed-over self variable.Damien George
The self variable may be closed-over in the function, and in that case the call to super() should load the contents of the closure cell using LOAD_DEREF (before this patch it would just load the cell directly).
2017-03-23py: Define and use MP_OBJ_ITER_BUF_NSLOTS to get size of stack iter buf.Damien George
It improves readability of code and reduces the chance to make a mistake. This patch also fixes a bug with nan-boxing builds by rounding up the calculation of the new NSLOTS variable, giving the correct number of slots (being 4) even if mp_obj_t is larger than the native machine size.
2017-02-24py: Create str/bytes objects in the parser, not the compiler.Damien George
Previous to this patch any non-interned str/bytes objects would create a special parse node that held a copy of the str/bytes data. Then in the compiler this data would be turned into a str/bytes object. This actually lead to 2 copies of the data, one in the parse node and one in the object. The parse node's copy of the data would be freed at the end of the compile stage but nevertheless it meant that the peak memory usage of the parse/compile stage was higher than it needed to be (by an amount equal to the number of bytes in all the non-interned str/bytes objects). This patch changes the behaviour so that str/bytes objects are created directly in the parser and the object stored in a const-object parse node (which already exists for bignum, float and complex const objects). This reduces peak RAM usage of the parse/compile stage, simplifies the parser and compiler, and reduces code size by about 170 bytes on Thumb2 archs, and by about 300 bytes on Xtensa archs.
2017-02-17py: Do adjacent str/bytes literal concatenation in lexer, not compiler.Damien George
It's much more efficient in RAM and code size to do implicit literal string concatenation in the lexer, as opposed to the compiler. RAM usage is reduced because the concatenation can be done right away in the tokeniser by just accumulating the string/bytes literals into the lexer's vstr. Prior to this patch adjacent strings/bytes would create a parse tree (one node per string/bytes) and then in the compiler a whole new chunk of memory was allocated to store the concatenated string, which used more than double the memory compared to just accumulating in the lexer. This patch also significantly reduces code size: bare-arm: -204 minimal: -204 unix x64: -328 stmhal: -208 esp8266: -284 cc3200: -224
2017-02-16py/grammar: Group no-compile grammar rules together to shrink tables.Damien George
Grammar rules have 2 variants: ones that are attached to a specific compile function which is called to compile that grammar node, and ones that don't have a compile function and are instead just inspected to see what form they take. In the compiler there is a table of all grammar rules, with each entry having a pointer to the associated compile function. Those rules with no compile function have a null pointer. There are 120 such rules, so that's 120 words of essentially wasted code space. By grouping together the compile vs no-compile rules we can put all the no-compile rules at the end of the list of rules, and then we don't need to store the null pointers. We just have a truncated table and it's guaranteed that when indexing this table we only index the first half, the half with populated pointers. This patch implements such a grouping by having a specific macro for the compile vs no-compile grammar rules (DEF_RULE vs DEF_RULE_NC). It saves around 460 bytes of code on 32-bit archs.
2017-02-16py/compile: Optimise list/dict/set comprehensions to use stack iter.Damien George
2017-02-16py: Remove unused "use_stack" argument from for_iter_end emit function.Damien George
2017-02-16py: Optimise storage of iterator so it takes only 4 slots on Py stack.Damien George
2017-02-16py: Make FOR_ITER opcode pop 1+4 slots from the stack when finished.Damien George
The extra 4 slots correspond to the iterator object stored on the stack.
2017-02-16py: Allow bytecode/native to put iter_buf on stack for simple for loops.Damien George
So that the "for x in it: ..." statement can now work without using the heap (so long as the iterator argument fits in an iter_buf structure).
2016-12-19py/compile: Add an extra pass for Xtensa inline assembler.Damien George
It needs an extra pass to compute the size of the constant table for the l32r instructions.
2016-12-09py/emitinline: Move common code for end of final pass to compiler.Damien George
This patch moves some common code from the individual inline assemblers to the compiler, the code that calls the emit-glue to assign the machine code to the functions scope.
2016-12-09py/emitinline: Move inline-asm align and data methods to compiler.Damien George
These are generic methods that don't depend on the architecture and so can be handled directly by the compiler.
2016-12-09py: Add inline Xtensa assembler.Damien George
This patch adds the MICROPY_EMIT_INLINE_XTENSA option, which, when enabled, allows the @micropython.asm_xtensa decorator to be used. The following opcodes are currently supported (ax is a register, a0-a15): ret_n() callx0(ax) j(label) jx(ax) beqz(ax, label) bnez(ax, label) mov(ax, ay) movi(ax, imm) # imm can be full 32-bit, uses l32r if needed and_(ax, ay, az) or_(ax, ay, az) xor(ax, ay, az) add(ax, ay, az) sub(ax, ay, az) mull(ax, ay, az) l8ui(ax, ay, imm) l16ui(ax, ay, imm) l32i(ax, ay, imm) s8i(ax, ay, imm) s16i(ax, ay, imm) s32i(ax, ay, imm) l16si(ax, ay, imm) addi(ax, ay, imm) ball(ax, ay, label) bany(ax, ay, label) bbc(ax, ay, label) bbs(ax, ay, label) beq(ax, ay, label) bge(ax, ay, label) bgeu(ax, ay, label) blt(ax, ay, label) bnall(ax, ay, label) bne(ax, ay, label) bnone(ax, ay, label) Upon entry to the assembly function the registers a0, a12, a13, a14 are pushed to the stack and the stack pointer (a1) decreased by 16. Upon exit, these registers and the stack pointer are restored, and ret.n is executed to return to the caller (caller address is in a0). Note that the ABI for the Xtensa emitters is non-windowing.
2016-12-09py: Allow inline-assembler emitter to be generic.Damien George
This patch refactors some code so that it is easier to integrate new inline assemblers for different architectures other than ARM Thumb.
2016-12-09py: Integrate Xtensa assembler into native emitter.Damien George
The config option MICROPY_EMIT_XTENSA can now be enabled to target the Xtensa architecture with @micropython.native and @micropython.viper decorators.
2016-12-07py/compile: Simplify configuration of native emitter.Damien George
2016-11-26py/compile: Remove comment about TODO for short circuiting for if-stmt.Damien George
Short circuiting is handled correctly by c_if_cond, and constants within short-circuit expressions are optimised by the parser.
2016-11-15py/parse: Make mp_parse_node_new_leaf an inline function.Damien George
It is split into 2 functions, one to make small ints and the other to make a non-small-int leaf node. This reduces code size by 32 bytes on bare-arm, 64 bytes on unix (x64-64) and 144 bytes on stmhal.
2016-11-15py/parse: Move function to check for const parse node to parse.[ch].Damien George
2016-10-12py/compile: Remove debugging code for compiler dispatch.Damien George
It was a relic from the days of developing the compiler and is no longer needed, and it's impossible to trigger via a test.