func (n *ForExpr) Gen(cg *CG) llvm.Value { startVal := n.Start.Gen(cg) if startVal.IsNil() { return errv("Code generation failed for start expression") } fun := cg.GetInsertBlock().Parent() alloca := createEntryBlockAlloca(fun, n.Var) cg.CreateStore(startVal, alloca) loopBB := llvm.AddBasicBlock(fun, "loop") cg.CreateBr(loopBB) cg.SetInsertPointAtEnd(loopBB) oldVal := cg.NamedValues[n.Var] cg.NamedValues[n.Var] = alloca if n.Body.Gen(cg).IsNil() { return llvm.Value{} } var stepVal llvm.Value if n.Step != nil { stepVal = n.Step.Gen(cg) if stepVal.IsNil() { return llvm.ConstNull(llvm.DoubleType()) } } else { stepVal = llvm.ConstFloat(llvm.DoubleType(), 1) } endVal := n.End.Gen(cg) if endVal.IsNil() { return llvm.Value{} } curVar := cg.CreateLoad(alloca, n.Var) nextVar := cg.CreateFAdd(curVar, stepVal, "nextvar") cg.CreateStore(nextVar, alloca) endVal = cg.CreateFCmp(llvm.FloatONE, endVal, llvm.ConstFloat(llvm.DoubleType(), 0), "loopcond") afterBB := cg.AddBasicBlock(fun, "afterloop") cg.CreateCondBr(endVal, loopBB, afterBB) cg.SetInsertPointAtEnd(afterBB) if !oldVal.IsNil() { cg.NamedValues[n.Var] = oldVal } else { delete(cg.NamedValues, n.Var) } return llvm.ConstFloat(llvm.DoubleType(), 0) }
func (v *Codegen) genDefaultValue(typ parser.Type) llvm.Value { atyp := typ.ActualType() // Generate default struct values if structType, ok := atyp.(parser.StructType); ok { lit := createStructInitializer(typ) if lit != nil { return v.genStructLiteral(lit) } else { return llvm.Undef(v.typeToLLVMType(structType)) } } if tupleType, ok := atyp.(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 atyp.IsIntegerType() || atyp == parser.PRIMITIVE_bool { return llvm.ConstInt(v.typeToLLVMType(atyp), 0, false) } if atyp.IsFloatingType() { return llvm.ConstFloat(v.typeToLLVMType(atyp), 0) } panic("type does not have default value: " + atyp.TypeName()) }
func (v *Codegen) genNumericLiteral(n *parser.NumericLiteral) llvm.Value { if n.Type.IsFloatingType() { return llvm.ConstFloat(v.typeToLLVMType(n.Type), n.AsFloat()) } else { return llvm.ConstInt(v.typeToLLVMType(n.Type), n.AsInt(), false) } }
func (n *VarExpr) Gen(cg *CG) llvm.Value { fun := cg.GetInsertBlock().Parent() var oldBindingNames []string var oldBindingValues []llvm.Value for name, init := range n.Names { var initVal llvm.Value if init != nil { init.Gen(cg) if initVal.IsNil() { return llvm.Value{} } } else { initVal = llvm.ConstFloat(cg.FloatType(), 0) } alloca := createEntryBlockAlloca(fun, name) cg.CreateStore(initVal, alloca) oldBindingNames = append(oldBindingNames, name) oldBindingValues = append(oldBindingValues, cg.NamedValues[name]) cg.NamedValues[name] = alloca } bodyVal := n.Body.Gen(cg) if bodyVal.IsNil() { return llvm.Value{} } for i, name := range oldBindingNames { cg.NamedValues[name] = oldBindingValues[i] } return bodyVal }
func (c *Codegen) generateExpression(node parser.Node) llvm.Value { switch n := node.(type) { case *parser.BinaryExprNode: return c.generateBinaryExpression(n) case *parser.NumLitNode: if n.IsFloat { return llvm.ConstFloat(PRIMITIVE_TYPES["float"], n.FloatValue) } else { return llvm.ConstInt(PRIMITIVE_TYPES["int"], uint64(n.IntValue), false) } case *parser.BoolLitNode: i := 0 if n.Value { i = 1 } return llvm.ConstInt(PRIMITIVE_TYPES["boolean"], uint64(i), false) case *parser.CharLitNode: return llvm.ConstInt(PRIMITIVE_TYPES["char"], uint64(n.Value), false) case *parser.VarAccessNode, *parser.ObjectAccessNode, *parser.ArrayAccessNode, *parser.CallExprNode, *parser.StringLitNode, *parser.MakeExprNode: return c.generateAccess(n, true) } return null }
func (v *Codegen) genFloatingLiteral(n *parser.FloatingLiteral) llvm.Value { return llvm.ConstFloat(v.typeToLLVMType(n.Type), n.Value) }
func (n *NumberExpr) Gen(cg *CG) llvm.Value { return llvm.ConstFloat(cg.DoubleType(), n.Value) }
// newValueFromConst converts a constant value to an LLVM value. func (fr *frame) newValueFromConst(v exact.Value, typ types.Type) *govalue { switch { case v == nil: llvmtyp := fr.types.ToLLVM(typ) return newValue(llvm.ConstNull(llvmtyp), typ) case isString(typ): if isUntyped(typ) { typ = types.Typ[types.String] } llvmtyp := fr.types.ToLLVM(typ) strval := exact.StringVal(v) strlen := len(strval) i8ptr := llvm.PointerType(llvm.Int8Type(), 0) var ptr llvm.Value if strlen > 0 { init := llvm.ConstString(strval, false) ptr = llvm.AddGlobal(fr.module.Module, init.Type(), "") ptr.SetInitializer(init) ptr.SetLinkage(llvm.InternalLinkage) ptr = llvm.ConstBitCast(ptr, i8ptr) } else { ptr = llvm.ConstNull(i8ptr) } len_ := llvm.ConstInt(fr.types.inttype, uint64(strlen), false) llvmvalue := llvm.Undef(llvmtyp) llvmvalue = llvm.ConstInsertValue(llvmvalue, ptr, []uint32{0}) llvmvalue = llvm.ConstInsertValue(llvmvalue, len_, []uint32{1}) return newValue(llvmvalue, typ) case isInteger(typ): if isUntyped(typ) { typ = types.Typ[types.Int] } llvmtyp := fr.types.ToLLVM(typ) var llvmvalue llvm.Value if isUnsigned(typ) { v, _ := exact.Uint64Val(v) llvmvalue = llvm.ConstInt(llvmtyp, v, false) } else { v, _ := exact.Int64Val(v) llvmvalue = llvm.ConstInt(llvmtyp, uint64(v), true) } return newValue(llvmvalue, typ) case isBoolean(typ): if isUntyped(typ) { typ = types.Typ[types.Bool] } return newValue(boolLLVMValue(exact.BoolVal(v)), typ) case isFloat(typ): if isUntyped(typ) { typ = types.Typ[types.Float64] } llvmtyp := fr.types.ToLLVM(typ) floatval, _ := exact.Float64Val(v) llvmvalue := llvm.ConstFloat(llvmtyp, floatval) return newValue(llvmvalue, typ) case typ == types.Typ[types.UnsafePointer]: llvmtyp := fr.types.ToLLVM(typ) v, _ := exact.Uint64Val(v) llvmvalue := llvm.ConstInt(fr.types.inttype, v, false) llvmvalue = llvm.ConstIntToPtr(llvmvalue, llvmtyp) return newValue(llvmvalue, typ) case isComplex(typ): if isUntyped(typ) { typ = types.Typ[types.Complex128] } llvmtyp := fr.types.ToLLVM(typ) floattyp := llvmtyp.StructElementTypes()[0] llvmvalue := llvm.ConstNull(llvmtyp) realv := exact.Real(v) imagv := exact.Imag(v) realfloatval, _ := exact.Float64Val(realv) imagfloatval, _ := exact.Float64Val(imagv) llvmre := llvm.ConstFloat(floattyp, realfloatval) llvmim := llvm.ConstFloat(floattyp, imagfloatval) llvmvalue = llvm.ConstInsertValue(llvmvalue, llvmre, []uint32{0}) llvmvalue = llvm.ConstInsertValue(llvmvalue, llvmim, []uint32{1}) return newValue(llvmvalue, typ) } // Special case for string -> [](byte|rune) if u, ok := typ.Underlying().(*types.Slice); ok && isInteger(u.Elem()) { if v.Kind() == exact.String { strval := fr.newValueFromConst(v, types.Typ[types.String]) return fr.convert(strval, typ) } } panic(fmt.Sprintf("unhandled: t=%s(%T), v=%v(%T)", typ, typ, v, v)) }