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