func (v *Codegen) genBinaryExpr(n *parser.BinaryExpr) llvm.Value { if n.Op.Category() == parser.OP_LOGICAL { return v.genLogicalBinop(n) } lhand := v.genExpr(n.Lhand) rhand := v.genExpr(n.Rhand) return v.genBinop(n.Op, n.GetType(), n.Lhand.GetType(), n.Rhand.GetType(), lhand, rhand) }
func (v *Codegen) genBinaryExpr(n *parser.BinaryExpr) llvm.Value { var res llvm.Value lhand := v.genExpr(n.Lhand) rhand := v.genExpr(n.Rhand) if lhand.IsNil() || rhand.IsNil() { v.err("invalid binary expr") } else { switch n.Op { // Arithmetic case parser.BINOP_ADD: if n.GetType().IsFloatingType() { return v.builder.CreateFAdd(lhand, rhand, "") } else { return v.builder.CreateAdd(lhand, rhand, "") } case parser.BINOP_SUB: if n.GetType().IsFloatingType() { return v.builder.CreateFSub(lhand, rhand, "") } else { return v.builder.CreateSub(lhand, rhand, "") } case parser.BINOP_MUL: if n.GetType().IsFloatingType() { return v.builder.CreateFMul(lhand, rhand, "") } else { return v.builder.CreateMul(lhand, rhand, "") } case parser.BINOP_DIV: if n.GetType().IsFloatingType() { return v.builder.CreateFDiv(lhand, rhand, "") } else { if n.GetType().(parser.PrimitiveType).IsSigned() { return v.builder.CreateSDiv(lhand, rhand, "") } else { return v.builder.CreateUDiv(lhand, rhand, "") } } case parser.BINOP_MOD: if n.GetType().IsFloatingType() { return v.builder.CreateFRem(lhand, rhand, "") } else { if n.GetType().(parser.PrimitiveType).IsSigned() { return v.builder.CreateSRem(lhand, rhand, "") } else { return v.builder.CreateURem(lhand, rhand, "") } } // Comparison case parser.BINOP_GREATER, parser.BINOP_LESS, parser.BINOP_GREATER_EQ, parser.BINOP_LESS_EQ, parser.BINOP_EQ, parser.BINOP_NOT_EQ: if n.Lhand.GetType().IsFloatingType() { return v.builder.CreateFCmp(comparisonOpToFloatPredicate(n.Op), lhand, rhand, "") } else { return v.builder.CreateICmp(comparisonOpToIntPredicate(n.Op, n.Lhand.GetType().IsSigned()), lhand, rhand, "") } // Bitwise case parser.BINOP_BIT_AND: return v.builder.CreateAnd(lhand, rhand, "") case parser.BINOP_BIT_OR: return v.builder.CreateOr(lhand, rhand, "") case parser.BINOP_BIT_XOR: return v.builder.CreateXor(lhand, rhand, "") case parser.BINOP_BIT_LEFT: return v.builder.CreateShl(lhand, rhand, "") case parser.BINOP_BIT_RIGHT: // TODO make sure both operands are same type (create type cast here?) // TODO in semantic.go, make sure rhand is *unsigned* (LLVM always treats it that way) // TODO doc this if n.Lhand.GetType().IsSigned() { return v.builder.CreateAShr(lhand, rhand, "") } else { return v.builder.CreateLShr(lhand, rhand, "") } // Logical case parser.BINOP_LOG_AND: return v.builder.CreateAnd(lhand, rhand, "") case parser.BINOP_LOG_OR: return v.builder.CreateOr(lhand, rhand, "") default: panic("umimplented binop") } } return res }
func (v *Codegen) genBinaryExpr(n *parser.BinaryExpr) llvm.Value { lhand := v.genExpr(n.Lhand) rhand := v.genExpr(n.Rhand) return v.genBinop(n.Op, n.GetType(), n.Lhand.GetType(), n.Rhand.GetType(), lhand, rhand) }