ir_closure.mx raw
1 package main
2
3 func (e *irEmitter) emitMakeClosure(m *SSAMakeClosure) {
4 reg := e.regName(m)
5 fn, _ := m.Fn.(*SSAFunction)
6 ipt := e.intptrType()
7
8 if len(m.Bindings) == 0 {
9 t1a := e.nextReg2("mc")
10 e.w(" ") ; e.w(t1a) ; e.w(" = insertvalue {ptr, ptr} undef, ptr null, 0\n")
11 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue {ptr, ptr} ") ; e.w(t1a)
12 e.w(", ptr ") ; e.w(e.funcSymbol(fn)) ; e.w(", 1\n")
13 return
14 }
15
16 ctxType := e.closureContextType(m.Bindings)
17 ctxSz := e.nextReg2("mc")
18 e.w(" ") ; e.w(ctxSz) ; e.w(" = ptrtoint ptr getelementptr (")
19 e.w(ctxType) ; e.w(", ptr null, i32 1) to ") ; e.w(ipt) ; e.w("\n")
20 ctxPtr := e.nextReg2("mc")
21 e.w(" ") ; e.w(ctxPtr) ; e.w(" = call ptr @runtime.alloc(")
22 e.w(ipt) ; e.w(" ") ; e.w(ctxSz) ; e.w(", ptr null, ptr null)\n")
23 e.declareRuntime("runtime.alloc", "ptr", ipt | ", ptr")
24 e.scopeTrackAlloc(ctxPtr)
25
26 for i, b := range m.Bindings {
27 bval := e.operand(b)
28 _, isFreeVar := b.(*SSAFreeVar)
29 actualType := e.llvmType(b.SSAType())
30 if !isFreeVar && actualType != "ptr" && actualType != "" && actualType != "void" {
31 boxAlloc := e.nextReg2("mc")
32 e.w(" ") ; e.w(boxAlloc) ; e.w(" = call ptr @runtime.alloc(")
33 e.w(ipt) ; e.w(" ptrtoint (ptr getelementptr (") ; e.w(actualType)
34 e.w(", ptr null, i32 1) to ") ; e.w(ipt) ; e.w("), ptr null, ptr null)\n")
35 e.w(" store ") ; e.w(actualType) ; e.w(" ") ; e.w(bval) ; e.w(", ptr ") ; e.w(boxAlloc) ; e.w("\n")
36 bval = boxAlloc
37 }
38 gep := e.nextReg2("mc")
39 e.w(" ") ; e.w(gep) ; e.w(" = getelementptr ") ; e.w(ctxType) ; e.w(", ptr ")
40 e.w(ctxPtr) ; e.w(", i32 0, i32 ") ; e.w(irItoa(i)) ; e.w("\n")
41 e.w(" store ptr ") ; e.w(bval) ; e.w(", ptr ") ; e.w(gep) ; e.w("\n")
42 }
43
44 t1 := e.nextReg2("mc")
45 e.w(" ") ; e.w(t1) ; e.w(" = insertvalue {ptr, ptr} undef, ptr ") ; e.w(ctxPtr) ; e.w(", 0\n")
46 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue {ptr, ptr} ") ; e.w(t1)
47 e.w(", ptr ") ; e.w(e.funcSymbol(fn)) ; e.w(", 1\n")
48 }
49
50 func (e *irEmitter) closureBindingType(b SSAValue) (s string) {
51 return "ptr"
52 }
53
54 func (e *irEmitter) closureContextType(bindings []SSAValue) (s string) {
55 s := "{"
56 for i, b := range bindings {
57 if i > 0 {
58 s = s | ", "
59 }
60 s = s | e.closureBindingType(b)
61 }
62 return s | "}"
63 }
64
65 func (e *irEmitter) freeVarType(fv *SSAFreeVar) (s string) {
66 return "ptr"
67 }
68
69 func (e *irEmitter) emitFreeVarUnpack(f *SSAFunction) {
70 ctxName := "_ctx"
71 ctxType := "{"
72 for i, fv := range f.FreeVars {
73 if i > 0 {
74 ctxType = ctxType | ", "
75 }
76 ctxType = ctxType | e.freeVarType(fv)
77 }
78 ctxType = ctxType | "}"
79
80 for i, fv := range f.FreeVars {
81 fvName := e.regName(fv)
82 e.nextReg++
83 gep := "%fv" | irItoa(e.nextReg)
84 e.w(" ") ; e.w(gep) ; e.w(" = getelementptr ") ; e.w(ctxType)
85 e.w(", ptr %") ; e.w(ctxName) ; e.w(", i32 0, i32 ") ; e.w(irItoa(i)) ; e.w("\n")
86 e.w(" ") ; e.w(fvName) ; e.w(" = load ptr, ptr ") ; e.w(gep) ; e.w("\n")
87 }
88 }
89