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)
}
Beispiel #2
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())
}
Beispiel #3
0
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
}
Beispiel #5
0
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
}
Beispiel #6
0
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)
}
Beispiel #8
0
// 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))
}