Skip to content

Commit ad992e2

Browse files
aykevldeadprogram
authored andcommitted
compiler: refactor top-level createInstruction function
1 parent c1521fe commit ad992e2

File tree

2 files changed

+64
-62
lines changed

2 files changed

+64
-62
lines changed

compiler/compiler.go

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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

compiler/gc.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,62 +12,62 @@ import (
1212

1313
// trackExpr inserts pointer tracking intrinsics for the GC if the expression is
1414
// one of the expressions that need this.
15-
func (c *Compiler) trackExpr(frame *Frame, expr ssa.Value, value llvm.Value) {
15+
func (b *builder) trackExpr(expr ssa.Value, value llvm.Value) {
1616
// There are uses of this expression, Make sure the pointers
1717
// are tracked during GC.
1818
switch expr := expr.(type) {
1919
case *ssa.Alloc, *ssa.MakeChan, *ssa.MakeMap:
2020
// These values are always of pointer type in IR.
21-
c.trackPointer(value)
21+
b.trackPointer(value)
2222
case *ssa.Call, *ssa.Convert, *ssa.MakeClosure, *ssa.MakeInterface, *ssa.MakeSlice, *ssa.Next:
2323
if !value.IsNil() {
24-
c.trackValue(value)
24+
b.trackValue(value)
2525
}
2626
case *ssa.Select:
27-
if alloca, ok := frame.selectRecvBuf[expr]; ok {
27+
if alloca, ok := b.selectRecvBuf[expr]; ok {
2828
if alloca.IsAUndefValue().IsNil() {
29-
c.trackPointer(alloca)
29+
b.trackPointer(alloca)
3030
}
3131
}
3232
case *ssa.UnOp:
3333
switch expr.Op {
3434
case token.MUL:
3535
// Pointer dereference.
36-
c.trackValue(value)
36+
b.trackValue(value)
3737
case token.ARROW:
3838
// Channel receive operator.
3939
// It's not necessary to look at commaOk here, because in that
4040
// case it's just an aggregate and trackValue will extract the
4141
// pointer in there (if there is one).
42-
c.trackValue(value)
42+
b.trackValue(value)
4343
}
4444
}
4545
}
4646

4747
// trackValue locates pointers in a value (possibly an aggregate) and tracks the
4848
// individual pointers
49-
func (c *Compiler) trackValue(value llvm.Value) {
49+
func (b *builder) trackValue(value llvm.Value) {
5050
typ := value.Type()
5151
switch typ.TypeKind() {
5252
case llvm.PointerTypeKind:
53-
c.trackPointer(value)
53+
b.trackPointer(value)
5454
case llvm.StructTypeKind:
5555
if !typeHasPointers(typ) {
5656
return
5757
}
5858
numElements := typ.StructElementTypesCount()
5959
for i := 0; i < numElements; i++ {
60-
subValue := c.builder.CreateExtractValue(value, i, "")
61-
c.trackValue(subValue)
60+
subValue := b.CreateExtractValue(value, i, "")
61+
b.trackValue(subValue)
6262
}
6363
case llvm.ArrayTypeKind:
6464
if !typeHasPointers(typ) {
6565
return
6666
}
6767
numElements := typ.ArrayLength()
6868
for i := 0; i < numElements; i++ {
69-
subValue := c.builder.CreateExtractValue(value, i, "")
70-
c.trackValue(subValue)
69+
subValue := b.CreateExtractValue(value, i, "")
70+
b.trackValue(subValue)
7171
}
7272
}
7373
}

0 commit comments

Comments
 (0)