diff --git a/languages/lang0.md b/languages/lang0.md index a5dd4983..42cd6a2f 100644 --- a/languages/lang0.md +++ b/languages/lang0.md @@ -46,11 +46,13 @@ arith ::= (Neg ) | (Shl ) | (Shr ) -conv ::= (Reinterp ) - | (Conv ) - -# TODO: `Reinterp` and `Conv` need to be replaced with concrete operations -# (e.g., zero extend, sign extend, ftoi.) +conv ::= (Reinterp ) # bit casting (between numeric types) + | (Conv ) # int-to-float conversion and vice versa + | (Zext ) # zero extension (integer only) + | (Sext ) # sign extension (integer only) + | (Trunc ) # integer truncation + | (Demote ) # larger float to smaller float demotion + | (Promote ) # smaller float to larger float promotion memops ::= (Load ) diff --git a/passes/pass0.nim b/passes/pass0.nim index bfa8d6cb..91341be7 100644 --- a/passes/pass0.nim +++ b/passes/pass0.nim @@ -209,6 +209,11 @@ proc genCheckedBinary(c; tree; op: NodeIndex, opc: Opcode) = c.instr(opc, int8(parseType(tree, typ).size * 8)) c.instr(opcPopLocal, tree[op, 3].id) +proc prepareConvOp(c; tree; n: NodeIndex): (Type0, Type0) = + let (dst, src, x) = triplet(tree, n) + c.genExpr(tree, x) + (parseType(tree, dst), parseType(tree, src)) + proc loadLocal(c; local: int32) = c.instr(opcGetLocal, local) # TODO: merge opcPopLocal + opcGetLocal into opcSetLocal, if there's no @@ -359,43 +364,51 @@ proc genExpr(c; tree; val: NodeIndex) = of 4: c.instr(opcReinterpF32) else: unreachable() of Conv: - # numeric conversion let - dtyp = parseType(tree, tree.child(val, 0)) - styp = parseType(tree, tree.child(val, 1)) + (dtyp, styp) = c.prepareConvOp(tree, val) + width = int8(dtyp.size * 8) - c.genExpr(tree, tree.child(val, 2)) case dtyp.kind of t0kInt: - case styp.kind - of t0kInt, t0kUInt: - c.signExtend(dtyp) - of t0kFloat: - c.instr(opcFloatToSInt, int8(dtyp.size * 8)) + assert styp.kind == t0kFloat + c.instr(opcFloatToSInt, width) of t0kUInt: - case styp.kind - of t0kInt: - c.mask(dtyp) - of t0kUInt: - # the upper bits can only be set if the source type has larger bit- - # width than the destination - if dtyp.size < styp.size: - c.mask(dtyp) - of t0kFloat: - c.instr(opcFloatToUInt, int8(dtyp.size * 8)) + assert styp.kind == t0kFloat + c.instr(opcFloatToUInt, width) of t0kFloat: case styp.kind of t0kInt: - c.instr(opcSIntToFloat, int8(dtyp.size * 8)) + c.instr(opcSIntToFloat, width) of t0kUInt: - c.instr(opcUIntToFloat, int8(dtyp.size * 8)) + c.instr(opcUIntToFloat, width) of t0kFloat: - if styp.size == 8 and dtyp.size == 4: - # demote 64-bit float to 32-bit float value. Reinterpret the bits as - # a 32-bit integer (which internally converts to a 32-bit float - # first) and then reinterpret the result as a 32-bit float - c.instr(opcReinterpI32) - c.instr(opcReinterpF32) + unreachable() + # TODO: demote the result when the destination type is a 32-bit float + of Sext: + let (dtyp, styp) = c.prepareConvOp(tree, val) + c.signExtend(styp) + if dtyp.kind == t0kUInt: + c.mask(dtyp) + of Zext: + let (_, styp) = c.prepareConvOp(tree, val) + if styp.kind == t0kInt: + c.mask(styp) # zero all leading bits + of Trunc: + let (dtyp, _) = c.prepareConvOp(tree, val) + if dtyp.kind == t0kInt: + c.signExtend(dtyp) + else: + c.mask(dtyp) + of Demote: + # demote 64-bit float to 32-bit float value. Reinterpret the bits as + # a 32-bit integer (which internally converts to a 32-bit float + # first) and then reinterpret the result as a 32-bit float + c.genExpr(tree, tree.child(val, 2)) + c.instr(opcReinterpI32) + c.instr(opcReinterpF32) + of Promote: + c.genExpr(tree, tree.child(val, 2)) + # a no-op of Call: c.genCall(tree, val, 0, ^1) else: diff --git a/passes/pass_aggregateParams.nim b/passes/pass_aggregateParams.nim index e5e0c077..272de81d 100644 --- a/passes/pass_aggregateParams.nim +++ b/passes/pass_aggregateParams.nim @@ -79,7 +79,8 @@ proc signature(c; tree; n): NodeIndex = proc typeof(c; tree; n): Node = case tree[n].kind of Path, Load, Deref, Add, Sub, Mul, Div, Mod, BitNot, BitAnd, BitOr, BitXor, - AddChck, SubChck, MulChck, Shl, Shr, Conv, Reinterp, Neg: + AddChck, SubChck, MulChck, Shl, Shr, Conv, Zext, Sext, Trunc, Demote, + Promote, Reinterp, Neg: # these are all expression that store their result type as the first # node tree[n, 0] @@ -235,7 +236,7 @@ proc lowerExpr(c; tree; n, bu) = c.lowerExpr(tree, tree.child(n, 0), bu) of Load, Neg, BitNot: c.lowerExpr(tree, tree.child(n, 1), bu) - of Reinterp, Conv: + of Reinterp, Conv, Zext, Sext, Trunc, Demote, Promote: c.lowerExpr(tree, tree.child(n, 2), bu) of Add, Sub, Mul, Div, Mod, BitAnd, BitOr, BitXor, AddChck, SubChck, MulChck, Eq, Lt, Le, Shl, Shr: diff --git a/passes/syntax.nim b/passes/syntax.nim index ffc0d083..8e1ccb71 100644 --- a/passes/syntax.nim +++ b/passes/syntax.nim @@ -31,7 +31,7 @@ type BitAnd, BitNot, BitXor, BitOr Shl, Shr - Conv, Reinterp + Conv, Reinterp, Zext, Sext, Trunc, Demote, Promote Goto, Loop, Raise, Unreachable, Select, Branch CheckedCall, CheckedCallAsgn, Unwind, Choice diff --git a/skully/backend.nim b/skully/backend.nim index 41622850..64af7f40 100644 --- a/skully/backend.nim +++ b/skully/backend.nim @@ -1055,11 +1055,75 @@ proc genLength(c; env: var MirEnv; tree; n; dest: Expr, stmts) = else: unreachable() +proc genNumericConv(c; env; val: Expr, to: TypeId, bu) = + ## If the types are equal (at the IL level), emits an *unchecked* numeric + ## conversion for `val` to type `to`. + proc skip(env; t: TypeId): TypeId = + result = env.types.canonical(t) + # treat imported types as their underlying representation + if env.types.headerFor(t, Lowered).kind == tkImported: + result = env.skip(env.types.headerFor(t, Lowered).elem) + + let dst = env.types.headerFor(env.skip(to), Lowered) + let src = env.types.headerFor(env.skip(val.typ), Lowered) + + template convOp(kind: NodeKind) = + bu.subTree kind: + bu.add typeRef(c, env, to) + bu.add typeRef(c, env, val.typ) + bu.use val + + template sizedConv(widen, narrow: NodeKind) = + if dst.size(env.types) < src.size(env.types): + convOp narrow + elif dst.size(env.types) > dst.size(env.types): + convOp widen + else: + # nothing to do + bu.use val + + const + uints = {tkUInt, tkChar, tkBool} + ints = {tkInt} + + case dst.kind + of uints: + case src.kind + of ints, uints: + # conversion to uint is the same as casting to uint + sizedConv Trunc, Zext + of tkFloat: + convOp Conv + else: + unreachable(src.kind) + of ints: + case src.kind + of ints: sizedConv Trunc, Sext + of uints: sizedConv Trunc, Zext + of tkFloat: convOp Conv + else: + unreachable(src.kind) + of tkFloat: + case src.kind + of ints, uints: + convOp Conv + of tkFloat: + sizedConv Promote, Demote + else: + unreachable() + of tkPtr, tkPointer, tkProc, tkCstring: + # a conversion between pointer types is a no-op. These conversion aren't + # really numeric conversions, but it's easier to also include them here + bu.use val + else: + unreachable(dst.kind) + proc genSetElem(c; env; tree; n; styp: TypeId, bu) = ## Emits the expression for loading a value for use in a set-related ## operation. This means turning the value into one relative to the start of ## the set's value range. The resulting value is always of uint16 type. - proc aux(c; env; tree; n; styp: TypeId, bu) = + let val = makeExpr tree[n].typ: + # shift the operand's value so that its range starts at 0 assert env.types[styp].kind == tySet let first = c.graph.config.firstOrd(env.types[styp]) if first != Zero: @@ -1070,16 +1134,8 @@ proc genSetElem(c; env; tree; n; styp: TypeId, bu) = else: c.translateValue(env, tree, n, true, bu) - let typ = env.types.canonical(tree[n].typ) - let desc = env.types.headerFor(typ, Lowered) - if desc.kind != tkUInt or desc.size(env.types) != 2: - # sets cannot have more than 2^16 elements, hence a uint16 - bu.subTree Conv: - bu.add node(UInt, 2) - bu.add typeRef(c, env, typ) - aux(c, env, tree, n, styp, bu) - else: - aux(c, env, tree, n, styp, bu) + # sets cannot have more than 2^16 elements, hence a uint16 + c.genNumericConv(env, val, UInt16Type, bu) proc genSetOp(c; env: var MirEnv, tree; n; dest: Expr, stmts) = ## Generates and emits the IL code for a binary set operation. @@ -1381,10 +1437,10 @@ proc genMagic(c; env: var MirEnv, tree; n; dest: Expr, stmts) = wrapAsgn: value(tree.argument(n, 0)) of mChr: - wrapAsgn Conv: - bu.add typeRef(c, env, tree[n].typ) - bu.add typeRef(c, env, tree[tree.argument(n, 0)].typ) - value(tree.argument(n, 0)) + # it's a conversion, nothing more + let input = c.gen(env, tree, NodePosition(tree.argument(n, 0)), true) + wrapAsgn: + c.genNumericConv(env, input, tree[n].typ, bu) of mIncl, mExcl, mLtSet, mLeSet, mEqSet, mMinusSet, mPlusSet, mMulSet, mInSet: c.genSetOp(env, tree, n, dest, stmts) @@ -1408,7 +1464,7 @@ proc genMagic(c; env: var MirEnv, tree; n; dest: Expr, stmts) = # also use countBits32, but widen the operand first wrapAsgn Call: bu.add compilerProc(c, env, "countBits32") - bu.subTree Conv: + bu.subTree Zext: bu.add node(UInt, 4) bu.add typeRef(c, env, tree[a].typ) value a @@ -1934,10 +1990,11 @@ proc translateExpr(c; env: var MirEnv, tree; n; dest: Expr, stmts) = wrapAsgn: value(n) of mnkConv, mnkStdConv: - wrapAsgn Conv: - bu.add typeRef(c, env, tree[n].typ) - bu.add typeRef(c, env, tree[n, 0].typ) - value(tree.child(n, 0)) + # the high-level MIR conversions are lowered into the more specific + # operations of the target IL + let input = c.gen(env, tree, tree.child(n, 0), true) + wrapAsgn: + c.genNumericConv(env, input, tree[n].typ, bu) of mnkCopy, mnkMove, mnkSink: wrapAsgn: value(tree.child(n, 0)) @@ -2254,10 +2311,6 @@ proc translateExpr(c; env: var MirEnv, tree; n; dest: Expr, stmts) = takeAddr tree.child(n, 0) bu.add node(IntVal, c.lit.pack(size)) else: - template isUnsigned(id: TypeId): bool = - env.types.headerFor(id, Lowered).kind in - {tkPtr, tkPointer, tkRef, tkUInt, tkChar, tkBool} - let a = env.types.headerFor(dst, Lowered).size(env.types) let b = env.types.headerFor(src, Lowered).size(env.types) # for the implementation, keep in mind that Reinterp only supports @@ -2271,40 +2324,16 @@ proc translateExpr(c; env: var MirEnv, tree; n; dest: Expr, stmts) = bu.add typeRef(c, env, dst) bu.add typeRef(c, env, src) value tree.child(n, 0) - elif isUnsigned(dst): - if isUnsigned(src): - # a simple conversion (i.e., a zero extension) is enough - wrapAsgn Conv: - bu.add typeRef(c, env, dst) - bu.add typeRef(c, env, src) - value tree.child(n, 0) - else: - wrapAsgn Conv: - bu.add typeRef(c, env, dst) - bu.add node(UInt, b.uint32) - bu.subTree Reinterp: - bu.add node(UInt, b.uint32) - bu.add typeRef(c, env, src) - value tree.child(n, 0) - elif isUnsigned(src): - wrapAsgn Reinterp: + elif a < b: + wrapAsgn Trunc: bu.add typeRef(c, env, dst) - bu.add node(UInt, a.uint32) - bu.subTree Conv: - bu.add node(UInt, a.uint32) - bu.add typeRef(c, env, src) - value tree.child(n, 0) + bu.add typeRef(c, env, src) + value tree.child(n, 0) else: - wrapAsgn Reinterp: + wrapAsgn Zext: bu.add typeRef(c, env, dst) - bu.add node(UInt, a.uint32) - bu.subTree Conv: - bu.add node(UInt, a.uint32) - bu.add node(UInt, b.uint32) - bu.subTree Reinterp: - bu.add node(UInt, b.uint32) - bu.add typeRef(c, env, src) - value tree.child(n, 0) + bu.add typeRef(c, env, src) + value tree.child(n, 0) else: unreachable() diff --git a/tests/pass0/t03_conv_float64_to_32.expected b/tests/pass0/t03_demote_float64_to_float32.expected similarity index 100% rename from tests/pass0/t03_conv_float64_to_32.expected rename to tests/pass0/t03_demote_float64_to_float32.expected diff --git a/tests/pass0/t03_demote_float64_to_float32.test b/tests/pass0/t03_demote_float64_to_float32.test new file mode 100644 index 00000000..8c7026cc --- /dev/null +++ b/tests/pass0/t03_demote_float64_to_float32.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done 0.5)" +""" +(TypeDefs + (ProcTy (Float 4))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Demote (Float 4) (Float 8) (FloatVal 0.5000000149))))))) diff --git a/tests/pass0/t03_promote_float64_to_float32.expected b/tests/pass0/t03_promote_float64_to_float32.expected new file mode 100644 index 00000000..22c11686 --- /dev/null +++ b/tests/pass0/t03_promote_float64_to_float32.expected @@ -0,0 +1,5 @@ +.type t0 () -> float +.start t0 p0 + LdImmFloat 0.5 + Ret +.end diff --git a/tests/pass0/t03_conv_float64_to_32.test b/tests/pass0/t03_promote_float64_to_float32.test similarity index 72% rename from tests/pass0/t03_conv_float64_to_32.test rename to tests/pass0/t03_promote_float64_to_float32.test index 398cf5b6..82f4f083 100644 --- a/tests/pass0/t03_conv_float64_to_32.test +++ b/tests/pass0/t03_promote_float64_to_float32.test @@ -9,4 +9,4 @@ discard """ (List (Block (Params) (Return - (Conv (Float 4) (Float 8) (FloatVal 0.5000000149))))))) + (Promote (Float 8) (Float 4) (FloatVal 0.5))))))) diff --git a/tests/pass0/t03_sext_int_to_int.expected b/tests/pass0/t03_sext_int_to_int.expected new file mode 100644 index 00000000..162186d6 --- /dev/null +++ b/tests/pass0/t03_sext_int_to_int.expected @@ -0,0 +1,6 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt -3 + SignExtend 56 + Ret +.end diff --git a/tests/pass0/t03_sext_int_to_int.test b/tests/pass0/t03_sext_int_to_int.test new file mode 100644 index 00000000..572dd81a --- /dev/null +++ b/tests/pass0/t03_sext_int_to_int.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done (18446744073709551613 or -3))" +""" +(TypeDefs + (ProcTy (Int 2))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Sext (Int 2) (Int 1) (IntVal -3))))))) diff --git a/tests/pass0/t03_sext_int_to_uint.expected b/tests/pass0/t03_sext_int_to_uint.expected new file mode 100644 index 00000000..6d1e3f13 --- /dev/null +++ b/tests/pass0/t03_sext_int_to_uint.expected @@ -0,0 +1,7 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt -3 + SignExtend 56 + Mask 16 + Ret +.end diff --git a/tests/pass0/t03_sext_int_to_uint.test b/tests/pass0/t03_sext_int_to_uint.test new file mode 100644 index 00000000..d6ebb3e2 --- /dev/null +++ b/tests/pass0/t03_sext_int_to_uint.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done 65533)" +""" +(TypeDefs + (ProcTy (UInt 2))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Sext (UInt 2) (Int 1) (IntVal -3))))))) diff --git a/tests/pass0/t03_sext_uint_to_int.expected b/tests/pass0/t03_sext_uint_to_int.expected new file mode 100644 index 00000000..ec8053ee --- /dev/null +++ b/tests/pass0/t03_sext_uint_to_int.expected @@ -0,0 +1,6 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt 253 + SignExtend 56 + Ret +.end diff --git a/tests/pass0/t03_sext_uint_to_int.test b/tests/pass0/t03_sext_uint_to_int.test new file mode 100644 index 00000000..48dc2ef2 --- /dev/null +++ b/tests/pass0/t03_sext_uint_to_int.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done (18446744073709551613 or -3))" +""" +(TypeDefs + (ProcTy (Int 2))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Sext (Int 2) (UInt 1) (IntVal 253))))))) diff --git a/tests/pass0/t03_sext_uint_to_uint.expected b/tests/pass0/t03_sext_uint_to_uint.expected new file mode 100644 index 00000000..15784c38 --- /dev/null +++ b/tests/pass0/t03_sext_uint_to_uint.expected @@ -0,0 +1,7 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt 253 + SignExtend 56 + Mask 16 + Ret +.end diff --git a/tests/pass0/t03_sext_uint_to_uint.test b/tests/pass0/t03_sext_uint_to_uint.test new file mode 100644 index 00000000..41c5d7b3 --- /dev/null +++ b/tests/pass0/t03_sext_uint_to_uint.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done 65533)" +""" +(TypeDefs + (ProcTy (UInt 2))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Sext (UInt 2) (UInt 1) (IntVal 253))))))) diff --git a/tests/pass0/t03_trunc_int_to_int.expected b/tests/pass0/t03_trunc_int_to_int.expected new file mode 100644 index 00000000..bd0a88c2 --- /dev/null +++ b/tests/pass0/t03_trunc_int_to_int.expected @@ -0,0 +1,6 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt 511 + SignExtend 56 + Ret +.end diff --git a/tests/pass0/t03_trunc_int_to_int.test b/tests/pass0/t03_trunc_int_to_int.test new file mode 100644 index 00000000..c54ba9c4 --- /dev/null +++ b/tests/pass0/t03_trunc_int_to_int.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done (18446744073709551615 or -1))" +""" +(TypeDefs + (ProcTy (UInt 1))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Trunc (Int 1) (Int 2) (IntVal 511))))))) diff --git a/tests/pass0/t03_trunc_int_to_uint.expected b/tests/pass0/t03_trunc_int_to_uint.expected new file mode 100644 index 00000000..1aa8432d --- /dev/null +++ b/tests/pass0/t03_trunc_int_to_uint.expected @@ -0,0 +1,6 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt 511 + Mask 8 + Ret +.end diff --git a/tests/pass0/t03_trunc_int_to_uint.test b/tests/pass0/t03_trunc_int_to_uint.test new file mode 100644 index 00000000..a6d0dacf --- /dev/null +++ b/tests/pass0/t03_trunc_int_to_uint.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done 255)" +""" +(TypeDefs + (ProcTy (UInt 1))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Trunc (UInt 1) (Int 2) (IntVal 511))))))) diff --git a/tests/pass0/t03_trunc_uint_to_int.expected b/tests/pass0/t03_trunc_uint_to_int.expected new file mode 100644 index 00000000..3de88d60 --- /dev/null +++ b/tests/pass0/t03_trunc_uint_to_int.expected @@ -0,0 +1,6 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt 510 + SignExtend 56 + Ret +.end diff --git a/tests/pass0/t03_trunc_uint_to_int.test b/tests/pass0/t03_trunc_uint_to_int.test new file mode 100644 index 00000000..b272514c --- /dev/null +++ b/tests/pass0/t03_trunc_uint_to_int.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done (18446744073709551614 or -2))" +""" +(TypeDefs + (ProcTy (UInt 1))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Trunc (Int 1) (UInt 2) (IntVal 510))))))) diff --git a/tests/pass0/t03_trunc_uint_to_uint.expected b/tests/pass0/t03_trunc_uint_to_uint.expected new file mode 100644 index 00000000..53b9545c --- /dev/null +++ b/tests/pass0/t03_trunc_uint_to_uint.expected @@ -0,0 +1,6 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt 510 + Mask 8 + Ret +.end diff --git a/tests/pass0/t03_trunc_uint_to_uint.test b/tests/pass0/t03_trunc_uint_to_uint.test new file mode 100644 index 00000000..44cabde0 --- /dev/null +++ b/tests/pass0/t03_trunc_uint_to_uint.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done 254)" +""" +(TypeDefs + (ProcTy (UInt 1))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Trunc (UInt 1) (UInt 2) (IntVal 510))))))) diff --git a/tests/pass0/t03_zext_int_to_int.expected b/tests/pass0/t03_zext_int_to_int.expected new file mode 100644 index 00000000..9cd0aa5c --- /dev/null +++ b/tests/pass0/t03_zext_int_to_int.expected @@ -0,0 +1,6 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt -1 + Mask 8 + Ret +.end diff --git a/tests/pass0/t03_zext_int_to_int.test b/tests/pass0/t03_zext_int_to_int.test new file mode 100644 index 00000000..b911da6c --- /dev/null +++ b/tests/pass0/t03_zext_int_to_int.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done 255)" +""" +(TypeDefs + (ProcTy (Int 2))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Zext (Int 2) (Int 1) (IntVal -1))))))) diff --git a/tests/pass0/t03_zext_int_to_uint.expected b/tests/pass0/t03_zext_int_to_uint.expected new file mode 100644 index 00000000..9cd0aa5c --- /dev/null +++ b/tests/pass0/t03_zext_int_to_uint.expected @@ -0,0 +1,6 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt -1 + Mask 8 + Ret +.end diff --git a/tests/pass0/t03_zext_int_to_uint.test b/tests/pass0/t03_zext_int_to_uint.test new file mode 100644 index 00000000..96dfcc71 --- /dev/null +++ b/tests/pass0/t03_zext_int_to_uint.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done 255)" +""" +(TypeDefs + (ProcTy (UInt 2))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Zext (UInt 2) (Int 1) (IntVal -1))))))) diff --git a/tests/pass0/t03_zext_uint_to_int.expected b/tests/pass0/t03_zext_uint_to_int.expected new file mode 100644 index 00000000..2dc7bbcd --- /dev/null +++ b/tests/pass0/t03_zext_uint_to_int.expected @@ -0,0 +1,5 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt 255 + Ret +.end diff --git a/tests/pass0/t03_zext_uint_to_int.test b/tests/pass0/t03_zext_uint_to_int.test new file mode 100644 index 00000000..25cff1f0 --- /dev/null +++ b/tests/pass0/t03_zext_uint_to_int.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done 255)" +""" +(TypeDefs + (ProcTy (Int 2))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Zext (Int 2) (UInt 1) (IntVal 255))))))) diff --git a/tests/pass0/t03_zext_uint_to_uint.expected b/tests/pass0/t03_zext_uint_to_uint.expected new file mode 100644 index 00000000..2dc7bbcd --- /dev/null +++ b/tests/pass0/t03_zext_uint_to_uint.expected @@ -0,0 +1,5 @@ +.type t0 () -> int +.start t0 p0 + LdImmInt 255 + Ret +.end diff --git a/tests/pass0/t03_zext_uint_to_uint.test b/tests/pass0/t03_zext_uint_to_uint.test new file mode 100644 index 00000000..dc4576c3 --- /dev/null +++ b/tests/pass0/t03_zext_uint_to_uint.test @@ -0,0 +1,12 @@ +discard """ + output: "(Done 255)" +""" +(TypeDefs + (ProcTy (UInt 2))) +(GlobalDefs) +(ProcDefs + (ProcDef (Type 0) 0 (Locals) + (List + (Block (Params) + (Return + (Zext (UInt 2) (UInt 1) (IntVal 255)))))))