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 primitiveTypeToLLVMType(typ parser.PrimitiveType) llvm.Type { switch typ { case parser.PRIMITIVE_int, parser.PRIMITIVE_uint: return llvm.IntType(intSize * 8) case parser.PRIMITIVE_s8, parser.PRIMITIVE_u8: return llvm.IntType(8) case parser.PRIMITIVE_s16, parser.PRIMITIVE_u16: return llvm.IntType(16) case parser.PRIMITIVE_s32, parser.PRIMITIVE_u32: return llvm.IntType(32) case parser.PRIMITIVE_s64, parser.PRIMITIVE_u64: return llvm.IntType(64) case parser.PRIMITIVE_i128, parser.PRIMITIVE_u128: return llvm.IntType(128) case parser.PRIMITIVE_f32: return llvm.FloatType() case parser.PRIMITIVE_f64: return llvm.DoubleType() case parser.PRIMITIVE_f128: return llvm.FP128Type() case parser.PRIMITIVE_rune: // runes are signed 32-bit int return llvm.IntType(32) case parser.PRIMITIVE_bool: return llvm.IntType(1) case parser.PRIMITIVE_str: return llvm.PointerType(llvm.IntType(8), 0) default: panic("Unimplemented primitive type in LLVM codegen") } }
func (v *Codegen) primitiveTypeToLLVMType(typ parser.PrimitiveType) llvm.Type { switch typ { case parser.PRIMITIVE_int, parser.PRIMITIVE_uint: return v.targetData.IntPtrType() case parser.PRIMITIVE_s8, parser.PRIMITIVE_u8: return llvm.IntType(8) case parser.PRIMITIVE_s16, parser.PRIMITIVE_u16: return llvm.IntType(16) case parser.PRIMITIVE_s32, parser.PRIMITIVE_u32: return llvm.IntType(32) case parser.PRIMITIVE_s64, parser.PRIMITIVE_u64: return llvm.IntType(64) case parser.PRIMITIVE_s128, parser.PRIMITIVE_u128: return llvm.IntType(128) case parser.PRIMITIVE_f32: return llvm.FloatType() case parser.PRIMITIVE_f64: return llvm.DoubleType() case parser.PRIMITIVE_f128: return llvm.FP128Type() case parser.PRIMITIVE_rune: // runes are signed 32-bit int return llvm.IntType(32) case parser.PRIMITIVE_bool: return llvm.IntType(1) case parser.PRIMITIVE_void: return llvm.VoidType() default: panic("Unimplemented primitive type in LLVM codegen") } }
func (p *Parser) handleTop() { if fn := p.parseTop(); fn != nil { if ir := fn.Gen(p, p.cg); !ir.IsNil() { ir.Dump() ret := p.cg.EE.RunFunction(ir, []llvm.GenericValue{}) fmt.Printf("Evaluated to: %v\n", ret.Float(llvm.DoubleType())) p.cg.Init() } } else { p.next() } }
func (n *ProtoDecl) Gen(cg *CG) llvm.Value { var args []llvm.Type for _ = range n.Args { args = append(args, llvm.DoubleType()) } typ := llvm.FunctionType(llvm.DoubleType(), args, false) fun := llvm.AddFunction(cg.Mod, n.Name, typ) if fun.BasicBlocksCount() != 0 { return errv("redefinition of function: " + n.Name) } if fun.ParamsCount() != len(n.Args) { return errv("redefinition of function with different number of args") } for i, param := range fun.Params() { param.SetName(n.Args[i]) } return fun }
func createEntryBlockAlloca(f llvm.Value, name string) llvm.Value { b := llvm.NewBuilder() b.SetInsertPoint(f.EntryBasicBlock(), f.EntryBasicBlock().FirstInstruction()) return b.CreateAlloca(llvm.DoubleType(), name) }
func (fr *frame) convert(v *govalue, dsttyp types.Type) *govalue { b := fr.builder // If it's a stack allocated value, we'll want to compare the // value type, not the pointer type. srctyp := v.typ // Get the underlying type, if any. origdsttyp := dsttyp dsttyp = dsttyp.Underlying() srctyp = srctyp.Underlying() // Identical (underlying) types? Just swap in the destination type. if types.Identical(srctyp, dsttyp) { return newValue(v.value, origdsttyp) } // Both pointer types with identical underlying types? Same as above. if srctyp, ok := srctyp.(*types.Pointer); ok { if dsttyp, ok := dsttyp.(*types.Pointer); ok { srctyp := srctyp.Elem().Underlying() dsttyp := dsttyp.Elem().Underlying() if types.Identical(srctyp, dsttyp) { return newValue(v.value, origdsttyp) } } } // string -> if isString(srctyp) { // (untyped) string -> string // XXX should untyped strings be able to escape go/types? if isString(dsttyp) { return newValue(v.value, origdsttyp) } // string -> []byte if isSlice(dsttyp, types.Byte) { value := v.value strdata := fr.builder.CreateExtractValue(value, 0, "") strlen := fr.builder.CreateExtractValue(value, 1, "") // Data must be copied, to prevent changes in // the byte slice from mutating the string. newdata := fr.createMalloc(strlen, false) fr.memcpy(newdata, strdata, strlen) struct_ := llvm.Undef(fr.types.ToLLVM(dsttyp)) struct_ = fr.builder.CreateInsertValue(struct_, newdata, 0, "") struct_ = fr.builder.CreateInsertValue(struct_, strlen, 1, "") struct_ = fr.builder.CreateInsertValue(struct_, strlen, 2, "") return newValue(struct_, origdsttyp) } // string -> []rune if isSlice(dsttyp, types.Rune) { return fr.stringToRuneSlice(v) } } // []byte -> string if isSlice(srctyp, types.Byte) && isString(dsttyp) { value := v.value data := fr.builder.CreateExtractValue(value, 0, "") len := fr.builder.CreateExtractValue(value, 1, "") // Data must be copied, to prevent changes in // the byte slice from mutating the string. newdata := fr.createMalloc(len, false) fr.memcpy(newdata, data, len) struct_ := llvm.Undef(fr.types.ToLLVM(types.Typ[types.String])) struct_ = fr.builder.CreateInsertValue(struct_, newdata, 0, "") struct_ = fr.builder.CreateInsertValue(struct_, len, 1, "") return newValue(struct_, types.Typ[types.String]) } // []rune -> string if isSlice(srctyp, types.Rune) && isString(dsttyp) { return fr.runeSliceToString(v) } // rune -> string if isString(dsttyp) && isInteger(srctyp) { return fr.runeToString(v) } // Unsafe pointer conversions. llvm_type := fr.types.ToLLVM(dsttyp) if dsttyp == types.Typ[types.UnsafePointer] { // X -> unsafe.Pointer if _, isptr := srctyp.(*types.Pointer); isptr { return newValue(v.value, origdsttyp) } else if srctyp == types.Typ[types.Uintptr] { value := b.CreateIntToPtr(v.value, llvm_type, "") return newValue(value, origdsttyp) } } else if srctyp == types.Typ[types.UnsafePointer] { // unsafe.Pointer -> X if _, isptr := dsttyp.(*types.Pointer); isptr { return newValue(v.value, origdsttyp) } else if dsttyp == types.Typ[types.Uintptr] { value := b.CreatePtrToInt(v.value, llvm_type, "") return newValue(value, origdsttyp) } } lv := v.value srcType := lv.Type() switch srcType.TypeKind() { case llvm.IntegerTypeKind: switch llvm_type.TypeKind() { case llvm.IntegerTypeKind: srcBits := srcType.IntTypeWidth() dstBits := llvm_type.IntTypeWidth() delta := srcBits - dstBits switch { case delta < 0: if !isUnsigned(srctyp) { lv = b.CreateSExt(lv, llvm_type, "") } else { lv = b.CreateZExt(lv, llvm_type, "") } case delta > 0: lv = b.CreateTrunc(lv, llvm_type, "") } return newValue(lv, origdsttyp) case llvm.FloatTypeKind, llvm.DoubleTypeKind: if !isUnsigned(v.Type()) { lv = b.CreateSIToFP(lv, llvm_type, "") } else { lv = b.CreateUIToFP(lv, llvm_type, "") } return newValue(lv, origdsttyp) } case llvm.DoubleTypeKind: switch llvm_type.TypeKind() { case llvm.FloatTypeKind: lv = b.CreateFPTrunc(lv, llvm_type, "") return newValue(lv, origdsttyp) case llvm.IntegerTypeKind: if !isUnsigned(dsttyp) { lv = b.CreateFPToSI(lv, llvm_type, "") } else { lv = b.CreateFPToUI(lv, llvm_type, "") } return newValue(lv, origdsttyp) } case llvm.FloatTypeKind: switch llvm_type.TypeKind() { case llvm.DoubleTypeKind: lv = b.CreateFPExt(lv, llvm_type, "") return newValue(lv, origdsttyp) case llvm.IntegerTypeKind: if !isUnsigned(dsttyp) { lv = b.CreateFPToSI(lv, llvm_type, "") } else { lv = b.CreateFPToUI(lv, llvm_type, "") } return newValue(lv, origdsttyp) } } // Complex -> complex. Complexes are only convertible to other // complexes, contant conversions aside. So we can just check the // source type here; given that the types are not identical // (checked above), we can assume the destination type is the alternate // complex type. if isComplex(srctyp) { var fpcast func(llvm.Builder, llvm.Value, llvm.Type, string) llvm.Value var fptype llvm.Type if srctyp == types.Typ[types.Complex64] { fpcast = (llvm.Builder).CreateFPExt fptype = llvm.DoubleType() } else { fpcast = (llvm.Builder).CreateFPTrunc fptype = llvm.FloatType() } if fpcast != nil { realv := b.CreateExtractValue(lv, 0, "") imagv := b.CreateExtractValue(lv, 1, "") realv = fpcast(b, realv, fptype, "") imagv = fpcast(b, imagv, fptype, "") lv = llvm.Undef(fr.types.ToLLVM(dsttyp)) lv = b.CreateInsertValue(lv, realv, 0, "") lv = b.CreateInsertValue(lv, imagv, 1, "") return newValue(lv, origdsttyp) } } panic(fmt.Sprintf("unimplemented conversion: %s (%s) -> %s", v.typ, lv.Type(), origdsttyp)) }