Пример #1
0
func (c *compiler) compareStrings(lhs, rhs *LLVMValue, op token.Token) *LLVMValue {
	strcmp := c.module.Module.NamedFunction("runtime.strcmp")
	if strcmp.IsNil() {
		string_type := c.types.ToLLVM(types.String)
		param_types := []llvm.Type{string_type, string_type}
		func_type := llvm.FunctionType(llvm.Int32Type(), param_types, false)
		strcmp = llvm.AddFunction(c.module.Module, "runtime.strcmp", func_type)
	}
	args := []llvm.Value{lhs.LLVMValue(), rhs.LLVMValue()}
	result := c.builder.CreateCall(strcmp, args, "")
	zero := llvm.ConstNull(llvm.Int32Type())
	var pred llvm.IntPredicate
	switch op {
	case token.EQL:
		pred = llvm.IntEQ
	case token.LSS:
		pred = llvm.IntSLT
	case token.GTR:
		pred = llvm.IntSGT
	case token.LEQ:
		pred = llvm.IntSLE
	case token.GEQ:
		pred = llvm.IntSGE
	case token.NEQ:
		panic("NEQ is handled in LLVMValue.BinaryOp")
	default:
		panic("unreachable")
	}
	result = c.builder.CreateICmp(pred, result, zero, "")
	return c.NewLLVMValue(result, types.Bool)
}
Пример #2
0
// makeSlice allocates a new slice with the optional length and capacity,
// initialising its contents to their zero values.
func (c *compiler) makeSlice(elttyp types.Type, length, capacity Value) llvm.Value {
	var lengthValue llvm.Value
	if length != nil {
		lengthValue = length.Convert(types.Int32).LLVMValue()
	} else {
		lengthValue = llvm.ConstNull(llvm.Int32Type())
	}

	// TODO check capacity >= length
	capacityValue := lengthValue
	if capacity != nil {
		capacityValue = capacity.Convert(types.Int32).LLVMValue()
	}

	eltType := c.types.ToLLVM(elttyp)
	sizeof := llvm.ConstTrunc(llvm.SizeOf(eltType), llvm.Int32Type())
	size := c.builder.CreateMul(capacityValue, sizeof, "")
	mem := c.createMalloc(c.NewLLVMValue(size, types.Int32).Convert(types.Uintptr).LLVMValue())
	mem = c.builder.CreateIntToPtr(mem, llvm.PointerType(eltType, 0), "")
	c.memsetZero(mem, size)

	slicetyp := types.Slice{Elt: elttyp}
	struct_ := llvm.Undef(c.types.ToLLVM(&slicetyp))
	struct_ = c.builder.CreateInsertValue(struct_, mem, 0, "")
	struct_ = c.builder.CreateInsertValue(struct_, lengthValue, 1, "")
	struct_ = c.builder.CreateInsertValue(struct_, capacityValue, 2, "")
	return struct_
}
Пример #3
0
func (c *compiler) defineMemcpyFunction(fn llvm.Value) {
	entry := llvm.AddBasicBlock(fn, "entry")
	c.builder.SetInsertPointAtEnd(entry)
	dst, src, size := fn.Param(0), fn.Param(1), fn.Param(2)

	pint8 := llvm.PointerType(llvm.Int8Type(), 0)
	dst = c.builder.CreateIntToPtr(dst, pint8, "")
	src = c.builder.CreateIntToPtr(src, pint8, "")

	sizeType := size.Type()
	sizeBits := sizeType.IntTypeWidth()
	memcpyName := "llvm.memcpy.p0i8.p0i8.i" + strconv.Itoa(sizeBits)
	memcpy := c.module.NamedFunction(memcpyName)
	if memcpy.IsNil() {
		paramtypes := []llvm.Type{
			pint8, pint8, size.Type(), llvm.Int32Type(), llvm.Int1Type()}
		memcpyType := llvm.FunctionType(llvm.VoidType(), paramtypes, false)
		memcpy = llvm.AddFunction(c.module.Module, memcpyName, memcpyType)
	}

	args := []llvm.Value{
		dst, src, size,
		llvm.ConstInt(llvm.Int32Type(), 1, false), // single byte alignment
		llvm.ConstInt(llvm.Int1Type(), 0, false),  // not volatile
	}
	c.builder.CreateCall(memcpy, args, "")
	c.builder.CreateRetVoid()
}
Пример #4
0
// interfaceMethod returns a function pointer for the specified
// interface and method pair.
func (c *compiler) interfaceMethod(iface *LLVMValue, method *types.Func) *LLVMValue {
	lliface := iface.LLVMValue()
	llitab := c.builder.CreateExtractValue(lliface, 0, "")
	llvalue := c.builder.CreateExtractValue(lliface, 1, "")
	sig := method.Type().(*types.Signature)
	methodset := c.types.MethodSet(sig.Recv().Type())
	// TODO(axw) cache ordered method index
	var index int
	for i := 0; i < methodset.Len(); i++ {
		if methodset.At(i).Obj() == method {
			index = i
			break
		}
	}
	llitab = c.builder.CreateBitCast(llitab, llvm.PointerType(c.runtime.itab.llvm, 0), "")
	llifn := c.builder.CreateGEP(llitab, []llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), 0, false),
		llvm.ConstInt(llvm.Int32Type(), 5, false), // index of itab.fun
	}, "")
	_ = index
	llifn = c.builder.CreateGEP(llifn, []llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(index), false),
	}, "")
	llifn = c.builder.CreateLoad(llifn, "")
	// Strip receiver.
	sig = types.NewSignature(nil, nil, sig.Params(), sig.Results(), sig.Variadic())
	llfn := llvm.Undef(c.types.ToLLVM(sig))
	llifn = c.builder.CreateIntToPtr(llifn, llfn.Type().StructElementTypes()[0], "")
	llfn = c.builder.CreateInsertValue(llfn, llifn, 0, "")
	llfn = c.builder.CreateInsertValue(llfn, llvalue, 1, "")
	return c.NewValue(llfn, sig)
}
Пример #5
0
func (tm *TypeMap) basicLLVMType(b *types.Basic) llvm.Type {
	switch b.Kind {
	case types.BoolKind:
		return llvm.Int1Type()
	case types.Int8Kind, types.Uint8Kind:
		return llvm.Int8Type()
	case types.Int16Kind, types.Uint16Kind:
		return llvm.Int16Type()
	case types.Int32Kind, types.Uint32Kind:
		return llvm.Int32Type()
	case types.Int64Kind, types.Uint64Kind:
		return llvm.Int64Type()
	case types.Float32Kind:
		return llvm.FloatType()
	case types.Float64Kind:
		return llvm.DoubleType()
	case types.UnsafePointerKind, types.UintptrKind,
		types.UintKind, types.IntKind:
		return tm.target.IntPtrType()
	//case Complex64: TODO
	//case Complex128:
	//case UntypedInt:
	//case UntypedFloat:
	//case UntypedComplex:
	case types.StringKind:
		i8ptr := llvm.PointerType(llvm.Int8Type(), 0)
		elements := []llvm.Type{i8ptr, llvm.Int32Type()}
		return llvm.StructType(elements, false)
	}
	panic(fmt.Sprint("unhandled kind: ", b.Kind))
}
Пример #6
0
func (tm *TypeMap) sliceLLVMType(s *types.Slice) llvm.Type {
	elements := []llvm.Type{
		llvm.PointerType(tm.ToLLVM(s.Elt), 0),
		llvm.Int32Type(),
		llvm.Int32Type(),
	}
	return llvm.StructType(elements, false)
}
Пример #7
0
func (c *compiler) VisitSliceExpr(expr *ast.SliceExpr) Value {
	// expr.X, expr.Low, expr.High
	value := c.VisitExpr(expr.X)
	var low, high llvm.Value
	if expr.Low != nil {
		low = c.VisitExpr(expr.Low).Convert(types.Int32).LLVMValue()
	} else {
		low = llvm.ConstNull(llvm.Int32Type())
	}
	if expr.High != nil {
		high = c.VisitExpr(expr.High).Convert(types.Int32).LLVMValue()
	} else {
		high = llvm.ConstAllOnes(llvm.Int32Type()) // -1
	}

	if _, ok := types.Underlying(value.Type()).(*types.Pointer); ok {
		value = value.(*LLVMValue).makePointee()
	}

	switch typ := types.Underlying(value.Type()).(type) {
	case *types.Array:
		sliceslice := c.NamedFunction("runtime.sliceslice", "func f(t uintptr, s slice, low, high int32) slice")
		i8slice := sliceslice.Type().ElementType().ReturnType()
		sliceValue := llvm.Undef(i8slice) // temporary slice
		arrayptr := value.(*LLVMValue).pointer.LLVMValue()
		arrayptr = c.builder.CreateBitCast(arrayptr, i8slice.StructElementTypes()[0], "")
		arraylen := llvm.ConstInt(llvm.Int32Type(), typ.Len, false)
		sliceValue = c.builder.CreateInsertValue(sliceValue, arrayptr, 0, "")
		sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 1, "")
		sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 2, "")
		sliceTyp := &types.Slice{Elt: typ.Elt}
		runtimeTyp := c.types.ToRuntime(sliceTyp)
		runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
		args := []llvm.Value{runtimeTyp, sliceValue, low, high}
		result := c.builder.CreateCall(sliceslice, args, "")
		llvmSliceTyp := c.types.ToLLVM(sliceTyp)
		return c.NewLLVMValue(c.coerceSlice(result, llvmSliceTyp), sliceTyp)
	case *types.Slice:
		sliceslice := c.NamedFunction("runtime.sliceslice", "func f(t uintptr, s slice, low, high int32) slice")
		i8slice := sliceslice.Type().ElementType().ReturnType()
		sliceValue := value.LLVMValue()
		sliceTyp := sliceValue.Type()
		sliceValue = c.coerceSlice(sliceValue, i8slice)
		runtimeTyp := c.types.ToRuntime(value.Type())
		runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
		args := []llvm.Value{runtimeTyp, sliceValue, low, high}
		result := c.builder.CreateCall(sliceslice, args, "")
		return c.NewLLVMValue(c.coerceSlice(result, sliceTyp), value.Type())
	case *types.Name: // String
		stringslice := c.NamedFunction("runtime.stringslice", "func f(a string, low, high int32) string")
		args := []llvm.Value{value.LLVMValue(), low, high}
		result := c.builder.CreateCall(stringslice, args, "")
		return c.NewLLVMValue(result, value.Type())
	default:
		panic("unimplemented")
	}
	panic("unreachable")
}
Пример #8
0
func (v ConstValue) LLVMValue() llvm.Value {
	typ := types.Underlying(v.Type())
	switch typ {
	case types.Int, types.Uint:
		return llvm.ConstInt(llvm.Int32Type(), uint64(v.Int64()), true)
		// TODO 32/64bit (probably wait for gc)
		//int_val := v.Val.(*big.Int)
		//if int_val.Cmp(maxBigInt32) > 0 || int_val.Cmp(minBigInt32) < 0 {
		//	panic(fmt.Sprint("const ", int_val, " overflows int"))
		//}
		//return llvm.ConstInt(v.compiler.target.IntPtrType(), uint64(v.Int64()), true)
	case types.Uint:
		return llvm.ConstInt(llvm.Int32Type(), uint64(v.Int64()), false)

	case types.Int8:
		return llvm.ConstInt(llvm.Int8Type(), uint64(v.Int64()), true)
	case types.Uint8, types.Byte:
		return llvm.ConstInt(llvm.Int8Type(), uint64(v.Int64()), false)

	case types.Int16:
		return llvm.ConstInt(llvm.Int16Type(), uint64(v.Int64()), true)
	case types.Uint16:
		return llvm.ConstInt(llvm.Int16Type(), uint64(v.Int64()), false)

	case types.Int32, types.Rune:
		return llvm.ConstInt(llvm.Int32Type(), uint64(v.Int64()), true)
	case types.Uint32:
		return llvm.ConstInt(llvm.Int32Type(), uint64(v.Int64()), false)

	case types.Int64:
		return llvm.ConstInt(llvm.Int64Type(), uint64(v.Int64()), true)
	case types.Uint64:
		return llvm.ConstInt(llvm.Int64Type(), uint64(v.Int64()), true)

	case types.Float32:
		return llvm.ConstFloat(llvm.FloatType(), float64(v.Float64()))
	case types.Float64:
		return llvm.ConstFloat(llvm.DoubleType(), float64(v.Float64()))

	case types.UnsafePointer, types.Uintptr:
		inttype := v.compiler.target.IntPtrType()
		return llvm.ConstInt(inttype, uint64(v.Int64()), false)

	case types.String:
		strval := (v.Val).(string)
		ptr := v.compiler.builder.CreateGlobalStringPtr(strval, "")
		len_ := llvm.ConstInt(llvm.Int32Type(), uint64(len(strval)), false)
		return llvm.ConstStruct([]llvm.Value{ptr, len_}, false)

	case types.Bool:
		if v := v.Val.(bool); v {
			return llvm.ConstAllOnes(llvm.Int1Type())
		}
		return llvm.ConstNull(llvm.Int1Type())
	}
	panic(fmt.Errorf("Unhandled type: %v", typ)) //v.typ.Kind))
}
Пример #9
0
func (d *debugInfo) setLocation(b llvm.Builder, pos token.Pos) {
	position := d.Fset.Position(pos)
	b.SetCurrentDebugLocation(llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(position.Line), true),
		llvm.ConstInt(llvm.Int32Type(), uint64(position.Column), true),
		d.MDNode(d.context()),
		llvm.Value{},
	}))
}
Пример #10
0
func (d *BlockDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		info.mdFileNode(d.File),
		info.MDNode(d.Context),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Column), false),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Id), false),
	})
}
Пример #11
0
func (c *compiler) createMainFunction() error {
	// In a PNaCl program (plugin), there should not be a "main.main";
	// instead, we expect a "main.CreateModule" function.
	// See pkg/nacl/ppapi/ppapi.go for more details.
	mainMain := c.module.NamedFunction("main.main")
	/*
		if c.pnacl {
			// PNaCl's libppapi_stub.a implements "main", which simply
			// calls through to PpapiPluginMain. We define our own "main"
			// so that we can capture argc/argv.
			if !mainMain.IsNil() {
				return fmt.Errorf("Found main.main")
			}
			pluginMain := c.RuntimeFunction("PpapiPluginMain", "func() int32")

			// Synthesise a main which has no return value. We could cast
			// PpapiPluginMain, but this is potentially unsafe as its
			// calling convention is unspecified.
			ftyp := llvm.FunctionType(llvm.VoidType(), nil, false)
			mainMain = llvm.AddFunction(c.module.Module, "main.main", ftyp)
			entry := llvm.AddBasicBlock(mainMain, "entry")
			c.builder.SetInsertPointAtEnd(entry)
			c.builder.CreateCall(pluginMain, nil, "")
			c.builder.CreateRetVoid()
		} else */{
		mainMain = c.module.NamedFunction("main.main")
	}

	if mainMain.IsNil() {
		return fmt.Errorf("Could not find main.main")
	}

	// runtime.main is called by main, with argc, argv, argp,
	// and a pointer to main.main, which must be a niladic
	// function with no result.
	runtimeMain := c.runtime.main.LLVMValue()

	ptrptr := llvm.PointerType(llvm.PointerType(llvm.Int8Type(), 0), 0)
	ftyp := llvm.FunctionType(llvm.Int32Type(), []llvm.Type{llvm.Int32Type(), ptrptr, ptrptr}, true)
	main := llvm.AddFunction(c.module.Module, "main", ftyp)

	c.builder.SetCurrentDebugLocation(c.debug.MDNode(nil))
	entry := llvm.AddBasicBlock(main, "entry")
	c.builder.SetInsertPointAtEnd(entry)
	runtimeMainParamTypes := runtimeMain.Type().ElementType().ParamTypes()
	args := []llvm.Value{
		main.Param(0), // argc
		main.Param(1), // argv
		main.Param(2), // argp
		c.builder.CreateBitCast(mainMain, runtimeMainParamTypes[3], ""),
	}
	result := c.builder.CreateCall(runtimeMain, args, "")
	c.builder.CreateRet(result)
	return nil
}
Пример #12
0
func (d *LocalVariableDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		info.MDNode(d.Context),
		llvm.MDString(d.Name),
		info.mdFileNode(d.File),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Line)|(uint64(d.Argument)<<24), false),
		info.MDNode(d.Type),
		llvm.ConstNull(llvm.Int32Type()), // flags
		llvm.ConstNull(llvm.Int32Type()), // optional reference to inline location
	})
}
Пример #13
0
func (d *DerivedTypeDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), llvm.LLVMDebugVersion+uint64(d.Tag()), false),
		FileDescriptor(d.File).path(),
		info.MDNode(d.Context),
		llvm.MDString(d.Name),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false),
		llvm.ConstInt(llvm.Int64Type(), d.Size, false),
		llvm.ConstInt(llvm.Int64Type(), d.Alignment, false),
		llvm.ConstInt(llvm.Int64Type(), d.Offset, false),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Flags), false),
		info.MDNode(d.Base)})
}
Пример #14
0
func (d *GlobalVariableDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		llvm.ConstNull(llvm.Int32Type()),
		info.MDNode(d.Context),
		llvm.MDString(d.Name),
		llvm.MDString(d.DisplayName),
		llvm.MDNode(nil),
		info.mdFileNode(d.File),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false),
		info.MDNode(d.Type),
		constInt1(d.Local),
		constInt1(!d.External),
		d.Value})
}
Пример #15
0
func addExterns(m *llgo.Module) {
	CharPtr := llvm.PointerType(llvm.Int8Type(), 0)
	fn_type := llvm.FunctionType(
		llvm.Int32Type(), []llvm.Type{CharPtr}, false)
	fflush := llvm.AddFunction(m.Module, "fflush", fn_type)
	fflush.SetFunctionCallConv(llvm.CCallConv)
}
Пример #16
0
func (c *compiler) makeSlice(v []llvm.Value, elttyp types.Type) llvm.Value {
	n := llvm.ConstInt(llvm.Int32Type(), uint64(len(v)), false)
	mem := c.builder.CreateArrayMalloc(c.types.ToLLVM(elttyp), n, "")
	for i, value := range v {
		indices := []llvm.Value{
			llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
		ep := c.builder.CreateGEP(mem, indices, "")
		c.builder.CreateStore(value, ep)
	}
	slicetyp := types.Slice{Elt: elttyp}
	struct_ := c.builder.CreateAlloca(c.types.ToLLVM(&slicetyp), "")
	c.builder.CreateStore(mem, c.builder.CreateStructGEP(struct_, 0, ""))
	c.builder.CreateStore(n, c.builder.CreateStructGEP(struct_, 1, ""))
	c.builder.CreateStore(n, c.builder.CreateStructGEP(struct_, 2, ""))
	return c.builder.CreateLoad(struct_, "")
}
Пример #17
0
// makeSlice allocates a new slice, storing in it the provided elements.
func (c *compiler) makeSlice(v []llvm.Value, elttyp types.Type) llvm.Value {
	n := llvm.ConstInt(llvm.Int32Type(), uint64(len(v)), false)
	llvmelttyp := c.types.ToLLVM(elttyp)
	mem := c.builder.CreateArrayMalloc(llvmelttyp, n, "")
	for i, value := range v {
		indices := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
		ep := c.builder.CreateGEP(mem, indices, "")
		c.builder.CreateStore(value, ep)
	}
	slicetyp := types.Slice{Elt: elttyp}
	struct_ := llvm.Undef(c.types.ToLLVM(&slicetyp))
	struct_ = c.builder.CreateInsertValue(struct_, mem, 0, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 1, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 2, "")
	return struct_
}
Пример #18
0
func (tm *llvmTypeMap) basicLLVMType(b *types.Basic) llvm.Type {
	switch b.Kind() {
	case types.Bool:
		return llvm.Int1Type()
	case types.Int8, types.Uint8:
		return llvm.Int8Type()
	case types.Int16, types.Uint16:
		return llvm.Int16Type()
	case types.Int32, types.Uint32:
		return llvm.Int32Type()
	case types.Uint, types.Int:
		return tm.inttype
	case types.Int64, types.Uint64:
		return llvm.Int64Type()
	case types.Float32:
		return llvm.FloatType()
	case types.Float64:
		return llvm.DoubleType()
	case types.UnsafePointer, types.Uintptr:
		return tm.target.IntPtrType()
	case types.Complex64:
		f32 := llvm.FloatType()
		elements := []llvm.Type{f32, f32}
		return llvm.StructType(elements, false)
	case types.Complex128:
		f64 := llvm.DoubleType()
		elements := []llvm.Type{f64, f64}
		return llvm.StructType(elements, false)
	case types.String:
		i8ptr := llvm.PointerType(llvm.Int8Type(), 0)
		elements := []llvm.Type{i8ptr, tm.inttype}
		return llvm.StructType(elements, false)
	}
	panic(fmt.Sprint("unhandled kind: ", b.Kind))
}
Пример #19
0
func (c *compiler) VisitAppend(expr *ast.CallExpr) Value {
	// TODO handle ellpisis arg
	s := c.VisitExpr(expr.Args[0])
	elem := c.VisitExpr(expr.Args[1])

	sliceappend := c.NamedFunction("runtime.sliceappend", "func f(t uintptr, dst, src slice) slice")
	i8slice := sliceappend.Type().ElementType().ReturnType()
	i8ptr := c.types.ToLLVM(&types.Pointer{Base: types.Int8})

	// Coerce first argument into an []int8.
	a_ := s.LLVMValue()
	sliceTyp := a_.Type()
	a := c.coerceSlice(a_, i8slice)

	// Construct a fresh []int8 for the temporary slice.
	b_ := elem.LLVMValue()
	one := llvm.ConstInt(llvm.Int32Type(), 1, false)
	mem := c.builder.CreateAlloca(elem.LLVMValue().Type(), "")
	c.builder.CreateStore(b_, mem)
	b := llvm.Undef(i8slice)
	b = c.builder.CreateInsertValue(b, c.builder.CreateBitCast(mem, i8ptr, ""), 0, "")
	b = c.builder.CreateInsertValue(b, one, 1, "")
	b = c.builder.CreateInsertValue(b, one, 2, "")

	// Call runtime function, then coerce the result.
	runtimeTyp := c.types.ToRuntime(s.Type())
	runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
	args := []llvm.Value{runtimeTyp, a, b}
	result := c.builder.CreateCall(sliceappend, args, "")
	return c.NewLLVMValue(c.coerceSlice(result, sliceTyp), s.Type())
}
Пример #20
0
func (d subrangeDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		llvm.ConstInt(llvm.Int64Type(), uint64(d.low), true),
		llvm.ConstInt(llvm.Int64Type(), uint64(d.high), true),
	})
}
Пример #21
0
func (c *compiler) compareStrings(lhs, rhs *LLVMValue, op token.Token) *LLVMValue {
	strcmp := c.NamedFunction("runtime.strcmp", "func(a, b _string) int32")
	_string := strcmp.Type().ElementType().ParamTypes()[0]
	lhsstr := c.coerceString(lhs.LLVMValue(), _string)
	rhsstr := c.coerceString(rhs.LLVMValue(), _string)
	args := []llvm.Value{lhsstr, rhsstr}
	result := c.builder.CreateCall(strcmp, args, "")
	zero := llvm.ConstNull(llvm.Int32Type())
	var pred llvm.IntPredicate
	switch op {
	case token.EQL:
		pred = llvm.IntEQ
	case token.LSS:
		pred = llvm.IntSLT
	case token.GTR:
		pred = llvm.IntSGT
	case token.LEQ:
		pred = llvm.IntSLE
	case token.GEQ:
		pred = llvm.IntSGE
	case token.NEQ:
		panic("NEQ is handled in LLVMValue.BinaryOp")
	default:
		panic("unreachable")
	}
	result = c.builder.CreateICmp(pred, result, zero, "")
	return c.NewValue(result, types.Typ[types.Bool])
}
Пример #22
0
func reorderGlobalConstructors(m llvm.Module) error {
	ctors := m.NamedGlobal("llvm.global_ctors")
	if ctors.IsNil() {
		// No global constructors.
		return nil
	}

	init := ctors.Initializer()
	arraylength := init.Type().ArrayLength()
	zeroindex := []uint32{0}

	// The constructors are ordered within each package, but the packages
	// are in reverse order. We must go backwards through the constructors,
	// reassigning priorities.
	ceiling, npackagectors := -1, -1
	for i := arraylength - 1; i >= 0; i-- {
		indices := []uint32{uint32(i)}
		ctor := llvm.ConstExtractValue(init, indices)
		priority := int(llvm.ConstExtractValue(ctor, zeroindex).ZExtValue())
		if npackagectors == -1 {
			ceiling = arraylength - (i + 1) + priority
			npackagectors = priority
		}
		newpriority := ceiling - (npackagectors - priority)
		newpriorityvalue := llvm.ConstInt(llvm.Int32Type(), uint64(newpriority), false)
		ctor = llvm.ConstInsertValue(ctor, newpriorityvalue, zeroindex)
		if priority == 1 {
			npackagectors = -1
		}
		init = llvm.ConstInsertValue(init, ctor, indices)
	}
	ctors.SetInitializer(init)
	return nil
}
Пример #23
0
func (d *CompositeTypeDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), llvm.LLVMDebugVersion+uint64(d.Tag()), false),
		FileDescriptor(d.File).path(),
		info.MDNode(d.Context),
		llvm.MDString(d.Name),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false),
		llvm.ConstInt(llvm.Int64Type(), d.Size, false),
		llvm.ConstInt(llvm.Int64Type(), d.Alignment, false),
		llvm.ConstInt(llvm.Int64Type(), d.Offset, false),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Flags), false),
		info.MDNode(d.Base), // reference type derived from
		llvm.MDNode(info.MDNodes(d.Members)),
		llvm.ConstInt(llvm.Int32Type(), uint64(0), false), // Runtime language
		llvm.ConstInt(llvm.Int32Type(), uint64(0), false), // Base type containing the vtable pointer for this type
	})
}
Пример #24
0
func (d *CompileUnitDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		d.Path.path(),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Language), false),
		llvm.MDString(d.Producer),
		constInt1(d.Optimized),
		llvm.MDString(d.CompilerFlags),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Runtime), false),
		d.mdNodeList(info, d.EnumTypes),
		d.mdNodeList(info, d.RetainedTypes),
		d.mdNodeList(info, d.Subprograms),
		d.mdNodeList(info, d.GlobalVariables),
		d.mdNodeList(info, nil), // List of imported entities
		llvm.MDString(""),       // Split debug filename
	})
}
Пример #25
0
func (tm *TypeMap) makeRuntimeTypeGlobal(v llvm.Value) (global, ptr llvm.Value) {
	// Each runtime type is preceded by an interface{}.
	initType := llvm.StructType([]llvm.Type{tm.runtimeType, v.Type()}, false)
	global = llvm.AddGlobal(tm.module, initType, "")
	ptr = llvm.ConstBitCast(global, llvm.PointerType(tm.runtimeType, 0))

	// interface{} containing v's *commonType representation.
	runtimeTypeValue := llvm.Undef(tm.runtimeType)
	zero := llvm.ConstNull(llvm.Int32Type())
	one := llvm.ConstInt(llvm.Int32Type(), 1, false)
	i8ptr := llvm.PointerType(llvm.Int8Type(), 0)
	if tm.commonTypePtrRuntimeType.IsNil() {
		// Create a dummy pointer value, which we'll update straight after
		// defining the runtime type info for commonType.
		tm.commonTypePtrRuntimeType = llvm.Undef(i8ptr)
		commonTypePtr := &types.Pointer{Base: tm.commonType}
		commonTypeGlobal, commonTypeRuntimeType := tm.makeRuntimeType(tm.commonType)
		tm.types[tm.commonType.String()] = runtimeTypeInfo{commonTypeGlobal, commonTypeRuntimeType}
		commonTypePtrGlobal, commonTypePtrRuntimeType := tm.makeRuntimeType(commonTypePtr)
		tm.types[commonTypePtr.String()] = runtimeTypeInfo{commonTypePtrGlobal, commonTypePtrRuntimeType}
		tm.commonTypePtrRuntimeType = llvm.ConstBitCast(commonTypePtrRuntimeType, i8ptr)
		if tm.pkgpath == tm.commonType.Package {
			// Update the interace{} header of the commonType/*commonType
			// runtime types we just created.
			for _, g := range [...]llvm.Value{commonTypeGlobal, commonTypePtrGlobal} {
				init := g.Initializer()
				typptr := tm.commonTypePtrRuntimeType
				runtimeTypeValue := llvm.ConstExtractValue(init, []uint32{0})
				runtimeTypeValue = llvm.ConstInsertValue(runtimeTypeValue, typptr, []uint32{0})
				init = llvm.ConstInsertValue(init, runtimeTypeValue, []uint32{0})
				g.SetInitializer(init)
			}
		}
	}
	commonTypePtr := llvm.ConstGEP(global, []llvm.Value{zero, one})
	commonTypePtr = llvm.ConstBitCast(commonTypePtr, i8ptr)
	runtimeTypeValue = llvm.ConstInsertValue(runtimeTypeValue, tm.commonTypePtrRuntimeType, []uint32{0})
	runtimeTypeValue = llvm.ConstInsertValue(runtimeTypeValue, commonTypePtr, []uint32{1})

	init := llvm.Undef(initType)
	init = llvm.ConstInsertValue(init, runtimeTypeValue, []uint32{0})
	init = llvm.ConstInsertValue(init, v, []uint32{1})
	global.SetInitializer(init)

	return global, ptr
}
Пример #26
0
// makeLiteralSlice allocates a new slice, storing in it the provided elements.
func (c *compiler) makeLiteralSlice(v []llvm.Value, elttyp types.Type) llvm.Value {
	n := llvm.ConstInt(llvm.Int32Type(), uint64(len(v)), false)
	eltType := c.types.ToLLVM(elttyp)
	arrayType := llvm.ArrayType(eltType, len(v))
	mem := c.createMalloc(llvm.SizeOf(arrayType))
	mem = c.builder.CreateIntToPtr(mem, llvm.PointerType(eltType, 0), "")
	for i, value := range v {
		indices := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
		ep := c.builder.CreateGEP(mem, indices, "")
		c.builder.CreateStore(value, ep)
	}
	slicetyp := types.Slice{Elt: elttyp}
	struct_ := llvm.Undef(c.types.ToLLVM(&slicetyp))
	struct_ = c.builder.CreateInsertValue(struct_, mem, 0, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 1, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 2, "")
	return struct_
}
Пример #27
0
func (d FileDescriptor) mdNode(info *DebugInfo) llvm.Value {
	if d == "" {
		return llvm.Value{}
	}
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), llvm.LLVMDebugVersion+uint64(d.Tag()), false),
		d.path(),
	})
}
Пример #28
0
func getFflush(module llvm.Module) llvm.Value {
	fflush := module.NamedFunction("fflush")
	if fflush.IsNil() {
		voidPtr := llvm.PointerType(llvm.Int8Type(), 0)
		ftyp := llvm.FunctionType(llvm.Int32Type(), []llvm.Type{voidPtr}, false)
		fflush = llvm.AddFunction(module, "fflush", ftyp)
		fflush.SetFunctionCallConv(llvm.CCallConv)
	}
	return fflush
}
Пример #29
0
func getPrintf(module llvm.Module) llvm.Value {
	printf := module.NamedFunction("printf")
	if printf.IsNil() {
		charPtr := llvm.PointerType(llvm.Int8Type(), 0)
		ftyp := llvm.FunctionType(llvm.Int32Type(), []llvm.Type{charPtr}, true)
		printf = llvm.AddFunction(module, "printf", ftyp)
		printf.SetFunctionCallConv(llvm.CCallConv)
	}
	return printf
}
Пример #30
0
// globalStringPtr returns a *string with the specified value.
func (tm *TypeMap) globalStringPtr(value string) llvm.Value {
	strval := llvm.ConstString(value, false)
	strglobal := llvm.AddGlobal(tm.module, strval.Type(), "")
	strglobal.SetInitializer(strval)
	strglobal = llvm.ConstBitCast(strglobal, llvm.PointerType(llvm.Int8Type(), 0))
	strlen := llvm.ConstInt(llvm.Int32Type(), uint64(len(value)), false)
	str := llvm.ConstStruct([]llvm.Value{strglobal, strlen}, false)
	g := llvm.AddGlobal(tm.module, str.Type(), "")
	g.SetInitializer(str)
	return g
}