compiler: rename Compiler.getValue -> builder.getValue
This is a fairly big commit, but it actually changes very little. getValue should really be a property of the builder (or frame), where the previously created instructions are kept.
Этот коммит содержится в:
		
							родитель
							
								
									840acdd316
								
							
						
					
					
						коммит
						349ecf1736
					
				
					 13 изменённых файлов: 122 добавлений и 110 удалений
				
			
		| 
						 | 
				
			
			@ -14,7 +14,7 @@ import (
 | 
			
		|||
func (c *Compiler) emitMakeChan(frame *Frame, expr *ssa.MakeChan) llvm.Value {
 | 
			
		||||
	elementSize := c.targetData.TypeAllocSize(c.getLLVMType(expr.Type().(*types.Chan).Elem()))
 | 
			
		||||
	elementSizeValue := llvm.ConstInt(c.uintptrType, elementSize, false)
 | 
			
		||||
	bufSize := c.getValue(frame, expr.Size)
 | 
			
		||||
	bufSize := frame.getValue(expr.Size)
 | 
			
		||||
	c.emitChanBoundsCheck(frame, elementSize, bufSize, expr.Size.Type().Underlying().(*types.Basic), expr.Pos())
 | 
			
		||||
	if bufSize.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
 | 
			
		||||
		bufSize = c.builder.CreateZExt(bufSize, c.uintptrType, "")
 | 
			
		||||
| 
						 | 
				
			
			@ -27,8 +27,8 @@ func (c *Compiler) emitMakeChan(frame *Frame, expr *ssa.MakeChan) llvm.Value {
 | 
			
		|||
// emitChanSend emits a pseudo chan send operation. It is lowered to the actual
 | 
			
		||||
// channel send operation during goroutine lowering.
 | 
			
		||||
func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) {
 | 
			
		||||
	ch := c.getValue(frame, instr.Chan)
 | 
			
		||||
	chanValue := c.getValue(frame, instr.X)
 | 
			
		||||
	ch := frame.getValue(instr.Chan)
 | 
			
		||||
	chanValue := frame.getValue(instr.X)
 | 
			
		||||
 | 
			
		||||
	// store value-to-send
 | 
			
		||||
	valueType := c.getLLVMType(instr.X.Type())
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) {
 | 
			
		|||
// actual channel receive operation during goroutine lowering.
 | 
			
		||||
func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) llvm.Value {
 | 
			
		||||
	valueType := c.getLLVMType(unop.X.Type().(*types.Chan).Elem())
 | 
			
		||||
	ch := c.getValue(frame, unop.X)
 | 
			
		||||
	ch := frame.getValue(unop.X)
 | 
			
		||||
 | 
			
		||||
	// Allocate memory to receive into.
 | 
			
		||||
	valueAlloca, valueAllocaCast, valueAllocaSize := c.createTemporaryAlloca(valueType, "chan.value")
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +70,7 @@ func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) llvm.Value {
 | 
			
		|||
 | 
			
		||||
// emitChanClose closes the given channel.
 | 
			
		||||
func (c *Compiler) emitChanClose(frame *Frame, param ssa.Value) {
 | 
			
		||||
	ch := c.getValue(frame, param)
 | 
			
		||||
	ch := frame.getValue(param)
 | 
			
		||||
	c.createRuntimeCall("chanClose", []llvm.Value{ch}, "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +111,7 @@ func (c *Compiler) emitSelect(frame *Frame, expr *ssa.Select) llvm.Value {
 | 
			
		|||
	var selectStates []llvm.Value
 | 
			
		||||
	chanSelectStateType := c.getLLVMRuntimeType("chanSelectState")
 | 
			
		||||
	for _, state := range expr.States {
 | 
			
		||||
		ch := c.getValue(frame, state.Chan)
 | 
			
		||||
		ch := frame.getValue(state.Chan)
 | 
			
		||||
		selectState := llvm.ConstNull(chanSelectStateType)
 | 
			
		||||
		selectState = c.builder.CreateInsertValue(selectState, ch, 0, "")
 | 
			
		||||
		switch state.Dir {
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +128,7 @@ func (c *Compiler) emitSelect(frame *Frame, expr *ssa.Select) llvm.Value {
 | 
			
		|||
		case types.SendOnly:
 | 
			
		||||
			// Store this value in an alloca and put a pointer to this alloca
 | 
			
		||||
			// in the send state.
 | 
			
		||||
			sendValue := c.getValue(frame, state.Send)
 | 
			
		||||
			sendValue := frame.getValue(state.Send)
 | 
			
		||||
			alloca := llvmutil.CreateEntryBlockAlloca(c.builder, sendValue.Type(), "select.send.value")
 | 
			
		||||
			c.builder.CreateStore(sendValue, alloca)
 | 
			
		||||
			ptr := c.builder.CreateBitCast(alloca, c.i8ptrType, "")
 | 
			
		||||
| 
						 | 
				
			
			@ -219,7 +219,7 @@ func (c *Compiler) emitSelect(frame *Frame, expr *ssa.Select) llvm.Value {
 | 
			
		|||
func (c *Compiler) getChanSelectResult(frame *Frame, expr *ssa.Extract) llvm.Value {
 | 
			
		||||
	if expr.Index == 0 {
 | 
			
		||||
		// index
 | 
			
		||||
		value := c.getValue(frame, expr.Tuple)
 | 
			
		||||
		value := frame.getValue(expr.Tuple)
 | 
			
		||||
		index := c.builder.CreateExtractValue(value, expr.Index, "")
 | 
			
		||||
		if index.Type().IntTypeWidth() < c.intType.IntTypeWidth() {
 | 
			
		||||
			index = c.builder.CreateSExt(index, c.intType, "")
 | 
			
		||||
| 
						 | 
				
			
			@ -227,7 +227,7 @@ func (c *Compiler) getChanSelectResult(frame *Frame, expr *ssa.Extract) llvm.Val
 | 
			
		|||
		return index
 | 
			
		||||
	} else if expr.Index == 1 {
 | 
			
		||||
		// comma-ok
 | 
			
		||||
		value := c.getValue(frame, expr.Tuple)
 | 
			
		||||
		value := frame.getValue(expr.Tuple)
 | 
			
		||||
		return c.builder.CreateExtractValue(value, expr.Index, "")
 | 
			
		||||
	} else {
 | 
			
		||||
		// Select statements are (index, ok, ...) where ... is a number of
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,6 +53,7 @@ type compilerContext struct {
 | 
			
		|||
	uintptrType      llvm.Type
 | 
			
		||||
	ir               *ir.Program
 | 
			
		||||
	diagnostics      []error
 | 
			
		||||
	astComments      map[string]*ast.CommentGroup
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Compiler struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +61,6 @@ type Compiler struct {
 | 
			
		|||
	builder                 llvm.Builder
 | 
			
		||||
	initFuncs               []llvm.Value
 | 
			
		||||
	interfaceInvokeWrappers []interfaceInvokeWrapper
 | 
			
		||||
	astComments             map[string]*ast.CommentGroup
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Frame struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -513,7 +513,7 @@ func isPointer(typ types.Type) bool {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Get the DWARF type for this Go type.
 | 
			
		||||
func (c *Compiler) getDIType(typ types.Type) llvm.Metadata {
 | 
			
		||||
func (c *compilerContext) getDIType(typ types.Type) llvm.Metadata {
 | 
			
		||||
	if md, ok := c.ditypes[typ]; ok {
 | 
			
		||||
		return md
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -524,7 +524,7 @@ func (c *Compiler) getDIType(typ types.Type) llvm.Metadata {
 | 
			
		|||
 | 
			
		||||
// createDIType creates a new DWARF type. Don't call this function directly,
 | 
			
		||||
// call getDIType instead.
 | 
			
		||||
func (c *Compiler) createDIType(typ types.Type) llvm.Metadata {
 | 
			
		||||
func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
 | 
			
		||||
	llvmType := c.getLLVMType(typ)
 | 
			
		||||
	sizeInBytes := c.targetData.TypeAllocSize(llvmType)
 | 
			
		||||
	switch typ := typ.(type) {
 | 
			
		||||
| 
						 | 
				
			
			@ -836,7 +836,7 @@ func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix,
 | 
			
		|||
// getDIFile returns a DIFile metadata node for the given filename. It tries to
 | 
			
		||||
// use one that was already created, otherwise it falls back to creating a new
 | 
			
		||||
// one.
 | 
			
		||||
func (c *Compiler) getDIFile(filename string) llvm.Metadata {
 | 
			
		||||
func (c *compilerContext) getDIFile(filename string) llvm.Metadata {
 | 
			
		||||
	if _, ok := c.difiles[filename]; !ok {
 | 
			
		||||
		dir, file := filepath.Split(filename)
 | 
			
		||||
		if dir != "" {
 | 
			
		||||
| 
						 | 
				
			
			@ -988,7 +988,7 @@ func (c *Compiler) parseFunc(frame *Frame) {
 | 
			
		|||
				}
 | 
			
		||||
				dbgVar := c.getLocalVariable(frame, variable)
 | 
			
		||||
				pos := c.ir.Program.Fset.Position(instr.Pos())
 | 
			
		||||
				c.dibuilder.InsertValueAtEnd(c.getValue(frame, instr.X), dbgVar, c.dibuilder.CreateExpression(nil), llvm.DebugLoc{
 | 
			
		||||
				c.dibuilder.InsertValueAtEnd(frame.getValue(instr.X), dbgVar, c.dibuilder.CreateExpression(nil), llvm.DebugLoc{
 | 
			
		||||
					Line:  uint(pos.Line),
 | 
			
		||||
					Col:   uint(pos.Column),
 | 
			
		||||
					Scope: frame.difunc,
 | 
			
		||||
| 
						 | 
				
			
			@ -1013,7 +1013,7 @@ func (c *Compiler) parseFunc(frame *Frame) {
 | 
			
		|||
	for _, phi := range frame.phis {
 | 
			
		||||
		block := phi.ssa.Block()
 | 
			
		||||
		for i, edge := range phi.ssa.Edges {
 | 
			
		||||
			llvmVal := c.getValue(frame, edge)
 | 
			
		||||
			llvmVal := frame.getValue(edge)
 | 
			
		||||
			llvmBlock := frame.blockExits[block.Preds[i]]
 | 
			
		||||
			phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock})
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1051,7 +1051,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
 | 
			
		|||
		// Get all function parameters to pass to the goroutine.
 | 
			
		||||
		var params []llvm.Value
 | 
			
		||||
		for _, param := range instr.Call.Args {
 | 
			
		||||
			params = append(params, c.getValue(frame, param))
 | 
			
		||||
			params = append(params, frame.getValue(param))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Start a new goroutine.
 | 
			
		||||
| 
						 | 
				
			
			@ -1067,7 +1067,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
 | 
			
		|||
			case *ssa.MakeClosure:
 | 
			
		||||
				// A goroutine call on a func value, but the callee is trivial to find. For
 | 
			
		||||
				// example: immediately applied functions.
 | 
			
		||||
				funcValue := c.getValue(frame, value)
 | 
			
		||||
				funcValue := frame.getValue(value)
 | 
			
		||||
				context = c.extractFuncContext(funcValue)
 | 
			
		||||
			default:
 | 
			
		||||
				panic("StaticCallee returned an unexpected value")
 | 
			
		||||
| 
						 | 
				
			
			@ -1080,7 +1080,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
 | 
			
		|||
			// goroutine:
 | 
			
		||||
			//   * The function context, for closures.
 | 
			
		||||
			//   * The function pointer (for tasks).
 | 
			
		||||
			funcPtr, context := c.decodeFuncValue(c.getValue(frame, instr.Call.Value), instr.Call.Value.Type().(*types.Signature))
 | 
			
		||||
			funcPtr, context := c.decodeFuncValue(frame.getValue(instr.Call.Value), instr.Call.Value.Type().(*types.Signature))
 | 
			
		||||
			params = append(params, context) // context parameter
 | 
			
		||||
			switch c.Scheduler() {
 | 
			
		||||
			case "none", "coroutines":
 | 
			
		||||
| 
						 | 
				
			
			@ -1096,7 +1096,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
 | 
			
		|||
			c.addError(instr.Pos(), "todo: go on interface call")
 | 
			
		||||
		}
 | 
			
		||||
	case *ssa.If:
 | 
			
		||||
		cond := c.getValue(frame, instr.Cond)
 | 
			
		||||
		cond := frame.getValue(instr.Cond)
 | 
			
		||||
		block := instr.Block()
 | 
			
		||||
		blockThen := frame.blockEntries[block.Succs[0]]
 | 
			
		||||
		blockElse := frame.blockEntries[block.Succs[1]]
 | 
			
		||||
| 
						 | 
				
			
			@ -1105,25 +1105,25 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
 | 
			
		|||
		blockJump := frame.blockEntries[instr.Block().Succs[0]]
 | 
			
		||||
		c.builder.CreateBr(blockJump)
 | 
			
		||||
	case *ssa.MapUpdate:
 | 
			
		||||
		m := c.getValue(frame, instr.Map)
 | 
			
		||||
		key := c.getValue(frame, instr.Key)
 | 
			
		||||
		value := c.getValue(frame, instr.Value)
 | 
			
		||||
		m := frame.getValue(instr.Map)
 | 
			
		||||
		key := frame.getValue(instr.Key)
 | 
			
		||||
		value := frame.getValue(instr.Value)
 | 
			
		||||
		mapType := instr.Map.Type().Underlying().(*types.Map)
 | 
			
		||||
		c.emitMapUpdate(mapType.Key(), m, key, value, instr.Pos())
 | 
			
		||||
	case *ssa.Panic:
 | 
			
		||||
		value := c.getValue(frame, instr.X)
 | 
			
		||||
		value := frame.getValue(instr.X)
 | 
			
		||||
		c.createRuntimeCall("_panic", []llvm.Value{value}, "")
 | 
			
		||||
		c.builder.CreateUnreachable()
 | 
			
		||||
	case *ssa.Return:
 | 
			
		||||
		if len(instr.Results) == 0 {
 | 
			
		||||
			c.builder.CreateRetVoid()
 | 
			
		||||
		} else if len(instr.Results) == 1 {
 | 
			
		||||
			c.builder.CreateRet(c.getValue(frame, instr.Results[0]))
 | 
			
		||||
			c.builder.CreateRet(frame.getValue(instr.Results[0]))
 | 
			
		||||
		} else {
 | 
			
		||||
			// Multiple return values. Put them all in a struct.
 | 
			
		||||
			retVal := llvm.ConstNull(frame.fn.LLVMFn.Type().ElementType().ReturnType())
 | 
			
		||||
			for i, result := range instr.Results {
 | 
			
		||||
				val := c.getValue(frame, result)
 | 
			
		||||
				val := frame.getValue(result)
 | 
			
		||||
				retVal = c.builder.CreateInsertValue(retVal, val, i, "")
 | 
			
		||||
			}
 | 
			
		||||
			c.builder.CreateRet(retVal)
 | 
			
		||||
| 
						 | 
				
			
			@ -1133,8 +1133,8 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
 | 
			
		|||
	case *ssa.Send:
 | 
			
		||||
		c.emitChanSend(frame, instr)
 | 
			
		||||
	case *ssa.Store:
 | 
			
		||||
		llvmAddr := c.getValue(frame, instr.Addr)
 | 
			
		||||
		llvmVal := c.getValue(frame, instr.Val)
 | 
			
		||||
		llvmAddr := frame.getValue(instr.Addr)
 | 
			
		||||
		llvmVal := frame.getValue(instr.Val)
 | 
			
		||||
		c.emitNilCheck(frame, llvmAddr, "store")
 | 
			
		||||
		if c.targetData.TypeAllocSize(llvmVal.Type()) == 0 {
 | 
			
		||||
			// nothing to store
 | 
			
		||||
| 
						 | 
				
			
			@ -1149,8 +1149,8 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
 | 
			
		|||
func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string, pos token.Pos) (llvm.Value, error) {
 | 
			
		||||
	switch callName {
 | 
			
		||||
	case "append":
 | 
			
		||||
		src := c.getValue(frame, args[0])
 | 
			
		||||
		elems := c.getValue(frame, args[1])
 | 
			
		||||
		src := frame.getValue(args[0])
 | 
			
		||||
		elems := frame.getValue(args[1])
 | 
			
		||||
		srcBuf := c.builder.CreateExtractValue(src, 0, "append.srcBuf")
 | 
			
		||||
		srcPtr := c.builder.CreateBitCast(srcBuf, c.i8ptrType, "append.srcPtr")
 | 
			
		||||
		srcLen := c.builder.CreateExtractValue(src, 1, "append.srcLen")
 | 
			
		||||
| 
						 | 
				
			
			@ -1171,7 +1171,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
 | 
			
		|||
		newSlice = c.builder.CreateInsertValue(newSlice, newCap, 2, "")
 | 
			
		||||
		return newSlice, nil
 | 
			
		||||
	case "cap":
 | 
			
		||||
		value := c.getValue(frame, args[0])
 | 
			
		||||
		value := frame.getValue(args[0])
 | 
			
		||||
		var llvmCap llvm.Value
 | 
			
		||||
		switch args[0].Type().(type) {
 | 
			
		||||
		case *types.Chan:
 | 
			
		||||
| 
						 | 
				
			
			@ -1191,8 +1191,8 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
 | 
			
		|||
		c.emitChanClose(frame, args[0])
 | 
			
		||||
		return llvm.Value{}, nil
 | 
			
		||||
	case "complex":
 | 
			
		||||
		r := c.getValue(frame, args[0])
 | 
			
		||||
		i := c.getValue(frame, args[1])
 | 
			
		||||
		r := frame.getValue(args[0])
 | 
			
		||||
		i := frame.getValue(args[1])
 | 
			
		||||
		t := args[0].Type().Underlying().(*types.Basic)
 | 
			
		||||
		var cplx llvm.Value
 | 
			
		||||
		switch t.Kind() {
 | 
			
		||||
| 
						 | 
				
			
			@ -1207,8 +1207,8 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
 | 
			
		|||
		cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
 | 
			
		||||
		return cplx, nil
 | 
			
		||||
	case "copy":
 | 
			
		||||
		dst := c.getValue(frame, args[0])
 | 
			
		||||
		src := c.getValue(frame, args[1])
 | 
			
		||||
		dst := frame.getValue(args[0])
 | 
			
		||||
		src := frame.getValue(args[1])
 | 
			
		||||
		dstLen := c.builder.CreateExtractValue(dst, 1, "copy.dstLen")
 | 
			
		||||
		srcLen := c.builder.CreateExtractValue(src, 1, "copy.srcLen")
 | 
			
		||||
		dstBuf := c.builder.CreateExtractValue(dst, 0, "copy.dstArray")
 | 
			
		||||
| 
						 | 
				
			
			@ -1219,14 +1219,14 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
 | 
			
		|||
		elemSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(elemType), false)
 | 
			
		||||
		return c.createRuntimeCall("sliceCopy", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil
 | 
			
		||||
	case "delete":
 | 
			
		||||
		m := c.getValue(frame, args[0])
 | 
			
		||||
		key := c.getValue(frame, args[1])
 | 
			
		||||
		m := frame.getValue(args[0])
 | 
			
		||||
		key := frame.getValue(args[1])
 | 
			
		||||
		return llvm.Value{}, c.emitMapDelete(args[1].Type(), m, key, pos)
 | 
			
		||||
	case "imag":
 | 
			
		||||
		cplx := c.getValue(frame, args[0])
 | 
			
		||||
		cplx := frame.getValue(args[0])
 | 
			
		||||
		return c.builder.CreateExtractValue(cplx, 1, "imag"), nil
 | 
			
		||||
	case "len":
 | 
			
		||||
		value := c.getValue(frame, args[0])
 | 
			
		||||
		value := frame.getValue(args[0])
 | 
			
		||||
		var llvmLen llvm.Value
 | 
			
		||||
		switch args[0].Type().Underlying().(type) {
 | 
			
		||||
		case *types.Basic, *types.Slice:
 | 
			
		||||
| 
						 | 
				
			
			@ -1250,7 +1250,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
 | 
			
		|||
			if i >= 1 && callName == "println" {
 | 
			
		||||
				c.createRuntimeCall("printspace", nil, "")
 | 
			
		||||
			}
 | 
			
		||||
			value := c.getValue(frame, arg)
 | 
			
		||||
			value := frame.getValue(arg)
 | 
			
		||||
			typ := arg.Type().Underlying()
 | 
			
		||||
			switch typ := typ.(type) {
 | 
			
		||||
			case *types.Basic:
 | 
			
		||||
| 
						 | 
				
			
			@ -1303,13 +1303,13 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
 | 
			
		|||
		}
 | 
			
		||||
		return llvm.Value{}, nil // print() or println() returns void
 | 
			
		||||
	case "real":
 | 
			
		||||
		cplx := c.getValue(frame, args[0])
 | 
			
		||||
		cplx := frame.getValue(args[0])
 | 
			
		||||
		return c.builder.CreateExtractValue(cplx, 0, "real"), nil
 | 
			
		||||
	case "recover":
 | 
			
		||||
		return c.createRuntimeCall("_recover", nil, ""), nil
 | 
			
		||||
	case "ssa:wrapnilchk":
 | 
			
		||||
		// TODO: do an actual nil check?
 | 
			
		||||
		return c.getValue(frame, args[0]), nil
 | 
			
		||||
		return frame.getValue(args[0]), nil
 | 
			
		||||
	default:
 | 
			
		||||
		return llvm.Value{}, c.makeError(pos, "todo: builtin: "+callName)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1318,7 +1318,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
 | 
			
		|||
func (c *Compiler) parseFunctionCall(frame *Frame, args []ssa.Value, llvmFn, context llvm.Value, exported bool) llvm.Value {
 | 
			
		||||
	var params []llvm.Value
 | 
			
		||||
	for _, param := range args {
 | 
			
		||||
		params = append(params, c.getValue(frame, param))
 | 
			
		||||
		params = append(params, frame.getValue(param))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !exported {
 | 
			
		||||
| 
						 | 
				
			
			@ -1375,7 +1375,7 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
 | 
			
		|||
		case *ssa.MakeClosure:
 | 
			
		||||
			// A call on a func value, but the callee is trivial to find. For
 | 
			
		||||
			// example: immediately applied functions.
 | 
			
		||||
			funcValue := c.getValue(frame, value)
 | 
			
		||||
			funcValue := frame.getValue(value)
 | 
			
		||||
			context = c.extractFuncContext(funcValue)
 | 
			
		||||
		default:
 | 
			
		||||
			panic("StaticCallee returned an unexpected value")
 | 
			
		||||
| 
						 | 
				
			
			@ -1388,7 +1388,7 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
 | 
			
		|||
	case *ssa.Builtin:
 | 
			
		||||
		return c.parseBuiltin(frame, instr.Args, call.Name(), instr.Pos())
 | 
			
		||||
	default: // function pointer
 | 
			
		||||
		value := c.getValue(frame, instr.Value)
 | 
			
		||||
		value := frame.getValue(instr.Value)
 | 
			
		||||
		// This is a func value, which cannot be called directly. We have to
 | 
			
		||||
		// extract the function pointer and context first from the func value.
 | 
			
		||||
		funcPtr, context := c.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature))
 | 
			
		||||
| 
						 | 
				
			
			@ -1399,27 +1399,27 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
 | 
			
		|||
 | 
			
		||||
// getValue returns the LLVM value of a constant, function value, global, or
 | 
			
		||||
// already processed SSA expression.
 | 
			
		||||
func (c *Compiler) getValue(frame *Frame, expr ssa.Value) llvm.Value {
 | 
			
		||||
func (b *builder) getValue(expr ssa.Value) llvm.Value {
 | 
			
		||||
	switch expr := expr.(type) {
 | 
			
		||||
	case *ssa.Const:
 | 
			
		||||
		return frame.createConst(frame.fn.LinkName(), expr)
 | 
			
		||||
		return b.createConst(b.fn.LinkName(), expr)
 | 
			
		||||
	case *ssa.Function:
 | 
			
		||||
		fn := c.ir.GetFunction(expr)
 | 
			
		||||
		fn := b.ir.GetFunction(expr)
 | 
			
		||||
		if fn.IsExported() {
 | 
			
		||||
			c.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String())
 | 
			
		||||
			return llvm.Undef(c.getLLVMType(expr.Type()))
 | 
			
		||||
			b.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String())
 | 
			
		||||
			return llvm.Undef(b.getLLVMType(expr.Type()))
 | 
			
		||||
		}
 | 
			
		||||
		return c.createFuncValue(fn.LLVMFn, llvm.Undef(c.i8ptrType), fn.Signature)
 | 
			
		||||
		return b.createFuncValue(fn.LLVMFn, llvm.Undef(b.i8ptrType), fn.Signature)
 | 
			
		||||
	case *ssa.Global:
 | 
			
		||||
		value := c.getGlobal(expr)
 | 
			
		||||
		value := b.getGlobal(expr)
 | 
			
		||||
		if value.IsNil() {
 | 
			
		||||
			c.addError(expr.Pos(), "global not found: "+expr.RelString(nil))
 | 
			
		||||
			return llvm.Undef(c.getLLVMType(expr.Type()))
 | 
			
		||||
			b.addError(expr.Pos(), "global not found: "+expr.RelString(nil))
 | 
			
		||||
			return llvm.Undef(b.getLLVMType(expr.Type()))
 | 
			
		||||
		}
 | 
			
		||||
		return value
 | 
			
		||||
	default:
 | 
			
		||||
		// other (local) SSA value
 | 
			
		||||
		if value, ok := frame.locals[expr]; ok {
 | 
			
		||||
		if value, ok := b.locals[expr]; ok {
 | 
			
		||||
			return value
 | 
			
		||||
		} else {
 | 
			
		||||
			// indicates a compiler bug
 | 
			
		||||
| 
						 | 
				
			
			@ -1458,8 +1458,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
			return buf, nil
 | 
			
		||||
		}
 | 
			
		||||
	case *ssa.BinOp:
 | 
			
		||||
		x := c.getValue(frame, expr.X)
 | 
			
		||||
		y := c.getValue(frame, expr.Y)
 | 
			
		||||
		x := frame.getValue(expr.X)
 | 
			
		||||
		y := frame.getValue(expr.Y)
 | 
			
		||||
		return frame.createBinOp(expr.Op, expr.X.Type(), x, y, expr.Pos())
 | 
			
		||||
	case *ssa.Call:
 | 
			
		||||
		// Passing the current task here to the subroutine. It is only used when
 | 
			
		||||
| 
						 | 
				
			
			@ -1472,12 +1472,12 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
		// This is different from how the official Go compiler works, because of
 | 
			
		||||
		// heap allocation and because it's easier to implement, see:
 | 
			
		||||
		// https://research.swtch.com/interfaces
 | 
			
		||||
		return c.getValue(frame, expr.X), nil
 | 
			
		||||
		return frame.getValue(expr.X), nil
 | 
			
		||||
	case *ssa.ChangeType:
 | 
			
		||||
		// This instruction changes the type, but the underlying value remains
 | 
			
		||||
		// the same. This is often a no-op, but sometimes we have to change the
 | 
			
		||||
		// LLVM type as well.
 | 
			
		||||
		x := c.getValue(frame, expr.X)
 | 
			
		||||
		x := frame.getValue(expr.X)
 | 
			
		||||
		llvmType := c.getLLVMType(expr.Type())
 | 
			
		||||
		if x.Type() == llvmType {
 | 
			
		||||
			// Different Go type but same LLVM type (for example, named int).
 | 
			
		||||
| 
						 | 
				
			
			@ -1506,20 +1506,20 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
	case *ssa.Const:
 | 
			
		||||
		panic("const is not an expression")
 | 
			
		||||
	case *ssa.Convert:
 | 
			
		||||
		x := c.getValue(frame, expr.X)
 | 
			
		||||
		x := frame.getValue(expr.X)
 | 
			
		||||
		return c.parseConvert(expr.X.Type(), expr.Type(), x, expr.Pos())
 | 
			
		||||
	case *ssa.Extract:
 | 
			
		||||
		if _, ok := expr.Tuple.(*ssa.Select); ok {
 | 
			
		||||
			return c.getChanSelectResult(frame, expr), nil
 | 
			
		||||
		}
 | 
			
		||||
		value := c.getValue(frame, expr.Tuple)
 | 
			
		||||
		value := frame.getValue(expr.Tuple)
 | 
			
		||||
		return c.builder.CreateExtractValue(value, expr.Index, ""), nil
 | 
			
		||||
	case *ssa.Field:
 | 
			
		||||
		value := c.getValue(frame, expr.X)
 | 
			
		||||
		value := frame.getValue(expr.X)
 | 
			
		||||
		result := c.builder.CreateExtractValue(value, expr.Field, "")
 | 
			
		||||
		return result, nil
 | 
			
		||||
	case *ssa.FieldAddr:
 | 
			
		||||
		val := c.getValue(frame, expr.X)
 | 
			
		||||
		val := frame.getValue(expr.X)
 | 
			
		||||
		// Check for nil pointer before calculating the address, from the spec:
 | 
			
		||||
		// > For an operand x of type T, the address operation &x generates a
 | 
			
		||||
		// > pointer of type *T to x. [...] If the evaluation of x would cause a
 | 
			
		||||
| 
						 | 
				
			
			@ -1536,8 +1536,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
	case *ssa.Global:
 | 
			
		||||
		panic("global is not an expression")
 | 
			
		||||
	case *ssa.Index:
 | 
			
		||||
		array := c.getValue(frame, expr.X)
 | 
			
		||||
		index := c.getValue(frame, expr.Index)
 | 
			
		||||
		array := frame.getValue(expr.X)
 | 
			
		||||
		index := frame.getValue(expr.Index)
 | 
			
		||||
 | 
			
		||||
		// Check bounds.
 | 
			
		||||
		arrayLen := expr.X.Type().(*types.Array).Len()
 | 
			
		||||
| 
						 | 
				
			
			@ -1554,8 +1554,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
		c.emitLifetimeEnd(allocaPtr, allocaSize)
 | 
			
		||||
		return result, nil
 | 
			
		||||
	case *ssa.IndexAddr:
 | 
			
		||||
		val := c.getValue(frame, expr.X)
 | 
			
		||||
		index := c.getValue(frame, expr.Index)
 | 
			
		||||
		val := frame.getValue(expr.X)
 | 
			
		||||
		index := frame.getValue(expr.Index)
 | 
			
		||||
 | 
			
		||||
		// Get buffer pointer and length
 | 
			
		||||
		var bufptr, buflen llvm.Value
 | 
			
		||||
| 
						 | 
				
			
			@ -1599,8 +1599,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
			panic("unreachable")
 | 
			
		||||
		}
 | 
			
		||||
	case *ssa.Lookup:
 | 
			
		||||
		value := c.getValue(frame, expr.X)
 | 
			
		||||
		index := c.getValue(frame, expr.Index)
 | 
			
		||||
		value := frame.getValue(expr.X)
 | 
			
		||||
		index := frame.getValue(expr.Index)
 | 
			
		||||
		switch xType := expr.X.Type().Underlying().(type) {
 | 
			
		||||
		case *types.Basic:
 | 
			
		||||
			// Value type must be a string, which is a basic type.
 | 
			
		||||
| 
						 | 
				
			
			@ -1630,13 +1630,13 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
	case *ssa.MakeClosure:
 | 
			
		||||
		return c.parseMakeClosure(frame, expr)
 | 
			
		||||
	case *ssa.MakeInterface:
 | 
			
		||||
		val := c.getValue(frame, expr.X)
 | 
			
		||||
		val := frame.getValue(expr.X)
 | 
			
		||||
		return c.parseMakeInterface(val, expr.X.Type(), expr.Pos()), nil
 | 
			
		||||
	case *ssa.MakeMap:
 | 
			
		||||
		return c.emitMakeMap(frame, expr)
 | 
			
		||||
	case *ssa.MakeSlice:
 | 
			
		||||
		sliceLen := c.getValue(frame, expr.Len)
 | 
			
		||||
		sliceCap := c.getValue(frame, expr.Cap)
 | 
			
		||||
		sliceLen := frame.getValue(expr.Len)
 | 
			
		||||
		sliceCap := frame.getValue(expr.Cap)
 | 
			
		||||
		sliceType := expr.Type().Underlying().(*types.Slice)
 | 
			
		||||
		llvmElemType := c.getLLVMType(sliceType.Elem())
 | 
			
		||||
		elemSize := c.targetData.TypeAllocSize(llvmElemType)
 | 
			
		||||
| 
						 | 
				
			
			@ -1688,8 +1688,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
		return slice, nil
 | 
			
		||||
	case *ssa.Next:
 | 
			
		||||
		rangeVal := expr.Iter.(*ssa.Range).X
 | 
			
		||||
		llvmRangeVal := c.getValue(frame, rangeVal)
 | 
			
		||||
		it := c.getValue(frame, expr.Iter)
 | 
			
		||||
		llvmRangeVal := frame.getValue(rangeVal)
 | 
			
		||||
		it := frame.getValue(expr.Iter)
 | 
			
		||||
		if expr.IsString {
 | 
			
		||||
			return c.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil
 | 
			
		||||
		} else { // map
 | 
			
		||||
| 
						 | 
				
			
			@ -1728,14 +1728,14 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
	case *ssa.Select:
 | 
			
		||||
		return c.emitSelect(frame, expr), nil
 | 
			
		||||
	case *ssa.Slice:
 | 
			
		||||
		value := c.getValue(frame, expr.X)
 | 
			
		||||
		value := frame.getValue(expr.X)
 | 
			
		||||
 | 
			
		||||
		var lowType, highType, maxType *types.Basic
 | 
			
		||||
		var low, high, max llvm.Value
 | 
			
		||||
 | 
			
		||||
		if expr.Low != nil {
 | 
			
		||||
			lowType = expr.Low.Type().Underlying().(*types.Basic)
 | 
			
		||||
			low = c.getValue(frame, expr.Low)
 | 
			
		||||
			low = frame.getValue(expr.Low)
 | 
			
		||||
			if low.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
 | 
			
		||||
				if lowType.Info()&types.IsUnsigned != 0 {
 | 
			
		||||
					low = c.builder.CreateZExt(low, c.uintptrType, "")
 | 
			
		||||
| 
						 | 
				
			
			@ -1750,7 +1750,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
 | 
			
		||||
		if expr.High != nil {
 | 
			
		||||
			highType = expr.High.Type().Underlying().(*types.Basic)
 | 
			
		||||
			high = c.getValue(frame, expr.High)
 | 
			
		||||
			high = frame.getValue(expr.High)
 | 
			
		||||
			if high.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
 | 
			
		||||
				if highType.Info()&types.IsUnsigned != 0 {
 | 
			
		||||
					high = c.builder.CreateZExt(high, c.uintptrType, "")
 | 
			
		||||
| 
						 | 
				
			
			@ -1764,7 +1764,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
 | 
			
		|||
 | 
			
		||||
		if expr.Max != nil {
 | 
			
		||||
			maxType = expr.Max.Type().Underlying().(*types.Basic)
 | 
			
		||||
			max = c.getValue(frame, expr.Max)
 | 
			
		||||
			max = frame.getValue(expr.Max)
 | 
			
		||||
			if max.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() {
 | 
			
		||||
				if maxType.Info()&types.IsUnsigned != 0 {
 | 
			
		||||
					max = c.builder.CreateZExt(max, c.uintptrType, "")
 | 
			
		||||
| 
						 | 
				
			
			@ -2524,7 +2524,7 @@ func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, p
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) {
 | 
			
		||||
	x := c.getValue(frame, unop.X)
 | 
			
		||||
	x := frame.getValue(unop.X)
 | 
			
		||||
	switch unop.Op {
 | 
			
		||||
	case token.NOT: // !x
 | 
			
		||||
		return c.builder.CreateNot(x, ""), nil
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,12 +91,12 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) {
 | 
			
		|||
 | 
			
		||||
		// Collect all values to be put in the struct (starting with
 | 
			
		||||
		// runtime._defer fields, followed by the call parameters).
 | 
			
		||||
		itf := c.getValue(frame, instr.Call.Value) // interface
 | 
			
		||||
		itf := frame.getValue(instr.Call.Value) // interface
 | 
			
		||||
		receiverValue := c.builder.CreateExtractValue(itf, 1, "invoke.func.receiver")
 | 
			
		||||
		values = []llvm.Value{callback, next, receiverValue}
 | 
			
		||||
		valueTypes = append(valueTypes, c.i8ptrType)
 | 
			
		||||
		for _, arg := range instr.Call.Args {
 | 
			
		||||
			val := c.getValue(frame, arg)
 | 
			
		||||
			val := frame.getValue(arg)
 | 
			
		||||
			values = append(values, val)
 | 
			
		||||
			valueTypes = append(valueTypes, val.Type())
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +115,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) {
 | 
			
		|||
		// runtime._defer fields).
 | 
			
		||||
		values = []llvm.Value{callback, next}
 | 
			
		||||
		for _, param := range instr.Call.Args {
 | 
			
		||||
			llvmParam := c.getValue(frame, param)
 | 
			
		||||
			llvmParam := frame.getValue(param)
 | 
			
		||||
			values = append(values, llvmParam)
 | 
			
		||||
			valueTypes = append(valueTypes, llvmParam.Type())
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +127,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) {
 | 
			
		|||
		// pointer.
 | 
			
		||||
		// TODO: ignore this closure entirely and put pointers to the free
 | 
			
		||||
		// variables directly in the defer struct, avoiding a memory allocation.
 | 
			
		||||
		closure := c.getValue(frame, instr.Call.Value)
 | 
			
		||||
		closure := frame.getValue(instr.Call.Value)
 | 
			
		||||
		context := c.builder.CreateExtractValue(closure, 0, "")
 | 
			
		||||
 | 
			
		||||
		// Get the callback number.
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +143,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) {
 | 
			
		|||
		// context pointer).
 | 
			
		||||
		values = []llvm.Value{callback, next}
 | 
			
		||||
		for _, param := range instr.Call.Args {
 | 
			
		||||
			llvmParam := c.getValue(frame, param)
 | 
			
		||||
			llvmParam := frame.getValue(param)
 | 
			
		||||
			values = append(values, llvmParam)
 | 
			
		||||
			valueTypes = append(valueTypes, llvmParam.Type())
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ func (c *compilerContext) makeError(pos token.Pos, msg string) types.Error {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) addError(pos token.Pos, msg string) {
 | 
			
		||||
func (c *compilerContext) addError(pos token.Pos, msg string) {
 | 
			
		||||
	c.diagnostics = append(c.diagnostics, c.makeError(pos, msg))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,18 @@ import (
 | 
			
		|||
// createFuncValue creates a function value from a raw function pointer with no
 | 
			
		||||
// context.
 | 
			
		||||
func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {
 | 
			
		||||
	return c.compilerContext.createFuncValue(c.builder, funcPtr, context, sig)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// createFuncValue creates a function value from a raw function pointer with no
 | 
			
		||||
// context.
 | 
			
		||||
func (b *builder) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {
 | 
			
		||||
	return b.compilerContext.createFuncValue(b.Builder, funcPtr, context, sig)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// createFuncValue creates a function value from a raw function pointer with no
 | 
			
		||||
// context.
 | 
			
		||||
func (c *compilerContext) createFuncValue(builder llvm.Builder, funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {
 | 
			
		||||
	var funcValueScalar llvm.Value
 | 
			
		||||
	switch c.FuncImplementation() {
 | 
			
		||||
	case compileopts.FuncValueDoubleword:
 | 
			
		||||
| 
						 | 
				
			
			@ -40,8 +52,8 @@ func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signa
 | 
			
		|||
	}
 | 
			
		||||
	funcValueType := c.getFuncType(sig)
 | 
			
		||||
	funcValue := llvm.Undef(funcValueType)
 | 
			
		||||
	funcValue = c.builder.CreateInsertValue(funcValue, context, 0, "")
 | 
			
		||||
	funcValue = c.builder.CreateInsertValue(funcValue, funcValueScalar, 1, "")
 | 
			
		||||
	funcValue = builder.CreateInsertValue(funcValue, context, 0, "")
 | 
			
		||||
	funcValue = builder.CreateInsertValue(funcValue, funcValueScalar, 1, "")
 | 
			
		||||
	return funcValue
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -151,7 +163,7 @@ func (c *Compiler) parseMakeClosure(frame *Frame, expr *ssa.MakeClosure) (llvm.V
 | 
			
		|||
	boundVars := make([]llvm.Value, len(expr.Bindings))
 | 
			
		||||
	for i, binding := range expr.Bindings {
 | 
			
		||||
		// The context stores the bound variables.
 | 
			
		||||
		llvmBoundVar := c.getValue(frame, binding)
 | 
			
		||||
		llvmBoundVar := frame.getValue(binding)
 | 
			
		||||
		boundVars[i] = llvmBoundVar
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ func (c *Compiler) emitAsmFull(frame *Frame, instr *ssa.CallCommon) (llvm.Value,
 | 
			
		|||
			}
 | 
			
		||||
			key := constant.StringVal(r.Key.(*ssa.Const).Value)
 | 
			
		||||
			//println("value:", r.Value.(*ssa.MakeInterface).X.String())
 | 
			
		||||
			registers[key] = c.getValue(frame, r.Value.(*ssa.MakeInterface).X)
 | 
			
		||||
			registers[key] = frame.getValue(r.Value.(*ssa.MakeInterface).X)
 | 
			
		||||
		case *ssa.Call:
 | 
			
		||||
			if r.Common() == instr {
 | 
			
		||||
				break
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +150,7 @@ func (c *Compiler) emitSVCall(frame *Frame, args []ssa.Value) (llvm.Value, error
 | 
			
		|||
		} else {
 | 
			
		||||
			constraints += ",{r" + strconv.Itoa(i) + "}"
 | 
			
		||||
		}
 | 
			
		||||
		llvmValue := c.getValue(frame, arg)
 | 
			
		||||
		llvmValue := frame.getValue(arg)
 | 
			
		||||
		llvmArgs = append(llvmArgs, llvmValue)
 | 
			
		||||
		argTypes = append(argTypes, llvmValue.Type())
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -190,19 +190,19 @@ func (c *Compiler) emitCSROperation(frame *Frame, call *ssa.CallCommon) (llvm.Va
 | 
			
		|||
		fnType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.uintptrType}, false)
 | 
			
		||||
		asm := fmt.Sprintf("csrw %d, $0", csr)
 | 
			
		||||
		target := llvm.InlineAsm(fnType, asm, "r", true, false, 0)
 | 
			
		||||
		return c.builder.CreateCall(target, []llvm.Value{c.getValue(frame, call.Args[1])}, ""), nil
 | 
			
		||||
		return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil
 | 
			
		||||
	case "SetBits":
 | 
			
		||||
		// Note: it may be possible to optimize this to csrrsi in many cases.
 | 
			
		||||
		fnType := llvm.FunctionType(c.uintptrType, []llvm.Type{c.uintptrType}, false)
 | 
			
		||||
		asm := fmt.Sprintf("csrrs $0, %d, $1", csr)
 | 
			
		||||
		target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0)
 | 
			
		||||
		return c.builder.CreateCall(target, []llvm.Value{c.getValue(frame, call.Args[1])}, ""), nil
 | 
			
		||||
		return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil
 | 
			
		||||
	case "ClearBits":
 | 
			
		||||
		// Note: it may be possible to optimize this to csrrci in many cases.
 | 
			
		||||
		fnType := llvm.FunctionType(c.uintptrType, []llvm.Type{c.uintptrType}, false)
 | 
			
		||||
		asm := fmt.Sprintf("csrrc $0, %d, $1", csr)
 | 
			
		||||
		target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0)
 | 
			
		||||
		return c.builder.CreateCall(target, []llvm.Value{c.getValue(frame, call.Args[1])}, ""), nil
 | 
			
		||||
		return c.builder.CreateCall(target, []llvm.Value{frame.getValue(call.Args[1])}, ""), nil
 | 
			
		||||
	default:
 | 
			
		||||
		return llvm.Value{}, c.makeError(call.Pos(), "unknown CSR operation: "+name)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,7 @@ func (c *Compiler) parseMakeInterface(val llvm.Value, typ types.Type, pos token.
 | 
			
		|||
// getTypeCode returns a reference to a type code.
 | 
			
		||||
// It returns a pointer to an external global which should be replaced with the
 | 
			
		||||
// real type in the interface lowering pass.
 | 
			
		||||
func (c *Compiler) getTypeCode(typ types.Type) llvm.Value {
 | 
			
		||||
func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
 | 
			
		||||
	globalName := "reflect/types.type:" + getTypeCodeName(typ)
 | 
			
		||||
	global := c.mod.NamedGlobal(globalName)
 | 
			
		||||
	if global.IsNil() {
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +91,7 @@ func (c *Compiler) getTypeCode(typ types.Type) llvm.Value {
 | 
			
		|||
// makeStructTypeFields creates a new global that stores all type information
 | 
			
		||||
// related to this struct type, and returns the resulting global. This global is
 | 
			
		||||
// actually an array of all the fields in the structs.
 | 
			
		||||
func (c *Compiler) makeStructTypeFields(typ *types.Struct) llvm.Value {
 | 
			
		||||
func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value {
 | 
			
		||||
	// The global is an array of runtime.structField structs.
 | 
			
		||||
	runtimeStructField := c.getLLVMRuntimeType("structField")
 | 
			
		||||
	structGlobalType := llvm.ArrayType(runtimeStructField, typ.NumFields())
 | 
			
		||||
| 
						 | 
				
			
			@ -315,7 +315,7 @@ func (c *Compiler) getMethodSignature(method *types.Func) llvm.Value {
 | 
			
		|||
// Type asserts on concrete types are trivial: just compare type numbers. Type
 | 
			
		||||
// asserts on interfaces are more difficult, see the comments in the function.
 | 
			
		||||
func (c *Compiler) parseTypeAssert(frame *Frame, expr *ssa.TypeAssert) llvm.Value {
 | 
			
		||||
	itf := c.getValue(frame, expr.X)
 | 
			
		||||
	itf := frame.getValue(expr.X)
 | 
			
		||||
	assertedType := c.getLLVMType(expr.AssertedType)
 | 
			
		||||
 | 
			
		||||
	actualTypeNum := c.builder.CreateExtractValue(itf, 0, "interface.type")
 | 
			
		||||
| 
						 | 
				
			
			@ -395,7 +395,7 @@ func (c *Compiler) parseTypeAssert(frame *Frame, expr *ssa.TypeAssert) llvm.Valu
 | 
			
		|||
// interface call. It can be used in a call or defer instruction.
 | 
			
		||||
func (c *Compiler) getInvokeCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, []llvm.Value) {
 | 
			
		||||
	// Call an interface method with dynamic dispatch.
 | 
			
		||||
	itf := c.getValue(frame, instr.Value) // interface
 | 
			
		||||
	itf := frame.getValue(instr.Value) // interface
 | 
			
		||||
 | 
			
		||||
	llvmFnType := c.getRawFuncType(instr.Method.Type().(*types.Signature))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -411,7 +411,7 @@ func (c *Compiler) getInvokeCall(frame *Frame, instr *ssa.CallCommon) (llvm.Valu
 | 
			
		|||
 | 
			
		||||
	args := []llvm.Value{receiverValue}
 | 
			
		||||
	for _, arg := range instr.Args {
 | 
			
		||||
		args = append(args, c.getValue(frame, arg))
 | 
			
		||||
		args = append(args, frame.getValue(arg))
 | 
			
		||||
	}
 | 
			
		||||
	// Add the context parameter. An interface call never takes a context but we
 | 
			
		||||
	// have to supply the parameter anyway.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ func (c *Compiler) emitInterruptGlobal(frame *Frame, instr *ssa.CallCommon) (llv
 | 
			
		|||
	// Note that bound functions are allowed if the function has a pointer
 | 
			
		||||
	// receiver and is a global. This is rather strict but still allows for
 | 
			
		||||
	// idiomatic Go code.
 | 
			
		||||
	funcValue := c.getValue(frame, instr.Args[1])
 | 
			
		||||
	funcValue := frame.getValue(instr.Args[1])
 | 
			
		||||
	if funcValue.IsAConstant().IsNil() {
 | 
			
		||||
		// Try to determine the cause of the non-constantness for a nice error
 | 
			
		||||
		// message.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ func (c *Compiler) emitPointerUnpack(ptr llvm.Value, valueTypes []llvm.Type) []l
 | 
			
		|||
// contents, and returns the global.
 | 
			
		||||
// Note that it is left with the default linkage etc., you should set
 | 
			
		||||
// linkage/constant/etc properties yourself.
 | 
			
		||||
func (c *Compiler) makeGlobalArray(buf []byte, name string, elementType llvm.Type) llvm.Value {
 | 
			
		||||
func (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType llvm.Type) llvm.Value {
 | 
			
		||||
	globalType := llvm.ArrayType(elementType, len(buf))
 | 
			
		||||
	global := llvm.AddGlobal(c.mod, globalType, name)
 | 
			
		||||
	value := llvm.Undef(globalType)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ func (c *Compiler) emitMakeMap(frame *Frame, expr *ssa.MakeMap) (llvm.Value, err
 | 
			
		|||
	llvmValueSize := llvm.ConstInt(c.ctx.Int8Type(), valueSize, false)
 | 
			
		||||
	sizeHint := llvm.ConstInt(c.uintptrType, 8, false)
 | 
			
		||||
	if expr.Reserve != nil {
 | 
			
		||||
		sizeHint = c.getValue(frame, expr.Reserve)
 | 
			
		||||
		sizeHint = frame.getValue(expr.Reserve)
 | 
			
		||||
		var err error
 | 
			
		||||
		sizeHint, err = c.parseConvert(expr.Reserve.Type(), types.Typ[types.Uintptr], sizeHint, expr.Pos())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ func (c *Compiler) loadASTComments(lprogram *loader.Program) {
 | 
			
		|||
 | 
			
		||||
// getGlobal returns a LLVM IR global value for a Go SSA global. It is added to
 | 
			
		||||
// the LLVM IR if it has not been added already.
 | 
			
		||||
func (c *Compiler) getGlobal(g *ssa.Global) llvm.Value {
 | 
			
		||||
func (c *compilerContext) getGlobal(g *ssa.Global) llvm.Value {
 | 
			
		||||
	info := c.getGlobalInfo(g)
 | 
			
		||||
	llvmGlobal := c.mod.NamedGlobal(info.linkName)
 | 
			
		||||
	if llvmGlobal.IsNil() {
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +104,7 @@ func (c *Compiler) getGlobal(g *ssa.Global) llvm.Value {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// getGlobalInfo returns some information about a specific global.
 | 
			
		||||
func (c *Compiler) getGlobalInfo(g *ssa.Global) globalInfo {
 | 
			
		||||
func (c *compilerContext) getGlobalInfo(g *ssa.Global) globalInfo {
 | 
			
		||||
	info := globalInfo{}
 | 
			
		||||
	if strings.HasPrefix(g.Name(), "C.") {
 | 
			
		||||
		// Created by CGo: such a name cannot be created by regular C code.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ import (
 | 
			
		|||
// emitSyscall emits an inline system call instruction, depending on the target
 | 
			
		||||
// OS/arch.
 | 
			
		||||
func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value, error) {
 | 
			
		||||
	num := c.getValue(frame, call.Args[0])
 | 
			
		||||
	num := frame.getValue(call.Args[0])
 | 
			
		||||
	var syscallResult llvm.Value
 | 
			
		||||
	switch {
 | 
			
		||||
	case c.GOARCH() == "amd64":
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +50,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
 | 
			
		|||
				"{r12}",
 | 
			
		||||
				"{r13}",
 | 
			
		||||
			}[i]
 | 
			
		||||
			llvmValue := c.getValue(frame, arg)
 | 
			
		||||
			llvmValue := frame.getValue(arg)
 | 
			
		||||
			args = append(args, llvmValue)
 | 
			
		||||
			argTypes = append(argTypes, llvmValue.Type())
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
 | 
			
		|||
				"{edi}",
 | 
			
		||||
				"{ebp}",
 | 
			
		||||
			}[i]
 | 
			
		||||
			llvmValue := c.getValue(frame, arg)
 | 
			
		||||
			llvmValue := frame.getValue(arg)
 | 
			
		||||
			args = append(args, llvmValue)
 | 
			
		||||
			argTypes = append(argTypes, llvmValue.Type())
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +102,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
 | 
			
		|||
				"{r5}",
 | 
			
		||||
				"{r6}",
 | 
			
		||||
			}[i]
 | 
			
		||||
			llvmValue := c.getValue(frame, arg)
 | 
			
		||||
			llvmValue := frame.getValue(arg)
 | 
			
		||||
			args = append(args, llvmValue)
 | 
			
		||||
			argTypes = append(argTypes, llvmValue.Type())
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +132,7 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
 | 
			
		|||
				"{x4}",
 | 
			
		||||
				"{x5}",
 | 
			
		||||
			}[i]
 | 
			
		||||
			llvmValue := c.getValue(frame, arg)
 | 
			
		||||
			llvmValue := frame.getValue(arg)
 | 
			
		||||
			args = append(args, llvmValue)
 | 
			
		||||
			argTypes = append(argTypes, llvmValue.Type())
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) emitVolatileLoad(frame *Frame, instr *ssa.CallCommon) (llvm.Value, error) {
 | 
			
		||||
	addr := c.getValue(frame, instr.Args[0])
 | 
			
		||||
	addr := frame.getValue(instr.Args[0])
 | 
			
		||||
	c.emitNilCheck(frame, addr, "deref")
 | 
			
		||||
	val := c.builder.CreateLoad(addr, "")
 | 
			
		||||
	val.SetVolatile(true)
 | 
			
		||||
| 
						 | 
				
			
			@ -17,8 +17,8 @@ func (c *Compiler) emitVolatileLoad(frame *Frame, instr *ssa.CallCommon) (llvm.V
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) emitVolatileStore(frame *Frame, instr *ssa.CallCommon) (llvm.Value, error) {
 | 
			
		||||
	addr := c.getValue(frame, instr.Args[0])
 | 
			
		||||
	val := c.getValue(frame, instr.Args[1])
 | 
			
		||||
	addr := frame.getValue(instr.Args[0])
 | 
			
		||||
	val := frame.getValue(instr.Args[1])
 | 
			
		||||
	c.emitNilCheck(frame, addr, "deref")
 | 
			
		||||
	store := c.builder.CreateStore(val, addr)
 | 
			
		||||
	store.SetVolatile(true)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче