1 ----------------------------------------------------------------------
3 -- WARNING! You're entering a hackish area, proceed at your own risks!
5 -- This code results from the borrowing, then ruthless abuse, of
6 -- Yueliang's implementation of Lua 5.0 compiler. I claim
7 -- responsibility for all of the ugly, dirty stuff that you might spot
10 -- Eventually, this code will be rewritten, either in Lua or more
11 -- probably in C. Meanwhile, if you're interested into digging
12 -- metalua's sources, this is not the best part to invest your time
17 ----------------------------------------------------------------------
19 --[[--------------------------------------------------------------------
21 $Id: lcode.lua,v 1.5 2006/11/15 09:07:50 fab13n Exp $
24 Lua 5 code generator in Lua
25 This file is part of Yueliang.
27 Copyright (c) 2005 Kein-Hong Man <khman@users.sf.net>
28 The COPYRIGHT file describes the conditions
29 under which this software may be distributed.
31 See the ChangeLog for more information.
33 ------------------------------------------------------------------------
35 [FF] Slightly modified, mainly to produce Lua 5.1 bytecode.
38 Revision 1.5 2006/11/15 09:07:50 fab13n
39 debugged meta operators.
40 Added command line options handling.
42 Revision 1.4 2006/11/09 09:39:57 fab13n
45 Revision 1.3 2006/11/07 04:37:59 fab13n
46 first bootstrapping version.
48 Revision 1.2 2006/11/05 15:08:34 fab13n
49 updated code generation, to be compliant with 5.1
52 ----------------------------------------------------------------------]]
54 --[[--------------------------------------------------------------------
56 -- * one function manipulate a pointer argument with a simple data type
57 -- (can't be emulated by a table, ambiguous), now returns that value:
58 -- luaK:concat(fs, l1, l2)
59 -- * some function parameters changed to boolean, additional code
60 -- translates boolean back to 1/0 for instruction fields
62 -- luaK:ttisnumber(o) (from lobject.h)
63 -- luaK:nvalue(o) (from lobject.h)
64 -- luaK:setnilvalue(o) (from lobject.h)
65 -- luaK:setsvalue(o) (from lobject.h)
66 -- luaK:setnvalue(o) (from lobject.h)
67 -- luaK:sethvalue(o) (from lobject.h)
68 ----------------------------------------------------------------------]]
70 module("bytecode", package.seeall)
72 local function debugf() end
76 luaK.MAXSTACK = 250 -- (llimits.h, used in lcode.lua)
77 luaK.LUA_MULTRET = -1 -- (lua.h)
79 ------------------------------------------------------------------------
80 -- Marks the end of a patch list. It is an invalid value both as an absolute
81 -- address, and as a list link (would link an element to itself).
82 ------------------------------------------------------------------------
86 function luaK:isnumeral(e)
87 return e.k=="VKNUM" and e.t==self.NO_JUMP and e.t==self.NO_JUMP
90 ------------------------------------------------------------------------
91 -- emulation of TObject macros (these are from lobject.h)
92 -- * TObject is a table since lcode passes references around
93 -- * tt member field removed, using Lua's type() instead
94 ------------------------------------------------------------------------
95 function luaK:ttisnumber(o)
96 if o then return type(o.value) == "number" else return false end
98 function luaK:nvalue(o) return o.value end
99 function luaK:setnilvalue(o) o.value = nil end
100 function luaK:setsvalue(o, s) o.value = s end
101 luaK.setnvalue = luaK.setsvalue
102 luaK.sethvalue = luaK.setsvalue
104 ------------------------------------------------------------------------
105 -- returns the instruction object for given e (expdesc)
106 ------------------------------------------------------------------------
107 function luaK:getcode(fs, e)
108 return fs.f.code[e.info]
111 ------------------------------------------------------------------------
112 -- codes an instruction with a signed Bx (sBx) field
113 ------------------------------------------------------------------------
114 function luaK:codeAsBx(fs, o, A, sBx)
115 return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx)
118 ------------------------------------------------------------------------
120 ------------------------------------------------------------------------
121 function luaK:hasjumps(e)
125 ------------------------------------------------------------------------
127 ------------------------------------------------------------------------
128 function luaK:_nil(fs, from, n)
129 if fs.pc > fs.lasttarget then -- no jumps to current position?
130 if fs.pc == 0 then return end --function start, positions are already clean
131 local previous = fs.f.code[fs.pc - 1]
132 if luaP:GET_OPCODE(previous) == "OP_LOADNIL" then
133 local pfrom = luaP:GETARG_A(previous)
134 local pto = luaP:GETARG_B(previous)
135 if pfrom <= from and from <= pto + 1 then -- can connect both?
136 if from + n - 1 > pto then
137 luaP:SETARG_B(previous, from + n - 1)
143 self:codeABC(fs, "OP_LOADNIL", from, from + n - 1, 0) -- else no optimization
146 ------------------------------------------------------------------------
148 ------------------------------------------------------------------------
149 function luaK:jump(fs)
150 local jpc = fs.jpc -- save list of jumps to here
151 fs.jpc = self.NO_JUMP
152 local j = self:codeAsBx(fs, "OP_JMP", 0, self.NO_JUMP)
153 return self:concat(fs, j, jpc) -- keep them on hold
157 function luaK:ret (fs, first, nret)
158 luaK:codeABC (fs, "OP_RETURN", first, nret+1, 0)
162 ------------------------------------------------------------------------
164 ------------------------------------------------------------------------
165 function luaK:condjump(fs, op, A, B, C)
166 self:codeABC(fs, op, A, B, C)
170 ------------------------------------------------------------------------
172 ------------------------------------------------------------------------
173 function luaK:fixjump(fs, pc, dest)
174 local jmp = fs.f.code[pc]
175 local offset = dest - (pc + 1)
176 assert(dest ~= self.NO_JUMP)
177 if math.abs(offset) > luaP.MAXARG_sBx then
178 luaX:syntaxerror(fs.ls, "control structure too long")
180 luaP:SETARG_sBx(jmp, offset)
183 ------------------------------------------------------------------------
184 -- returns current 'pc' and marks it as a jump target (to avoid wrong
185 -- optimizations with consecutive instructions not in the same basic block).
186 ------------------------------------------------------------------------
187 function luaK:getlabel(fs)
188 fs.lasttarget = fs.pc
192 ------------------------------------------------------------------------
194 ------------------------------------------------------------------------
195 function luaK:getjump(fs, pc)
196 local offset = luaP:GETARG_sBx(fs.f.code[pc])
197 if offset == self.NO_JUMP then -- point to itself represents end of list
198 return self.NO_JUMP -- end of list
200 return (pc + 1) + offset -- turn offset into absolute position
204 ------------------------------------------------------------------------
206 ------------------------------------------------------------------------
207 function luaK:getjumpcontrol(fs, pc)
208 local pi = fs.f.code[pc]
209 local ppi = fs.f.code[pc - 1]
210 if pc >= 1 and luaP:testOpMode(luaP:GET_OPCODE(ppi), "OpModeT") then
217 ------------------------------------------------------------------------
218 -- check whether list has any jump that do not produce a value
219 -- (or produce an inverted value)
220 ------------------------------------------------------------------------
222 function luaK:need_value(fs, list, cond)
223 while list ~= self.NO_JUMP do
224 local i = self:getjumpcontrol(fs, list)
225 if luaP:GET_OPCODE(i) ~= "OP_TESTSET" or
226 luaP:GETARG_A(i) ~= luaP.NO_REG or
227 luaP:GETARG_C(i) ~= cond then
230 list = self:getjump(fs, list)
232 return false -- not found
235 ------------------------------------------------------------------------
237 ------------------------------------------------------------------------
239 function luaK:patchtestreg(fs, node, reg)
240 assert(reg) -- pour assurer, vu que j'ai ajoute un parametre p/r a 5.0
241 local i = self:getjumpcontrol(fs, node)
242 if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then
243 return false end -- cannot patch other instructions
244 if reg ~= luaP.NO_REG and reg ~= luaP:GETARG_B(i) then
245 luaP:SETARG_A(i, reg)
247 -- no register to put value or register already has the value
248 luaP:SET_OPCODE(i, "OP_TEST")
249 luaP:SETARG_A(i, luaP:GETARG_B(i))
251 luaP:SETARG_C(i, luaP:GETARG_C(i))
257 function luaK:removevalues (fs, list)
258 while list ~= self.NO_JUMP do
259 self:patchtestreg (fs, list, luaP.NO_REG)
260 list = self:getjump (fs, list)
264 ------------------------------------------------------------------------
266 ------------------------------------------------------------------------
267 function luaK:patchlistaux(fs, list, vtarget, reg, dtarget)
268 while list ~= self.NO_JUMP do
269 local _next = self:getjump(fs, list)
270 if self:patchtestreg (fs, list, reg) then
271 self:fixjump(fs, list, vtarget)
273 self:fixjump (fs, list, dtarget)
279 ------------------------------------------------------------------------
281 ------------------------------------------------------------------------
282 function luaK:dischargejpc(fs)
283 self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc)
284 fs.jpc = self.NO_JUMP
287 ------------------------------------------------------------------------
289 ------------------------------------------------------------------------
290 function luaK:patchlist(fs, list, target)
291 if target == fs.pc then
292 self:patchtohere(fs, list)
294 assert(target < fs.pc)
295 self:patchlistaux(fs, list, target, luaP.NO_REG, target)
299 ------------------------------------------------------------------------
301 ------------------------------------------------------------------------
302 function luaK:patchtohere(fs, list)
304 fs.jpc = self:concat(fs, fs.jpc, list)
307 ------------------------------------------------------------------------
308 -- * l1 was a pointer, now l1 is returned and callee assigns the value
309 ------------------------------------------------------------------------
310 function luaK:concat(fs, l1, l2)
311 if l2 == self.NO_JUMP then return l1 -- unchanged
312 elseif l1 == self.NO_JUMP then
316 local _next = self:getjump(fs, list)
317 while _next ~= self.NO_JUMP do -- find last element
319 _next = self:getjump(fs, list)
321 self:fixjump(fs, list, l2)
323 return l1 -- unchanged
326 ------------------------------------------------------------------------
328 ------------------------------------------------------------------------
329 function luaK:checkstack(fs, n)
330 local newstack = fs.freereg + n
331 if newstack > fs.f.maxstacksize then
332 if newstack >= luaK.MAXSTACK then
333 luaX:syntaxerror(fs.ls, "function or expression too complex")
335 fs.f.maxstacksize = newstack
339 ------------------------------------------------------------------------
341 ------------------------------------------------------------------------
342 function luaK:reserveregs(fs, n)
343 self:checkstack(fs, n)
344 fs.freereg = fs.freereg + n
347 ------------------------------------------------------------------------
349 ------------------------------------------------------------------------
350 function luaK:freereg(fs, reg)
351 if not luaP:ISK (reg) and reg >= fs.nactvar then
352 fs.freereg = fs.freereg - 1
353 assert(reg == fs.freereg,
354 string.format("reg=%i, fs.freereg=%i", reg, fs.freereg))
358 ------------------------------------------------------------------------
360 ------------------------------------------------------------------------
361 function luaK:freeexp(fs, e)
362 if e.k == "VNONRELOC" then
363 self:freereg(fs, e.info)
367 ------------------------------------------------------------------------
368 -- k is a constant, v is... what?
369 -- fs.h is a hash value --> index in f.k
370 ------------------------------------------------------------------------
371 -- * luaH_get, luaH_set deleted; direct table access used instead
372 -- * luaO_rawequalObj deleted in first assert
373 -- * setobj2n deleted in assignment of v to f.k table
374 ------------------------------------------------------------------------
375 --FF radically updated, not completely understood
376 function luaK:addk(fs, k, v)
377 local idx = fs.h[k.value]
379 -- local oldsize = f.sizek
380 if self:ttisnumber (idx) then
381 --TODO this assert currently FAILS
382 --assert(fs.f.k[self:nvalue(idx)] == v)
383 return self:nvalue(idx)
384 else -- constant not found; create a new entry
386 local t = type (v.value)
387 assert(t=="nil" or t=="string" or t=="number" or t=="boolean")
389 --debugf("[const: k[%i] = %s ]", fs.nk, tostringv(v.value))
392 self:setnvalue(fs.h[k.value], fs.nk)
399 ------------------------------------------------------------------------
401 ------------------------------------------------------------------------
402 function luaK:stringK(fs, s)
403 assert (type(s)=="string")
404 local o = {} -- TObject
406 return self:addk(fs, o, o)
409 ------------------------------------------------------------------------
411 ------------------------------------------------------------------------
412 function luaK:numberK(fs, r)
413 assert (type(r)=="number")
414 local o = {} -- TObject
416 return self:addk(fs, o, o)
419 ------------------------------------------------------------------------
421 ------------------------------------------------------------------------
422 function luaK:boolK(fs, r)
423 assert (type(r)=="boolean")
424 local o = {} -- TObject
426 return self:addk(fs, o, o)
429 ------------------------------------------------------------------------
431 ------------------------------------------------------------------------
432 function luaK:nilK(fs)
433 local k, v = {}, {} -- TObject
435 self:sethvalue(k, fs.h) -- cannot use nil as key; instead use table itself
436 return self:addk(fs, k, v)
441 function luaK:setreturns (fs, e, nresults)
442 if e.k == "VCALL" then -- expression is an open function call?
443 luaP:SETARG_C(self:getcode(fs, e), nresults + 1)
444 elseif e.k == "VVARARG" then
445 luaP:SETARG_B (self:getcode (fs, e), nresults + 1)
446 luaP:SETARG_A (self:getcode (fs, e), fs.freereg)
447 self:reserveregs (fs, 1)
452 function luaK:setmultret (fs, e)
453 self:setreturns (fs, e, self.LUA_MULTRET)
457 function luaK:setoneret (fs, e)
458 if e.k == "VCALL" then -- expression is an open function call?
460 e.info = luaP:GETARG_A(self:getcode(fs, e))
461 elseif e.k == "VVARARG" then
462 luaP:SETARG_B (self:getcode (fs, e), 2)
468 ------------------------------------------------------------------------
469 --FF deprecated in 5.1
470 ------------------------------------------------------------------------
471 function luaK:setcallreturns(fs, e, nresults)
472 assert (false, "setcallreturns deprecated")
475 --printv(self:getcode(fs, e))
476 if e.k == "VCALL" then -- expression is an open function call?
477 luaP:SETARG_C(self:getcode(fs, e), nresults + 1)
478 if nresults == 1 then -- 'regular' expression?
480 e.info = luaP:GETARG_A(self:getcode(fs, e))
482 elseif e.k == "VVARARG" then
483 --printf("Handle vararg return on expr %s, whose code is %s",
484 -- tostringv(e), tostringv(self:getcode(fs, e)))
485 if nresults == 1 then
486 luaP:SETARG_B (self:getcode (fs, e), 2)
488 --FIXME: why no SETARG_A???
490 luaP:SETARG_B (self:getcode (fs, e), nresults + 1)
491 luaP:SETARG_A (self:getcode (fs, e), fs.freereg)
492 self:reserveregs (fs, 1)
493 --printf("Now code is %s", tostringv(self:getcode(fs, e)))
498 ------------------------------------------------------------------------
499 -- Ajoute le code pour effectuer l'extraction de la locvar/upval/globvar
501 ------------------------------------------------------------------------
502 function luaK:dischargevars(fs, e)
503 --printf("\ndischargevars\n")
505 if k == "VLOCAL" then
507 elseif k == "VUPVAL" then
508 e.info = self:codeABC(fs, "OP_GETUPVAL", 0, e.info, 0)
510 elseif k == "VGLOBAL" then
511 e.info = self:codeABx(fs, "OP_GETGLOBAL", 0, e.info)
513 elseif k == "VINDEXED" then
514 self:freereg(fs, e.aux)
515 self:freereg(fs, e.info)
516 e.info = self:codeABC(fs, "OP_GETTABLE", 0, e.info, e.aux)
518 elseif k == "VCALL" or k == "VVARARG" then
519 self:setoneret(fs, e)
521 -- there is one value available (somewhere)
523 --printf("\n/dischargevars\n")
526 ------------------------------------------------------------------------
528 ------------------------------------------------------------------------
529 function luaK:code_label(fs, A, b, jump)
530 self:getlabel(fs) -- those instructions may be jump targets
531 return self:codeABC(fs, "OP_LOADBOOL", A, b, jump)
534 ------------------------------------------------------------------------
536 ------------------------------------------------------------------------
537 function luaK:discharge2reg(fs, e, reg)
538 self:dischargevars(fs, e)
541 self:_nil(fs, reg, 1)
542 elseif k == "VFALSE" or k == "VTRUE" then
543 self:codeABC(fs, "OP_LOADBOOL", reg, (e.k == "VTRUE") and 1 or 0, 0)
544 elseif k == "VKNUM" then
545 self:codeABx (fs, "OP_LOADK", reg, self:numberK(fs, e.nval))
546 elseif k == "VK" then
547 self:codeABx(fs, "OP_LOADK", reg, e.info)
548 elseif k == "VRELOCABLE" then
549 local pc = self:getcode(fs, e)
550 luaP:SETARG_A(pc, reg)
551 elseif k == "VNONRELOC" then
552 if reg ~= e.info then
553 self:codeABC(fs, "OP_MOVE", reg, e.info, 0)
556 assert(e.k == "VVOID" or e.k == "VJMP")
557 return -- nothing to do...
563 ------------------------------------------------------------------------
565 ------------------------------------------------------------------------
566 function luaK:discharge2anyreg(fs, e)
567 if e.k ~= "VNONRELOC" then
568 self:reserveregs(fs, 1)
569 self:discharge2reg(fs, e, fs.freereg - 1)
573 ------------------------------------------------------------------------
575 ------------------------------------------------------------------------
576 function luaK:exp2reg(fs, e, reg)
577 self:discharge2reg(fs, e, reg)
578 if e.k == "VJMP" then
579 e.t = self:concat(fs, e.t, e.info) -- put this jump in 't' list
581 if self:hasjumps(e) then
582 local final -- position after whole expression
583 local p_f = self.NO_JUMP -- position of an eventual LOAD false
584 local p_t = self.NO_JUMP -- position of an eventual LOAD true
585 if self:need_value(fs, e.t, 1) or self:need_value(fs, e.f, 0) then
586 local fj = self.NO_JUMP -- first jump (over LOAD ops.)
587 if e.k ~= "VJMP" then fj = self:jump(fs) end
588 p_f = self:code_label(fs, reg, 0, 1)
589 p_t = self:code_label(fs, reg, 1, 0)
590 self:patchtohere(fs, fj)
592 final = self:getlabel(fs)
593 self:patchlistaux(fs, e.f, final, reg, p_f)
594 self:patchlistaux(fs, e.t, final, reg, p_t)
596 e.f, e.t = self.NO_JUMP, self.NO_JUMP
601 ------------------------------------------------------------------------
603 ------------------------------------------------------------------------
604 function luaK:exp2nextreg(fs, e)
605 self:dischargevars(fs, e)
606 --[FF] Allready in place (added for expr.Stat)
607 if e.k == "VNONRELOC" and e.info == fs.freereg then
610 self:reserveregs(fs, 1)
611 self:exp2reg(fs, e, fs.freereg - 1)
614 ------------------------------------------------------------------------
616 ------------------------------------------------------------------------
617 function luaK:exp2anyreg(fs, e)
618 --printf("exp2anyregs(e=%s)", tostringv(e))
619 self:dischargevars(fs, e)
620 if e.k == "VNONRELOC" then
621 if not self:hasjumps(e) then -- exp is already in a register
624 if e.info >= fs.nactvar then -- reg. is not a local?
625 self:exp2reg(fs, e, e.info) -- put value on it
629 self:exp2nextreg(fs, e) -- default
633 ------------------------------------------------------------------------
635 ------------------------------------------------------------------------
636 function luaK:exp2val(fs, e)
637 if self:hasjumps(e) then
638 self:exp2anyreg(fs, e)
640 self:dischargevars(fs, e)
644 ------------------------------------------------------------------------
646 ------------------------------------------------------------------------
647 function luaK:exp2RK(fs, e)
650 if k=="VNIL" or k=="VTRUE" or k=="VFALSE" or k=="VKNUM" then
651 if fs.nk <= luaP.MAXINDEXRK then
652 if k=="VNIL" then e.info = self:nilK(fs)
653 elseif k=="VKNUM" then e.info = self:numberK (fs, e.nval)
654 else e.info = self:boolK(fs, e.k=="VTRUE") end
656 return luaP:RKASK(e.info)
658 elseif k == "VK" then
659 if e.info <= luaP.MAXINDEXRK then -- constant fit in argC?
660 return luaP:RKASK (e.info)
663 -- not a constant in the right range: put it in a register
664 return self:exp2anyreg(fs, e)
667 ------------------------------------------------------------------------
669 ------------------------------------------------------------------------
670 function luaK:storevar(fs, var, exp)
672 --printf("var=%s", tostringv(var))
673 --printf("exp=%s", tostringv(exp))
676 if k == "VLOCAL" then
677 self:freeexp(fs, exp)
678 self:exp2reg(fs, exp, var.info)
680 elseif k == "VUPVAL" then
681 local e = self:exp2anyreg(fs, exp)
682 self:codeABC(fs, "OP_SETUPVAL", e, var.info, 0)
683 elseif k == "VGLOBAL" then
684 --printf("store global, exp=%s", tostringv(exp))
685 local e = self:exp2anyreg(fs, exp)
686 self:codeABx(fs, "OP_SETGLOBAL", e, var.info)
687 elseif k == "VINDEXED" then
688 local e = self:exp2RK(fs, exp)
689 self:codeABC(fs, "OP_SETTABLE", var.info, var.aux, e)
691 assert(0) -- invalid var kind to store
693 self:freeexp(fs, exp)
697 ------------------------------------------------------------------------
699 ------------------------------------------------------------------------
700 function luaK:_self(fs, e, key)
701 self:exp2anyreg(fs, e)
703 local func = fs.freereg
704 self:reserveregs(fs, 2)
705 self:codeABC(fs, "OP_SELF", func, e.info, self:exp2RK(fs, key))
706 self:freeexp(fs, key)
711 ------------------------------------------------------------------------
713 ------------------------------------------------------------------------
714 function luaK:invertjump(fs, e)
715 --printf("invertjump on jump instruction #%i", e.info)
716 --printv(self:getcode(fs, e))
717 local pc = self:getjumpcontrol(fs, e.info)
718 assert(luaP:testOpMode(luaP:GET_OPCODE(pc), "OpModeT") and
719 luaP:GET_OPCODE(pc) ~= "OP_TESTSET" and
720 luaP:GET_OPCODE(pc) ~= "OP_TEST")
721 --printf("Before invert:")
723 luaP:SETARG_A(pc, (luaP:GETARG_A(pc) == 0) and 1 or 0)
724 --printf("After invert:")
728 ------------------------------------------------------------------------
730 ------------------------------------------------------------------------
731 function luaK:jumponcond(fs, e, cond)
732 if e.k == "VRELOCABLE" then
733 local ie = self:getcode(fs, e)
734 if luaP:GET_OPCODE(ie) == "OP_NOT" then
735 fs.pc = fs.pc - 1 -- remove previous OP_NOT
736 return self:condjump(fs, "OP_TEST", luaP:GETARG_B(ie), 0,
741 self:discharge2anyreg(fs, e)
743 return self:condjump(fs, "OP_TESTSET", luaP.NO_REG, e.info, cond and 1 or 0)
746 ------------------------------------------------------------------------
748 ------------------------------------------------------------------------
749 function luaK:goiftrue(fs, e)
750 local pc -- pc of last jump
751 self:dischargevars(fs, e)
753 if k == "VK" or k == "VTRUE" or k == "VKNUM" then
754 pc = self.NO_JUMP -- always true; do nothing
755 elseif k == "VFALSE" then
756 pc = self:jump(fs) -- always jump
757 elseif k == "VJMP" then
758 self:invertjump(fs, e)
761 pc = self:jumponcond(fs, e, false)
763 e.f = self:concat(fs, e.f, pc) -- insert last jump in 'f' list
764 self:patchtohere(fs, e.t)
768 ------------------------------------------------------------------------
770 ------------------------------------------------------------------------
771 function luaK:goiffalse(fs, e)
772 local pc -- pc of last jump
773 self:dischargevars(fs, e)
775 if k == "VNIL" or k == "VFALSE"then
776 pc = self.NO_JUMP -- always false; do nothing
777 elseif k == "VTRUE" then
778 pc = self:jump(fs) -- always jump
779 elseif k == "VJMP" then
782 pc = self:jumponcond(fs, e, true)
784 e.t = self:concat(fs, e.t, pc) -- insert last jump in 't' list
785 self:patchtohere(fs, e.f)
789 ------------------------------------------------------------------------
791 ------------------------------------------------------------------------
792 function luaK:codenot(fs, e)
793 self:dischargevars(fs, e)
795 if k == "VNIL" or k == "VFALSE" then
797 elseif k == "VK" or k == "VKNUM" or k == "VTRUE" then
799 elseif k == "VJMP" then
800 self:invertjump(fs, e)
801 elseif k == "VRELOCABLE" or k == "VNONRELOC" then
802 self:discharge2anyreg(fs, e)
804 e.info = self:codeABC(fs, "OP_NOT", 0, e.info, 0)
807 assert(0) -- cannot happen
809 -- interchange true and false lists
811 self:removevalues(fs, e.f)
812 self:removevalues(fs, e.t)
815 ------------------------------------------------------------------------
817 ------------------------------------------------------------------------
818 function luaK:indexed(fs, t, k)
819 t.aux = self:exp2RK(fs, k)
824 function luaK:constfolding (op, e1, e2)
825 if not self:isnumeral(e1) or not self:isnumeral(e2) then return false end
826 local v1, v2, e, r = e1.nval, e2 and e2.nval, nil
827 if op == "OP_ADD" then r = v1+v2
828 elseif op == "OP_SUB" then r = v1-v2
829 elseif op == "OP_MUL" then r = v1*v2
830 elseif op == "OP_DIV" then if v2==0 then return false end r = v1/v2
831 elseif op == "OP_MOD" then if v2==0 then return false end r = v1%v2
832 elseif op == "OP_POW" then r = v1^v2
833 elseif op == "OP_UNM" then r = -v1
834 elseif op == "OP_LEN" then return false
835 else assert (false, "Unknown numeric value") end
841 function luaK:codearith (fs, op, e1, e2)
842 if self:constfolding (op, e1, e2) then return else
843 local o1 = self:exp2RK (fs, e1)
845 if op ~= "OP_UNM" and op ~= "OP_LEN" then
846 o2 = self:exp2RK (fs, e2) end
849 e1.info = self:codeABC (fs, op, 0, o1, o2)
855 function luaK:codecomp (fs, op, cond, e1, e2)
856 assert (type (cond) == "boolean")
857 local o1 = self:exp2RK (fs, e1)
858 local o2 = self:exp2RK (fs, e2)
859 self:freeexp (fs, e2)
860 self:freeexp (fs, e1)
861 if not cond and op ~= "OP_EQ" then
862 local temp = o1; o1=o2; o2=temp cond = true end
863 e1.info = self:condjump (fs, op, cond and 1 or 0, o1, o2)
867 ------------------------------------------------------------------------
869 ------------------------------------------------------------------------
870 function luaK:prefix (fs, op, e)
871 local e2 = { t = self.NO_JUMP; f = self.NO_JUMP;
872 k = "VKNUM"; nval = 0 }
875 self:exp2anyreg (fs, e) end
876 self:codearith (fs, "OP_UNM", e, e2)
877 elseif op == "not" then
879 elseif op == "len" then
880 self:exp2anyreg (fs, e)
881 self:codearith (fs, "OP_LEN", e, e2)
883 assert (false, "Unknown unary operator")
887 ------------------------------------------------------------------------
889 ------------------------------------------------------------------------
890 function luaK:infix (fs, op, v)
893 elseif op == "or" then
894 self:goiffalse(fs, v)
895 elseif op == "concat" then
896 self:exp2nextreg(fs, v) -- operand must be on the 'stack'
898 if not self:isnumeral (v) then self:exp2RK(fs, v) end
902 ------------------------------------------------------------------------
904 -- grep "ORDER OPR" if you change these enums
905 ------------------------------------------------------------------------
906 luaK.arith_opc = { -- done as a table lookup instead of a calc
916 luaK.test_opc = { -- was ops[] in the codebinop function
917 eq = {opc="OP_EQ", cond=true},
918 lt = {opc="OP_LT", cond=true},
919 le = {opc="OP_LE", cond=true},
921 -- Pseudo-ops, with no metatable equivalent:
922 ne = {opc="OP_EQ", cond=false},
923 gt = {opc="OP_LT", cond=false},
924 ge = {opc="OP_LE", cond=false}
927 ------------------------------------------------------------------------
929 ------------------------------------------------------------------------
930 function luaK:posfix(fs, op, e1, e2)
932 assert(e1.t == self.NO_JUMP) -- list must be closed
933 self:dischargevars(fs, e2)
934 e2.f = self:concat(fs, e2.f, e1.f)
935 for k,v in pairs(e2) do e1[k]=v end -- *e1 = *e2
936 elseif op == "or" then
937 assert(e1.f == self.NO_JUMP) -- list must be closed
938 self:dischargevars(fs, e2)
939 e2.t = self:concat(fs, e2.t, e1.t)
940 for k,v in pairs(e2) do e1[k]=v end -- *e1 = *e2
941 elseif op == "concat" then
943 if e2.k == "VRELOCABLE"
944 and luaP:GET_OPCODE(self:getcode(fs, e2)) == "OP_CONCAT" then
945 assert(e1.info == luaP:GETARG_B(self:getcode(fs, e2)) - 1)
947 luaP:SETARG_B(self:getcode(fs, e2), e1.info)
948 e1.k = "VRELOCABLE"; e1.info = e2.info
950 self:exp2nextreg(fs, e2)
951 self:codearith (fs, "OP_CONCAT", e1, e2)
954 local opc = self.arith_opc[op]
955 if opc then self:codearith (fs, opc, e1, e2) else
956 opc = self.test_opc[op] or error ("Unknown operator "..op)
957 self:codecomp (fs, opc.opc, opc.cond, e1, e2)
962 ------------------------------------------------------------------------
964 ------------------------------------------------------------------------
965 function luaK:fixline(fs, line)
967 fs.f.lineinfo[fs.pc - 1] = line or 0
970 ------------------------------------------------------------------------
972 ------------------------------------------------------------------------
973 function luaK:code(fs, i, line)
979 for _,x in ipairs{"A","B","Bx", "sBx", "C"} do
980 if i[x] then table.insert (params, string.format ("%s=%i", x, i[x])) end
982 debugf ("[code:\t%s\t%s]", luaP.opnames[i.OP], table.concat (params, ", "))
985 self:dischargejpc(fs) -- 'pc' will change
986 -- put new instruction in code array
987 --FF luaY:growvector(fs.L, f.code, fs.pc, f.sizecode, nil,
988 --FF luaY.MAX_INT, "code size overflow")
990 -- save corresponding line information
991 --FF luaY:growvector(fs.L, f.lineinfo, fs.pc, f.sizelineinfo, nil,
992 --FF luaY.MAX_INT, "code size overflow")
993 f.lineinfo[fs.pc] = line
999 ------------------------------------------------------------------------
1001 ------------------------------------------------------------------------
1002 function luaK:codeABC(fs, o, a, b, c)
1003 assert(luaP:getOpMode(o) == "iABC", o.." is not an ABC operation")
1004 --assert getbmode(o) ~= opargn or b == 0
1005 --assert getcmode(o) ~= opargn or c == 0
1007 --return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.ls.lastline)
1008 return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.lastline)
1011 ------------------------------------------------------------------------
1013 ------------------------------------------------------------------------
1014 function luaK:codeABx(fs, o, a, bc)
1015 assert(luaP:getOpMode(o) == "iABx" or luaP:getOpMode(o) == "iAsBx")
1016 --assert getcmode(o) == opargn
1018 --return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.ls.lastline)
1019 return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.lastline)
1022 ------------------------------------------------------------------------
1024 ------------------------------------------------------------------------
1025 function luaK:setlist (fs, base, nelems, tostore)
1026 local c = math.floor ((nelems-1) / luaP.LFIELDS_PER_FLUSH + 1)
1027 local b = tostore == self.LUA_MULTRET and 0 or tostore
1028 assert (tostore ~= 0)
1029 if c <= luaP.MAXARG_C then self:codeABC (fs, "OP_SETLIST", base, b, c)
1031 self:codeABC (fs, "OP_SETLIST", base, b, 0)
1032 self:code (fs, c, fs.lastline)--FIXME
1034 fs.freereg = base + 1