@@ -1000,7 +1000,7 @@ func (c *Compiler) parseFunc(frame *Frame) {
10001000 fmt .Printf ("\t %s\n " , instr .String ())
10011001 }
10021002 }
1003- c . parseInstr ( frame , instr )
1003+ frame . createInstruction ( instr )
10041004 }
10051005 if frame .fn .Name () == "init" && len (block .Instrs ) == 0 {
10061006 c .builder .CreateRetVoid ()
@@ -1018,69 +1018,71 @@ func (c *Compiler) parseFunc(frame *Frame) {
10181018 }
10191019}
10201020
1021- func (c * Compiler ) parseInstr (frame * Frame , instr ssa.Instruction ) {
1022- if c .Debug () {
1023- pos := c .ir .Program .Fset .Position (instr .Pos ())
1024- c .builder .SetCurrentDebugLocation (uint (pos .Line ), uint (pos .Column ), frame .difunc , llvm.Metadata {})
1021+ // createInstruction builds the LLVM IR equivalent instructions for the
1022+ // particular Go SSA instruction.
1023+ func (b * builder ) createInstruction (instr ssa.Instruction ) {
1024+ if b .Debug () {
1025+ pos := b .ir .Program .Fset .Position (instr .Pos ())
1026+ b .SetCurrentDebugLocation (uint (pos .Line ), uint (pos .Column ), b .difunc , llvm.Metadata {})
10251027 }
10261028
10271029 switch instr := instr .(type ) {
10281030 case ssa.Value :
1029- if value , err := frame .createExpr (instr ); err != nil {
1031+ if value , err := b .createExpr (instr ); err != nil {
10301032 // This expression could not be parsed. Add the error to the list
10311033 // of diagnostics and continue with an undef value.
10321034 // The resulting IR will be incorrect (but valid). However,
10331035 // compilation can proceed which is useful because there may be
10341036 // more compilation errors which can then all be shown together to
10351037 // the user.
1036- c .diagnostics = append (c .diagnostics , err )
1037- frame .locals [instr ] = llvm .Undef (c .getLLVMType (instr .Type ()))
1038+ b .diagnostics = append (b .diagnostics , err )
1039+ b .locals [instr ] = llvm .Undef (b .getLLVMType (instr .Type ()))
10381040 } else {
1039- frame .locals [instr ] = value
1040- if len (* instr .Referrers ()) != 0 && c .NeedsStackObjects () {
1041- c .trackExpr (frame , instr , value )
1041+ b .locals [instr ] = value
1042+ if len (* instr .Referrers ()) != 0 && b .NeedsStackObjects () {
1043+ b .trackExpr (instr , value )
10421044 }
10431045 }
10441046 case * ssa.DebugRef :
10451047 // ignore
10461048 case * ssa.Defer :
1047- frame .createDefer (instr )
1049+ b .createDefer (instr )
10481050 case * ssa.Go :
10491051 // Get all function parameters to pass to the goroutine.
10501052 var params []llvm.Value
10511053 for _ , param := range instr .Call .Args {
1052- params = append (params , frame .getValue (param ))
1054+ params = append (params , b .getValue (param ))
10531055 }
10541056
10551057 // Start a new goroutine.
10561058 if callee := instr .Call .StaticCallee (); callee != nil {
10571059 // Static callee is known. This makes it easier to start a new
10581060 // goroutine.
1059- calleeFn := c .ir .GetFunction (callee )
1061+ calleeFn := b .ir .GetFunction (callee )
10601062 var context llvm.Value
10611063 switch value := instr .Call .Value .(type ) {
10621064 case * ssa.Function :
10631065 // Goroutine call is regular function call. No context is necessary.
1064- context = llvm .Undef (c .i8ptrType )
1066+ context = llvm .Undef (b .i8ptrType )
10651067 case * ssa.MakeClosure :
10661068 // A goroutine call on a func value, but the callee is trivial to find. For
10671069 // example: immediately applied functions.
1068- funcValue := frame .getValue (value )
1069- context = frame .extractFuncContext (funcValue )
1070+ funcValue := b .getValue (value )
1071+ context = b .extractFuncContext (funcValue )
10701072 default :
10711073 panic ("StaticCallee returned an unexpected value" )
10721074 }
10731075 params = append (params , context ) // context parameter
1074- frame .createGoInstruction (calleeFn .LLVMFn , params )
1076+ b .createGoInstruction (calleeFn .LLVMFn , params )
10751077 } else if ! instr .Call .IsInvoke () {
10761078 // This is a function pointer.
10771079 // At the moment, two extra params are passed to the newly started
10781080 // goroutine:
10791081 // * The function context, for closures.
10801082 // * The function pointer (for tasks).
1081- funcPtr , context := frame .decodeFuncValue (frame .getValue (instr .Call .Value ), instr .Call .Value .Type ().(* types.Signature ))
1083+ funcPtr , context := b .decodeFuncValue (b .getValue (instr .Call .Value ), instr .Call .Value .Type ().(* types.Signature ))
10821084 params = append (params , context ) // context parameter
1083- switch c .Scheduler () {
1085+ switch b .Scheduler () {
10841086 case "none" , "coroutines" :
10851087 // There are no additional parameters needed for the goroutine start operation.
10861088 case "tasks" :
@@ -1089,58 +1091,58 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
10891091 default :
10901092 panic ("unknown scheduler type" )
10911093 }
1092- frame .createGoInstruction (funcPtr , params )
1094+ b .createGoInstruction (funcPtr , params )
10931095 } else {
1094- c .addError (instr .Pos (), "todo: go on interface call" )
1096+ b .addError (instr .Pos (), "todo: go on interface call" )
10951097 }
10961098 case * ssa.If :
1097- cond := frame .getValue (instr .Cond )
1099+ cond := b .getValue (instr .Cond )
10981100 block := instr .Block ()
1099- blockThen := frame .blockEntries [block .Succs [0 ]]
1100- blockElse := frame .blockEntries [block .Succs [1 ]]
1101- c . builder .CreateCondBr (cond , blockThen , blockElse )
1101+ blockThen := b .blockEntries [block .Succs [0 ]]
1102+ blockElse := b .blockEntries [block .Succs [1 ]]
1103+ b .CreateCondBr (cond , blockThen , blockElse )
11021104 case * ssa.Jump :
1103- blockJump := frame .blockEntries [instr .Block ().Succs [0 ]]
1104- c . builder .CreateBr (blockJump )
1105+ blockJump := b .blockEntries [instr .Block ().Succs [0 ]]
1106+ b .CreateBr (blockJump )
11051107 case * ssa.MapUpdate :
1106- m := frame .getValue (instr .Map )
1107- key := frame .getValue (instr .Key )
1108- value := frame .getValue (instr .Value )
1108+ m := b .getValue (instr .Map )
1109+ key := b .getValue (instr .Key )
1110+ value := b .getValue (instr .Value )
11091111 mapType := instr .Map .Type ().Underlying ().(* types.Map )
1110- frame .createMapUpdate (mapType .Key (), m , key , value , instr .Pos ())
1112+ b .createMapUpdate (mapType .Key (), m , key , value , instr .Pos ())
11111113 case * ssa.Panic :
1112- value := frame .getValue (instr .X )
1113- c .createRuntimeCall ("_panic" , []llvm.Value {value }, "" )
1114- c . builder .CreateUnreachable ()
1114+ value := b .getValue (instr .X )
1115+ b .createRuntimeCall ("_panic" , []llvm.Value {value }, "" )
1116+ b .CreateUnreachable ()
11151117 case * ssa.Return :
11161118 if len (instr .Results ) == 0 {
1117- c . builder .CreateRetVoid ()
1119+ b .CreateRetVoid ()
11181120 } else if len (instr .Results ) == 1 {
1119- c . builder . CreateRet (frame .getValue (instr .Results [0 ]))
1121+ b . CreateRet (b .getValue (instr .Results [0 ]))
11201122 } else {
11211123 // Multiple return values. Put them all in a struct.
1122- retVal := llvm .ConstNull (frame .fn .LLVMFn .Type ().ElementType ().ReturnType ())
1124+ retVal := llvm .ConstNull (b .fn .LLVMFn .Type ().ElementType ().ReturnType ())
11231125 for i , result := range instr .Results {
1124- val := frame .getValue (result )
1125- retVal = c . builder .CreateInsertValue (retVal , val , i , "" )
1126+ val := b .getValue (result )
1127+ retVal = b .CreateInsertValue (retVal , val , i , "" )
11261128 }
1127- c . builder .CreateRet (retVal )
1129+ b .CreateRet (retVal )
11281130 }
11291131 case * ssa.RunDefers :
1130- frame .createRunDefers ()
1132+ b .createRunDefers ()
11311133 case * ssa.Send :
1132- frame .createChanSend (instr )
1134+ b .createChanSend (instr )
11331135 case * ssa.Store :
1134- llvmAddr := frame .getValue (instr .Addr )
1135- llvmVal := frame .getValue (instr .Val )
1136- frame .createNilCheck (llvmAddr , "store" )
1137- if c .targetData .TypeAllocSize (llvmVal .Type ()) == 0 {
1136+ llvmAddr := b .getValue (instr .Addr )
1137+ llvmVal := b .getValue (instr .Val )
1138+ b .createNilCheck (llvmAddr , "store" )
1139+ if b .targetData .TypeAllocSize (llvmVal .Type ()) == 0 {
11381140 // nothing to store
11391141 return
11401142 }
1141- c . builder .CreateStore (llvmVal , llvmAddr )
1143+ b .CreateStore (llvmVal , llvmAddr )
11421144 default :
1143- c .addError (instr .Pos (), "unknown instruction: " + instr .String ())
1145+ b .addError (instr .Pos (), "unknown instruction: " + instr .String ())
11441146 }
11451147}
11461148
0 commit comments