func (v *Codegen) genDefaultValue(typ parser.Type) llvm.Value { typ = typ.ActualType() // Generate default struct values if structType, ok := typ.(*parser.StructType); ok { lit := createStructInitializer(structType) if lit != nil { return v.genStructLiteral(lit) } else { return llvm.Undef(v.typeToLLVMType(structType)) } } if tupleType, ok := typ.(*parser.TupleType); ok { values := make([]llvm.Value, len(tupleType.Members)) for idx, member := range tupleType.Members { values[idx] = v.genDefaultValue(member) } return llvm.ConstStruct(values, false) } if typ.IsIntegerType() || typ == parser.PRIMITIVE_bool { return llvm.ConstInt(v.typeToLLVMType(typ), 0, false) } if typ.IsFloatingType() { return llvm.ConstFloat(v.typeToLLVMType(typ), 0) } panic("type does not have default value: " + typ.TypeName()) }
func (v *Codegen) genBinop(operator parser.BinOpType, resType, lhandType, rhandType parser.Type, lhand, rhand llvm.Value) llvm.Value { if lhand.IsNil() || rhand.IsNil() { v.err("invalid binary expr") } else { switch operator { // Arithmetic case parser.BINOP_ADD: if resType.IsFloatingType() { return v.builder().CreateFAdd(lhand, rhand, "") } else { return v.builder().CreateAdd(lhand, rhand, "") } case parser.BINOP_SUB: if resType.IsFloatingType() { return v.builder().CreateFSub(lhand, rhand, "") } else { return v.builder().CreateSub(lhand, rhand, "") } case parser.BINOP_MUL: if resType.IsFloatingType() { return v.builder().CreateFMul(lhand, rhand, "") } else { return v.builder().CreateMul(lhand, rhand, "") } case parser.BINOP_DIV: if resType.IsFloatingType() { return v.builder().CreateFDiv(lhand, rhand, "") } else { if resType.(parser.PrimitiveType).IsSigned() { return v.builder().CreateSDiv(lhand, rhand, "") } else { return v.builder().CreateUDiv(lhand, rhand, "") } } case parser.BINOP_MOD: if resType.IsFloatingType() { return v.builder().CreateFRem(lhand, rhand, "") } else { if resType.(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 lhandType.IsFloatingType() { return v.builder().CreateFCmp(comparisonOpToFloatPredicate(operator), lhand, rhand, "") } else { return v.builder().CreateICmp(comparisonOpToIntPredicate(operator, lhandType.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 lhandType.IsSigned() { return v.builder().CreateAShr(lhand, rhand, "") } else { return v.builder().CreateLShr(lhand, rhand, "") } default: panic("umimplented binop") } } panic("unreachable") }