JS: Corrected shift operators. Made casting between ints behave like C does.

This commit is contained in:
Yuriy Glukhov 2016-01-22 18:30:07 +02:00
commit d2ecd84f67
4 changed files with 86 additions and 17 deletions

View file

@ -264,7 +264,7 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
["", "", "($1 - $2)", "($1 - $2)"], # SubF64
["", "", "($1 * $2)", "($1 * $2)"], # MulF64
["", "", "($1 / $2)", "($1 / $2)"], # DivF64
["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI
["", "", "", ""], # ShrI
["", "", "($1 << $2)", "($1 << $2)"], # ShlI
["", "", "($1 & $2)", "($1 & $2)"], # BitandI
["", "", "($1 | $2)", "($1 | $2)"], # BitorI
@ -344,19 +344,22 @@ proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
r.res = frmt % [x.rdLoc, y.rdLoc]
r.kind = resExpr
proc unsignedTrimmer(size: BiggestInt): Rope =
case size
of 1: rope"& 0xff"
of 2: rope"& 0xffff"
of 4: rope">>> 0"
else: rope""
proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string, reassign: bool = false) =
var x, y: TCompRes
gen(p, n.sons[1], x)
gen(p, n.sons[2], y)
let trimmer = case n[1].typ.skipTypes(abstractRange).size
of 1: "& 0xff"
of 2: "& 0xffff"
of 4: ">>> 0"
else: ""
let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
if reassign:
r.res = "$1 = (($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, rope trimmer]
r.res = "$1 = (($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
else:
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, rope trimmer]
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
proc ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
var x, y, z: TCompRes
@ -392,6 +395,12 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mSubU: binaryUintExpr(p, n, r, "-")
of mMulU: binaryUintExpr(p, n, r, "*")
of mDivU: binaryUintExpr(p, n, r, "/")
of mShrI:
var x, y: TCompRes
gen(p, n.sons[1], x)
gen(p, n.sons[2], y)
let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
r.res = "(($1 $2) >>> $3)" % [x.rdLoc, trimmer, y.rdLoc]
else:
arithAux(p, n, r, op, jsOps)
r.kind = resExpr
@ -1569,6 +1578,37 @@ proc genPragma(p: PProc, n: PNode) =
of wEmit: genAsmOrEmitStmt(p, it.sons[1])
else: discard
proc genCast(p: PProc, n: PNode, r: var TCompRes) =
var dest = skipTypes(n.typ, abstractVarRange)
var src = skipTypes(n.sons[1].typ, abstractVarRange)
gen(p, n.sons[1], r)
if dest.kind == src.kind:
# no-op conversion
return
let toInt = (dest.kind in tyInt .. tyInt32)
let toUint = (dest.kind in tyUInt .. tyUInt32)
let fromInt = (src.kind in tyInt .. tyInt32)
let fromUint = (src.kind in tyUInt .. tyUInt32)
if toUint and (fromInt or fromUint):
let trimmer = unsignedTrimmer(dest.size)
r.res = "($1 $2)" % [r.res, trimmer]
elif toInt:
if fromInt:
let trimmer = unsignedTrimmer(dest.size)
r.res = "($1 $2)" % [r.res, trimmer]
elif fromUint:
if src.size == 4 and dest.size == 4:
r.res = "($1|0)" % [r.res]
else:
let trimmer = unsignedTrimmer(dest.size)
let minuend = case dest.size
of 1: "0xfe"
of 2: "0xfffe"
of 4: "0xfffffffe"
else: ""
r.res = "($1 - ($2 $3))" % [rope minuend, r.res, trimmer]
proc gen(p: PProc, n: PNode, r: var TCompRes) =
r.typ = etyNone
r.kind = resNone
@ -1630,7 +1670,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
of nkCheckedFieldExpr: genCheckedFieldAccess(p, n, r)
of nkObjDownConv: gen(p, n.sons[0], r)
of nkObjUpConv: upConv(p, n, r)
of nkCast: gen(p, n.sons[1], r)
of nkCast: genCast(p, n, r)
of nkChckRangeF: genRangeChck(p, n, r, "chckRangeF")
of nkChckRange64: genRangeChck(p, n, r, "chckRange64")
of nkChckRange: genRangeChck(p, n, r, "chckRange")