Implement shifting with a differently-sized integer

This commit is contained in:
Ayke van Laethem
2018-08-22 04:35:25 +02:00
parent 337e48270b
commit 8fb9cd4e23
+12
View File
@@ -1530,6 +1530,15 @@ func (c *Compiler) parseBinOp(frame *Frame, binop *ssa.BinOp) (llvm.Value, error
return c.builder.CreateOr(x, y, ""), nil return c.builder.CreateOr(x, y, ""), nil
case token.XOR: // ^ case token.XOR: // ^
return c.builder.CreateXor(x, y, ""), nil return c.builder.CreateXor(x, y, ""), nil
case token.SHL, token.SHR:
sizeX := c.targetData.TypeAllocSize(x.Type())
sizeY := c.targetData.TypeAllocSize(y.Type())
if sizeX > sizeY {
// x and y must have equal sizes, make Y bigger in this case.
// y is unsigned, this has been checked by the Go type checker.
y = c.builder.CreateZExt(y, x.Type(), "")
}
switch binop.Op {
case token.SHL: // << case token.SHL: // <<
return c.builder.CreateShl(x, y, ""), nil return c.builder.CreateShl(x, y, ""), nil
case token.SHR: // >> case token.SHR: // >>
@@ -1538,6 +1547,9 @@ func (c *Compiler) parseBinOp(frame *Frame, binop *ssa.BinOp) (llvm.Value, error
} else { } else {
return c.builder.CreateLShr(x, y, ""), nil return c.builder.CreateLShr(x, y, ""), nil
} }
default:
panic("unreachable")
}
case token.AND_NOT: // &^ case token.AND_NOT: // &^
// Go specific. Calculate "and not" with x & (~y) // Go specific. Calculate "and not" with x & (~y)
inv := c.builder.CreateNot(y, "") // ~y inv := c.builder.CreateNot(y, "") // ~y