1 -------------------------------------------------------------------------------
2 -- Copyright (c) 2005-2013 Kein-Hong Man, Fabien Fleutot and others.
4 -- All rights reserved.
6 -- This program and the accompanying materials are made available
7 -- under the terms of the Eclipse Public License v1.0 which
8 -- accompanies this distribution, and is available at
9 -- http://www.eclipse.org/legal/epl-v10.html
11 -- This program and the accompanying materials are also made available
12 -- under the terms of the MIT public license which accompanies this
13 -- distribution, and is available at http://www.lua.org/license.html
16 -- Kein-Hong Man - Initial implementation for Lua 5.0, part of Yueliang
17 -- Fabien Fleutot - Port to Lua 5.1, integration with Metalua
19 -------------------------------------------------------------------------------
21 --[[--------------------------------------------------------------------
26 Lua 5 code generator in Lua
27 This file is part of Yueliang.
29 Copyright (c) 2005 Kein-Hong Man <khman@users.sf.net>
30 The COPYRIGHT file describes the conditions
31 under which this software may be distributed.
33 See the ChangeLog for more information.
35 ------------------------------------------------------------------------
37 [FF] Slightly modified, mainly to produce Lua 5.1 bytecode.
39 ----------------------------------------------------------------------]]
41 --[[--------------------------------------------------------------------
43 -- * one function manipulate a pointer argument with a simple data type
44 -- (can't be emulated by a table, ambiguous), now returns that value:
45 -- luaK:concat(fs, l1, l2)
46 -- * some function parameters changed to boolean, additional code
47 -- translates boolean back to 1/0 for instruction fields
49 -- luaK:ttisnumber(o) (from lobject.h)
50 -- luaK:nvalue(o) (from lobject.h)
51 -- luaK:setnilvalue(o) (from lobject.h)
52 -- luaK:setsvalue(o) (from lobject.h)
53 -- luaK:setnvalue(o) (from lobject.h)
54 -- luaK:sethvalue(o) (from lobject.h)
55 ----------------------------------------------------------------------]]
57 local luaP = require 'metalua.compiler.bytecode.lopcodes'
59 local function debugf() end
63 luaK.MAXSTACK = 250 -- (llimits.h, used in lcode.lua)
64 luaK.LUA_MULTRET = -1 -- (lua.h)
66 ------------------------------------------------------------------------
67 -- Marks the end of a patch list. It is an invalid value both as an absolute
68 -- address, and as a list link (would link an element to itself).
69 ------------------------------------------------------------------------
73 function luaK:isnumeral(e)
74 return e.k=="VKNUM" and e.t==self.NO_JUMP and e.t==self.NO_JUMP
77 ------------------------------------------------------------------------
78 -- emulation of TObject macros (these are from lobject.h)
79 -- * TObject is a table since lcode passes references around
80 -- * tt member field removed, using Lua's type() instead
81 ------------------------------------------------------------------------
82 function luaK:ttisnumber(o)
83 if o then return type(o.value) == "number" else return false end
85 function luaK:nvalue(o) return o.value end
86 function luaK:setnilvalue(o) o.value = nil end
87 function luaK:setsvalue(o, s) o.value = s end
88 luaK.setnvalue = luaK.setsvalue
89 luaK.sethvalue = luaK.setsvalue
91 ------------------------------------------------------------------------
92 -- returns the instruction object for given e (expdesc)
93 ------------------------------------------------------------------------
94 function luaK:getcode(fs, e)
95 return fs.f.code[e.info]
98 ------------------------------------------------------------------------
99 -- codes an instruction with a signed Bx (sBx) field
100 ------------------------------------------------------------------------
101 function luaK:codeAsBx(fs, o, A, sBx)
102 return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx)
105 ------------------------------------------------------------------------
107 ------------------------------------------------------------------------
108 function luaK:hasjumps(e)
112 ------------------------------------------------------------------------
114 ------------------------------------------------------------------------
115 function luaK:_nil(fs, from, n)
116 if fs.pc > fs.lasttarget then -- no jumps to current position?
117 if fs.pc == 0 then return end --function start, positions are already clean
118 local previous = fs.f.code[fs.pc - 1]
119 if luaP:GET_OPCODE(previous) == "OP_LOADNIL" then
120 local pfrom = luaP:GETARG_A(previous)
121 local pto = luaP:GETARG_B(previous)
122 if pfrom <= from and from <= pto + 1 then -- can connect both?
123 if from + n - 1 > pto then
124 luaP:SETARG_B(previous, from + n - 1)
130 self:codeABC(fs, "OP_LOADNIL", from, from + n - 1, 0) -- else no optimization
133 ------------------------------------------------------------------------
135 ------------------------------------------------------------------------
136 function luaK:jump(fs)
137 local jpc = fs.jpc -- save list of jumps to here
138 fs.jpc = self.NO_JUMP
139 local j = self:codeAsBx(fs, "OP_JMP", 0, self.NO_JUMP)
140 return self:concat(fs, j, jpc) -- keep them on hold
144 function luaK:ret (fs, first, nret)
145 luaK:codeABC (fs, "OP_RETURN", first, nret+1, 0)
149 ------------------------------------------------------------------------
151 ------------------------------------------------------------------------
152 function luaK:condjump(fs, op, A, B, C)
153 self:codeABC(fs, op, A, B, C)
157 ------------------------------------------------------------------------
159 ------------------------------------------------------------------------
160 function luaK:fixjump(fs, pc, dest)
161 local jmp = fs.f.code[pc]
162 local offset = dest - (pc + 1)
163 assert(dest ~= self.NO_JUMP)
164 if math.abs(offset) > luaP.MAXARG_sBx then
165 error("control structure too long")
167 luaP:SETARG_sBx(jmp, offset)
170 ------------------------------------------------------------------------
171 -- returns current 'pc' and marks it as a jump target (to avoid wrong
172 -- optimizations with consecutive instructions not in the same basic block).
173 ------------------------------------------------------------------------
174 function luaK:getlabel(fs)
175 fs.lasttarget = fs.pc
179 ------------------------------------------------------------------------
181 ------------------------------------------------------------------------
182 function luaK:getjump(fs, pc)
183 local offset = luaP:GETARG_sBx(fs.f.code[pc])
184 if offset == self.NO_JUMP then -- point to itself represents end of list
185 return self.NO_JUMP -- end of list
187 return (pc + 1) + offset -- turn offset into absolute position
191 ------------------------------------------------------------------------
193 ------------------------------------------------------------------------
194 function luaK:getjumpcontrol(fs, pc)
195 local pi = fs.f.code[pc]
196 local ppi = fs.f.code[pc - 1]
197 if pc >= 1 and luaP:testOpMode(luaP:GET_OPCODE(ppi), "OpModeT") then
204 ------------------------------------------------------------------------
205 -- check whether list has any jump that do not produce a value
206 -- (or produce an inverted value)
207 ------------------------------------------------------------------------
209 function luaK:need_value(fs, list, cond)
210 while list ~= self.NO_JUMP do
211 local i = self:getjumpcontrol(fs, list)
212 if luaP:GET_OPCODE(i) ~= "OP_TESTSET" or
213 luaP:GETARG_A(i) ~= luaP.NO_REG or
214 luaP:GETARG_C(i) ~= cond then
217 list = self:getjump(fs, list)
219 return false -- not found
222 ------------------------------------------------------------------------
224 ------------------------------------------------------------------------
226 function luaK:patchtestreg(fs, node, reg)
227 assert(reg) -- pour assurer, vu que j'ai ajoute un parametre p/r a 5.0
228 local i = self:getjumpcontrol(fs, node)
229 if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then
230 return false end -- cannot patch other instructions
231 if reg ~= luaP.NO_REG and reg ~= luaP:GETARG_B(i) then
232 luaP:SETARG_A(i, reg)
234 -- no register to put value or register already has the value
235 luaP:SET_OPCODE(i, "OP_TEST")
236 luaP:SETARG_A(i, luaP:GETARG_B(i))
238 luaP:SETARG_C(i, luaP:GETARG_C(i))
244 function luaK:removevalues (fs, list)
245 while list ~= self.NO_JUMP do
246 self:patchtestreg (fs, list, luaP.NO_REG)
247 list = self:getjump (fs, list)
251 ------------------------------------------------------------------------
253 ------------------------------------------------------------------------
254 function luaK:patchlistaux(fs, list, vtarget, reg, dtarget)
255 while list ~= self.NO_JUMP do
256 local _next = self:getjump(fs, list)
257 if self:patchtestreg (fs, list, reg) then
258 self:fixjump(fs, list, vtarget)
260 self:fixjump (fs, list, dtarget)
266 ------------------------------------------------------------------------
268 ------------------------------------------------------------------------
269 function luaK:dischargejpc(fs)
270 self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc)
271 fs.jpc = self.NO_JUMP
274 ------------------------------------------------------------------------
276 ------------------------------------------------------------------------
277 function luaK:patchlist(fs, list, target)
278 if target == fs.pc then
279 self:patchtohere(fs, list)
281 assert(target < fs.pc)
282 self:patchlistaux(fs, list, target, luaP.NO_REG, target)
286 ------------------------------------------------------------------------
288 ------------------------------------------------------------------------
289 function luaK:patchtohere(fs, list)
291 fs.jpc = self:concat(fs, fs.jpc, list)
294 ------------------------------------------------------------------------
295 -- * l1 was a pointer, now l1 is returned and callee assigns the value
296 ------------------------------------------------------------------------
297 function luaK:concat(fs, l1, l2)
298 if l2 == self.NO_JUMP then return l1 -- unchanged
299 elseif l1 == self.NO_JUMP then
303 local _next = self:getjump(fs, list)
304 while _next ~= self.NO_JUMP do -- find last element
306 _next = self:getjump(fs, list)
308 self:fixjump(fs, list, l2)
310 return l1 -- unchanged
313 ------------------------------------------------------------------------
315 ------------------------------------------------------------------------
316 function luaK:checkstack(fs, n)
317 local newstack = fs.freereg + n
318 if newstack > fs.f.maxstacksize then
319 if newstack >= luaK.MAXSTACK then
320 error("function or expression too complex")
322 fs.f.maxstacksize = newstack
326 ------------------------------------------------------------------------
328 ------------------------------------------------------------------------
329 function luaK:reserveregs(fs, n)
330 self:checkstack(fs, n)
331 fs.freereg = fs.freereg + n
334 ------------------------------------------------------------------------
336 ------------------------------------------------------------------------
337 function luaK:freereg(fs, reg)
338 if not luaP:ISK (reg) and reg >= fs.nactvar then
339 fs.freereg = fs.freereg - 1
340 assert(reg == fs.freereg,
341 string.format("reg=%i, fs.freereg=%i", reg, fs.freereg))
345 ------------------------------------------------------------------------
347 ------------------------------------------------------------------------
348 function luaK:freeexp(fs, e)
349 if e.k == "VNONRELOC" then
350 self:freereg(fs, e.info)
354 ------------------------------------------------------------------------
355 -- k is a constant, v is... what?
356 -- fs.h is a hash value --> index in f.k
357 ------------------------------------------------------------------------
358 -- * luaH_get, luaH_set deleted; direct table access used instead
359 -- * luaO_rawequalObj deleted in first assert
360 -- * setobj2n deleted in assignment of v to f.k table
361 ------------------------------------------------------------------------
362 --FF radically updated, not completely understood
363 function luaK:addk(fs, k, v)
364 local idx = fs.h[k.value]
366 -- local oldsize = f.sizek
367 if self:ttisnumber (idx) then
368 --TODO this assert currently FAILS
369 --assert(fs.f.k[self:nvalue(idx)] == v)
370 return self:nvalue(idx)
371 else -- constant not found; create a new entry
373 local t = type (v.value)
374 assert(t=="nil" or t=="string" or t=="number" or t=="boolean")
376 --debugf("[const: k[%i] = %s ]", fs.nk, tostringv(v.value))
379 self:setnvalue(fs.h[k.value], fs.nk)
386 ------------------------------------------------------------------------
388 ------------------------------------------------------------------------
389 function luaK:stringK(fs, s)
390 assert (type(s)=="string")
391 local o = {} -- TObject
393 return self:addk(fs, o, o)
396 ------------------------------------------------------------------------
398 ------------------------------------------------------------------------
399 function luaK:numberK(fs, r)
400 assert (type(r)=="number")
401 local o = {} -- TObject
403 return self:addk(fs, o, o)
406 ------------------------------------------------------------------------
408 ------------------------------------------------------------------------
409 function luaK:boolK(fs, r)
410 assert (type(r)=="boolean")
411 local o = {} -- TObject
413 return self:addk(fs, o, o)
416 ------------------------------------------------------------------------
418 ------------------------------------------------------------------------
419 function luaK:nilK(fs)
420 local k, v = {}, {} -- TObject
422 self:sethvalue(k, fs.h) -- cannot use nil as key; instead use table itself
423 return self:addk(fs, k, v)
428 function luaK:setreturns (fs, e, nresults)
429 if e.k == "VCALL" then -- expression is an open function call?
430 luaP:SETARG_C(self:getcode(fs, e), nresults + 1)
431 elseif e.k == "VVARARG" then
432 luaP:SETARG_B (self:getcode (fs, e), nresults + 1)
433 luaP:SETARG_A (self:getcode (fs, e), fs.freereg)
434 self:reserveregs (fs, 1)
439 function luaK:setmultret (fs, e)
440 self:setreturns (fs, e, self.LUA_MULTRET)
444 function luaK:setoneret (fs, e)
445 if e.k == "VCALL" then -- expression is an open function call?
447 e.info = luaP:GETARG_A(self:getcode(fs, e))
448 elseif e.k == "VVARARG" then
449 luaP:SETARG_B (self:getcode (fs, e), 2)
455 ------------------------------------------------------------------------
456 --FF deprecated in 5.1
457 ------------------------------------------------------------------------
458 function luaK:setcallreturns(fs, e, nresults)
459 assert (false, "setcallreturns deprecated")
462 --printv(self:getcode(fs, e))
463 if e.k == "VCALL" then -- expression is an open function call?
464 luaP:SETARG_C(self:getcode(fs, e), nresults + 1)
465 if nresults == 1 then -- 'regular' expression?
467 e.info = luaP:GETARG_A(self:getcode(fs, e))
469 elseif e.k == "VVARARG" then
470 --printf("Handle vararg return on expr %s, whose code is %s",
471 -- tostringv(e), tostringv(self:getcode(fs, e)))
472 if nresults == 1 then
473 luaP:SETARG_B (self:getcode (fs, e), 2)
475 --FIXME: why no SETARG_A???
477 luaP:SETARG_B (self:getcode (fs, e), nresults + 1)
478 luaP:SETARG_A (self:getcode (fs, e), fs.freereg)
479 self:reserveregs (fs, 1)
480 --printf("Now code is %s", tostringv(self:getcode(fs, e)))
485 ------------------------------------------------------------------------
486 -- Ajoute le code pour effectuer l'extraction de la locvar/upval/globvar
488 ------------------------------------------------------------------------
489 function luaK:dischargevars(fs, e)
490 --printf("\ndischargevars\n")
492 if k == "VLOCAL" then
494 elseif k == "VUPVAL" then
495 e.info = self:codeABC(fs, "OP_GETUPVAL", 0, e.info, 0)
497 elseif k == "VGLOBAL" then
498 e.info = self:codeABx(fs, "OP_GETGLOBAL", 0, e.info)
500 elseif k == "VINDEXED" then
501 self:freereg(fs, e.aux)
502 self:freereg(fs, e.info)
503 e.info = self:codeABC(fs, "OP_GETTABLE", 0, e.info, e.aux)
505 elseif k == "VCALL" or k == "VVARARG" then
506 self:setoneret(fs, e)
508 -- there is one value available (somewhere)
510 --printf("\n/dischargevars\n")
513 ------------------------------------------------------------------------
515 ------------------------------------------------------------------------
516 function luaK:code_label(fs, A, b, jump)
517 self:getlabel(fs) -- those instructions may be jump targets
518 return self:codeABC(fs, "OP_LOADBOOL", A, b, jump)
521 ------------------------------------------------------------------------
523 ------------------------------------------------------------------------
524 function luaK:discharge2reg(fs, e, reg)
525 self:dischargevars(fs, e)
528 self:_nil(fs, reg, 1)
529 elseif k == "VFALSE" or k == "VTRUE" then
530 self:codeABC(fs, "OP_LOADBOOL", reg, (e.k == "VTRUE") and 1 or 0, 0)
531 elseif k == "VKNUM" then
532 self:codeABx (fs, "OP_LOADK", reg, self:numberK(fs, e.nval))
533 elseif k == "VK" then
534 self:codeABx(fs, "OP_LOADK", reg, e.info)
535 elseif k == "VRELOCABLE" then
536 local pc = self:getcode(fs, e)
537 luaP:SETARG_A(pc, reg)
538 elseif k == "VNONRELOC" then
539 if reg ~= e.info then
540 self:codeABC(fs, "OP_MOVE", reg, e.info, 0)
543 assert(e.k == "VVOID" or e.k == "VJMP")
544 return -- nothing to do...
550 ------------------------------------------------------------------------
552 ------------------------------------------------------------------------
553 function luaK:discharge2anyreg(fs, e)
554 if e.k ~= "VNONRELOC" then
555 self:reserveregs(fs, 1)
556 self:discharge2reg(fs, e, fs.freereg - 1)
560 ------------------------------------------------------------------------
562 ------------------------------------------------------------------------
563 function luaK:exp2reg(fs, e, reg)
564 self:discharge2reg(fs, e, reg)
565 if e.k == "VJMP" then
566 e.t = self:concat(fs, e.t, e.info) -- put this jump in 't' list
568 if self:hasjumps(e) then
569 local final -- position after whole expression
570 local p_f = self.NO_JUMP -- position of an eventual LOAD false
571 local p_t = self.NO_JUMP -- position of an eventual LOAD true
572 if self:need_value(fs, e.t, 1) or self:need_value(fs, e.f, 0) then
573 local fj = self.NO_JUMP -- first jump (over LOAD ops.)
574 if e.k ~= "VJMP" then fj = self:jump(fs) end
575 p_f = self:code_label(fs, reg, 0, 1)
576 p_t = self:code_label(fs, reg, 1, 0)
577 self:patchtohere(fs, fj)
579 final = self:getlabel(fs)
580 self:patchlistaux(fs, e.f, final, reg, p_f)
581 self:patchlistaux(fs, e.t, final, reg, p_t)
583 e.f, e.t = self.NO_JUMP, self.NO_JUMP
588 ------------------------------------------------------------------------
590 ------------------------------------------------------------------------
591 function luaK:exp2nextreg(fs, e)
592 self:dischargevars(fs, e)
593 --[FF] Allready in place (added for expr.Stat)
594 if e.k == "VNONRELOC" and e.info == fs.freereg then
595 --printf("Expression already in next reg %i: %s", fs.freereg, tostringv(e))
598 self:reserveregs(fs, 1)
599 self:exp2reg(fs, e, fs.freereg - 1)
602 ------------------------------------------------------------------------
604 ------------------------------------------------------------------------
605 function luaK:exp2anyreg(fs, e)
606 --printf("exp2anyregs(e=%s)", tostringv(e))
607 self:dischargevars(fs, e)
608 if e.k == "VNONRELOC" then
609 if not self:hasjumps(e) then -- exp is already in a register
612 if e.info >= fs.nactvar then -- reg. is not a local?
613 self:exp2reg(fs, e, e.info) -- put value on it
617 self:exp2nextreg(fs, e) -- default
621 ------------------------------------------------------------------------
623 ------------------------------------------------------------------------
624 function luaK:exp2val(fs, e)
625 if self:hasjumps(e) then
626 self:exp2anyreg(fs, e)
628 self:dischargevars(fs, e)
632 ------------------------------------------------------------------------
634 ------------------------------------------------------------------------
635 function luaK:exp2RK(fs, e)
638 if k=="VNIL" or k=="VTRUE" or k=="VFALSE" or k=="VKNUM" then
639 if fs.nk <= luaP.MAXINDEXRK then
640 if k=="VNIL" then e.info = self:nilK(fs)
641 elseif k=="VKNUM" then e.info = self:numberK (fs, e.nval)
642 else e.info = self:boolK(fs, e.k=="VTRUE") end
644 return luaP:RKASK(e.info)
646 elseif k == "VK" then
647 if e.info <= luaP.MAXINDEXRK then -- constant fit in argC?
648 return luaP:RKASK (e.info)
651 -- not a constant in the right range: put it in a register
652 return self:exp2anyreg(fs, e)
655 ------------------------------------------------------------------------
657 ------------------------------------------------------------------------
658 function luaK:storevar(fs, var, exp)
660 --printf("var=%s", tostringv(var))
661 --printf("exp=%s", tostringv(exp))
664 if k == "VLOCAL" then
665 self:freeexp(fs, exp)
666 self:exp2reg(fs, exp, var.info)
668 elseif k == "VUPVAL" then
669 local e = self:exp2anyreg(fs, exp)
670 self:codeABC(fs, "OP_SETUPVAL", e, var.info, 0)
671 elseif k == "VGLOBAL" then
672 --printf("store global, exp=%s", tostringv(exp))
673 local e = self:exp2anyreg(fs, exp)
674 self:codeABx(fs, "OP_SETGLOBAL", e, var.info)
675 elseif k == "VINDEXED" then
676 local e = self:exp2RK(fs, exp)
677 self:codeABC(fs, "OP_SETTABLE", var.info, var.aux, e)
679 assert(0) -- invalid var kind to store
681 self:freeexp(fs, exp)
685 ------------------------------------------------------------------------
687 ------------------------------------------------------------------------
688 function luaK:_self(fs, e, key)
689 self:exp2anyreg(fs, e)
691 local func = fs.freereg
692 self:reserveregs(fs, 2)
693 self:codeABC(fs, "OP_SELF", func, e.info, self:exp2RK(fs, key))
694 self:freeexp(fs, key)
699 ------------------------------------------------------------------------
701 ------------------------------------------------------------------------
702 function luaK:invertjump(fs, e)
703 --printf("invertjump on jump instruction #%i", e.info)
704 --printv(self:getcode(fs, e))
705 local pc = self:getjumpcontrol(fs, e.info)
706 assert(luaP:testOpMode(luaP:GET_OPCODE(pc), "OpModeT") and
707 luaP:GET_OPCODE(pc) ~= "OP_TESTSET" and
708 luaP:GET_OPCODE(pc) ~= "OP_TEST")
709 --printf("Before invert:")
711 luaP:SETARG_A(pc, (luaP:GETARG_A(pc) == 0) and 1 or 0)
712 --printf("After invert:")
716 ------------------------------------------------------------------------
718 ------------------------------------------------------------------------
719 function luaK:jumponcond(fs, e, cond)
720 if e.k == "VRELOCABLE" then
721 local ie = self:getcode(fs, e)
722 if luaP:GET_OPCODE(ie) == "OP_NOT" then
723 fs.pc = fs.pc - 1 -- remove previous OP_NOT
724 return self:condjump(fs, "OP_TEST", luaP:GETARG_B(ie), 0,
729 self:discharge2anyreg(fs, e)
731 return self:condjump(fs, "OP_TESTSET", luaP.NO_REG, e.info, cond and 1 or 0)
734 ------------------------------------------------------------------------
736 ------------------------------------------------------------------------
737 function luaK:goiftrue(fs, e)
738 local pc -- pc of last jump
739 self:dischargevars(fs, e)
741 if k == "VK" or k == "VTRUE" or k == "VKNUM" then
742 pc = self.NO_JUMP -- always true; do nothing
743 elseif k == "VFALSE" then
744 pc = self:jump(fs) -- always jump
745 elseif k == "VJMP" then
746 self:invertjump(fs, e)
749 pc = self:jumponcond(fs, e, false)
751 e.f = self:concat(fs, e.f, pc) -- insert last jump in 'f' list
752 self:patchtohere(fs, e.t)
756 ------------------------------------------------------------------------
758 ------------------------------------------------------------------------
759 function luaK:goiffalse(fs, e)
760 local pc -- pc of last jump
761 self:dischargevars(fs, e)
763 if k == "VNIL" or k == "VFALSE"then
764 pc = self.NO_JUMP -- always false; do nothing
765 elseif k == "VTRUE" then
766 pc = self:jump(fs) -- always jump
767 elseif k == "VJMP" then
770 pc = self:jumponcond(fs, e, true)
772 e.t = self:concat(fs, e.t, pc) -- insert last jump in 't' list
773 self:patchtohere(fs, e.f)
777 ------------------------------------------------------------------------
779 ------------------------------------------------------------------------
780 function luaK:codenot(fs, e)
781 self:dischargevars(fs, e)
783 if k == "VNIL" or k == "VFALSE" then
785 elseif k == "VK" or k == "VKNUM" or k == "VTRUE" then
787 elseif k == "VJMP" then
788 self:invertjump(fs, e)
789 elseif k == "VRELOCABLE" or k == "VNONRELOC" then
790 self:discharge2anyreg(fs, e)
792 e.info = self:codeABC(fs, "OP_NOT", 0, e.info, 0)
795 assert(0) -- cannot happen
797 -- interchange true and false lists
799 self:removevalues(fs, e.f)
800 self:removevalues(fs, e.t)
803 ------------------------------------------------------------------------
805 ------------------------------------------------------------------------
806 function luaK:indexed(fs, t, k)
807 t.aux = self:exp2RK(fs, k)
812 function luaK:constfolding (op, e1, e2)
813 if not self:isnumeral(e1) or not self:isnumeral(e2) then return false end
814 local v1, v2, e, r = e1.nval, e2 and e2.nval, nil
815 if op == "OP_ADD" then r = v1+v2
816 elseif op == "OP_SUB" then r = v1-v2
817 elseif op == "OP_MUL" then r = v1*v2
818 elseif op == "OP_DIV" then if v2==0 then return false end r = v1/v2
819 elseif op == "OP_MOD" then if v2==0 then return false end r = v1%v2
820 elseif op == "OP_POW" then r = v1^v2
821 elseif op == "OP_UNM" then r = -v1
822 elseif op == "OP_LEN" then return false
823 else assert (false, "Unknown numeric value") end
829 function luaK:codearith (fs, op, e1, e2)
830 if self:constfolding (op, e1, e2) then return else
831 local o1 = self:exp2RK (fs, e1)
833 if op ~= "OP_UNM" and op ~= "OP_LEN" then
834 o2 = self:exp2RK (fs, e2) end
837 e1.info = self:codeABC (fs, op, 0, o1, o2)
843 function luaK:codecomp (fs, op, cond, e1, e2)
844 assert (type (cond) == "boolean")
845 local o1 = self:exp2RK (fs, e1)
846 local o2 = self:exp2RK (fs, e2)
847 self:freeexp (fs, e2)
848 self:freeexp (fs, e1)
849 if not cond and op ~= "OP_EQ" then
850 local temp = o1; o1=o2; o2=temp cond = true end
851 e1.info = self:condjump (fs, op, cond and 1 or 0, o1, o2)
855 ------------------------------------------------------------------------
857 ------------------------------------------------------------------------
858 function luaK:prefix (fs, op, e)
859 local e2 = { t = self.NO_JUMP; f = self.NO_JUMP;
860 k = "VKNUM"; nval = 0 }
863 self:exp2anyreg (fs, e) end
864 self:codearith (fs, "OP_UNM", e, e2)
865 elseif op == "not" then
867 elseif op == "len" then
868 self:exp2anyreg (fs, e)
869 self:codearith (fs, "OP_LEN", e, e2)
871 assert (false, "Unknown unary operator")
875 ------------------------------------------------------------------------
877 ------------------------------------------------------------------------
878 function luaK:infix (fs, op, v)
881 elseif op == "or" then
882 self:goiffalse(fs, v)
883 elseif op == "concat" then
884 self:exp2nextreg(fs, v) -- operand must be on the 'stack'
886 if not self:isnumeral (v) then self:exp2RK(fs, v) end
890 ------------------------------------------------------------------------
892 -- grep "ORDER OPR" if you change these enums
893 ------------------------------------------------------------------------
894 luaK.arith_opc = { -- done as a table lookup instead of a calc
904 luaK.test_opc = { -- was ops[] in the codebinop function
905 eq = {opc="OP_EQ", cond=true},
906 lt = {opc="OP_LT", cond=true},
907 le = {opc="OP_LE", cond=true},
909 -- Pseudo-ops, with no metatable equivalent:
910 ne = {opc="OP_EQ", cond=false},
911 gt = {opc="OP_LT", cond=false},
912 ge = {opc="OP_LE", cond=false}
915 ------------------------------------------------------------------------
917 ------------------------------------------------------------------------
918 function luaK:posfix(fs, op, e1, e2)
920 assert(e1.t == self.NO_JUMP) -- list must be closed
921 self:dischargevars(fs, e2)
922 e2.f = self:concat(fs, e2.f, e1.f)
923 for k,v in pairs(e2) do e1[k]=v end -- *e1 = *e2
924 elseif op == "or" then
925 assert(e1.f == self.NO_JUMP) -- list must be closed
926 self:dischargevars(fs, e2)
927 e2.t = self:concat(fs, e2.t, e1.t)
928 for k,v in pairs(e2) do e1[k]=v end -- *e1 = *e2
929 elseif op == "concat" then
931 if e2.k == "VRELOCABLE"
932 and luaP:GET_OPCODE(self:getcode(fs, e2)) == "OP_CONCAT" then
933 assert(e1.info == luaP:GETARG_B(self:getcode(fs, e2)) - 1)
935 luaP:SETARG_B(self:getcode(fs, e2), e1.info)
936 e1.k = "VRELOCABLE"; e1.info = e2.info
938 self:exp2nextreg(fs, e2)
939 self:codearith (fs, "OP_CONCAT", e1, e2)
942 local opc = self.arith_opc[op]
943 if opc then self:codearith (fs, opc, e1, e2) else
944 opc = self.test_opc[op] or error ("Unknown operator "..op)
945 self:codecomp (fs, opc.opc, opc.cond, e1, e2)
950 ------------------------------------------------------------------------
952 ------------------------------------------------------------------------
953 function luaK:fixline(fs, line)
956 --print(debug.traceback "fixline (line == nil)")
958 fs.f.lineinfo[fs.pc - 1] = line or 0
961 ------------------------------------------------------------------------
963 ------------------------------------------------------------------------
964 function luaK:code(fs, i, line)
967 --print(debug.traceback "line == nil")
973 for _,x in ipairs{"A","B","Bx", "sBx", "C"} do
974 if i[x] then table.insert (params, string.format ("%s=%i", x, i[x])) end
976 debugf ("[code:\t%s\t%s]", luaP.opnames[i.OP], table.concat (params, ", "))
979 self:dischargejpc(fs) -- 'pc' will change
982 f.lineinfo[fs.pc] = line
985 f.lineinfo[fs.pc] = fs.lastline
986 if fs.lastline == 0 then
987 --print(debug.traceback())
991 if f.lineinfo[fs.pc] == 0 then
992 f.lineinfo[fs.pc] = 42
1000 ------------------------------------------------------------------------
1002 ------------------------------------------------------------------------
1003 function luaK:codeABC(fs, o, a, b, c)
1004 assert(luaP:getOpMode(o) == "iABC", o.." is not an ABC operation")
1005 --assert getbmode(o) ~= opargn or b == 0
1006 --assert getcmode(o) ~= opargn or c == 0
1008 --return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.ls.lastline)
1009 return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.lastline)
1012 ------------------------------------------------------------------------
1014 ------------------------------------------------------------------------
1015 function luaK:codeABx(fs, o, a, bc)
1016 assert(luaP:getOpMode(o) == "iABx" or luaP:getOpMode(o) == "iAsBx")
1017 --assert getcmode(o) == opargn
1019 --return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.ls.lastline)
1020 return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.lastline)
1023 ------------------------------------------------------------------------
1025 ------------------------------------------------------------------------
1026 function luaK:setlist (fs, base, nelems, tostore)
1027 local c = math.floor ((nelems-1) / luaP.LFIELDS_PER_FLUSH + 1)
1028 local b = tostore == self.LUA_MULTRET and 0 or tostore
1029 assert (tostore ~= 0)
1030 if c <= luaP.MAXARG_C then self:codeABC (fs, "OP_SETLIST", base, b, c)
1032 self:codeABC (fs, "OP_SETLIST", base, b, 0)
1033 self:code (fs, c, fs.lastline)--FIXME
1035 fs.freereg = base + 1