def destroyClosure(refcAddr, cx): # assuming nonnull cdt = closureDestructorType(cx) sizep, funcpp, funcp, voidp = cx.local(), cx.local(), cx.local(), cx.local( ) cx.useBuiltin('~free') return [ inst.linearGEP(refcAddr, '%size_t', sizep, -1), inst.bitcast('%size_t*', lt.Pointer(cdt, cx), sizep, funcpp), inst.load(cdt, funcpp, funcp), inst.bitcast('%size_t*', '%voidptr', sizep, voidp), 'call void %s(%%voidptr %s)' % (funcp, voidp) ]
def compile(self, cx, out): expr, tagged, ptr = cx.local(), cx.local(), cx.local() sideType = lu.sumSideType(cx.s[self.type].parms[self.side].llvm(cx)) return self.expr.compile(cx, expr) + \ lu.formAggregate(sideType, cx, tagged, self.side, expr) \ + lu.heapCreate(sideType, tagged, cx, ptr) + [ inst.bitcast('%s*' % sideType, self.type.llvm(cx), ptr, out)]
def compile(self, cx, out): psum, pside, p = cx.local(), cx.local(), cx.local() tp = self.type.llvm(cx) sst = lu.sumSideType(tp) return self.expr.compile(cx, psum) + [ inst.bitcast('i1*', '%s*' % sst, psum, pside), inst.structGEP(pside, sst, p, 1), inst.load(tp, p, out)] + mem.reference(out, self.type, cx) + \ mem.unreference(psum, self.expr.type, cx)
def heapCreate(ltype, value, cx, out): voidp, rcp, rcval = cx.local(), cx.local(), cx.local() cx.useBuiltin('~malloc') rctype = mem.rctype(ltype, cx) return formAggregate(rctype, cx, rcval, 1, value) + [ '%s = call %%voidptr @malloc(%%size_t %d)' % (voidp, rctype.size), inst.bitcast('%voidptr', lt.Pointer(rctype, cx), voidp, rcp), inst.store(rctype, rcval, rcp), inst.structGEP(rcp, rctype, out, 1) ]
def createClosure(clType, clStuff, destructor, cx, out): t = closureTypeFull(clType, cx) voidp, rcp, rcval = cx.local(), cx.local(), cx.local() cx.useBuiltin('~malloc') return lu.formAggregate(t, cx, rcval, destructor, 1, clStuff) + [ '%s = call %%voidptr @malloc(%%size_t %d)' % (voidp, t.size), inst.bitcast('%voidptr', lt.Pointer(t, cx), voidp, rcp), inst.store(t, rcval, rcp), inst.structGEP(rcp, t, out, 2) ]
def destroySide(i): lt_i = mtype.parms[i].llvm(cx) sst = lu.sumSideType(lt_i) r, sp, mp = cx.local(), cx.local(), cx.local() unrefCode = unreference(r, mtype.parms[i], cx) if not unrefCode: return [] return [ inst.bitcast('i1*', lt.Pointer(sst, cx), '%object', sp), inst.structGEP(sp, sst, mp, 1), inst.load(lt_i, mp, r) ] + unrefCode
def closureDestructorDefinition(name, clType, items, cx): sig = 'void %s(%%voidptr %%cl)' % name clTypeFull = closureTypeFull(clType, cx) body = [] for i, (ltype, unrefCode, reg) in enumerate(items): unrefCode = unrefCode(cx) if unrefCode: body += [inst.extractvalue(clType, '%stuff', i, reg)] + unrefCode if body: body = [ inst.bitcast('%voidptr', lt.Pointer(clTypeFull, cx), '%cl', '%p'), inst.structGEP('%p', clTypeFull, '%stuffP', 2), inst.load(clType, '%stuffP', '%stuff') ] + body body += ['call void @free(%voidptr %cl)', inst.ret()] return lu.formatFunctionDef(sig, body, cx.llvmVersion)
def getDestructor(self, mtype): # for sum types smtype = self.canonicalStr(mtype) if smtype in self.destructors: return self.destructors[smtype] name = self.destructor() self.destructors[smtype] = name self.useBuiltin('~free') dbody = ['; ' + smtype] + mem.sumDestructorBody(mtype, self) sig = 'void %s(%s %%object)' % (name, mtype.llvm(self)) dbody += mem.getPtrToRefcount('%object', 'i1*', self, '%prefc') + [ inst.bitcast('%size_t*', '%voidptr', '%prefc', '%pvoid'), 'call void @free(%voidptr %pvoid)', inst.ret() ] self.destructorDefinitions.append( formatFunctionDef(sig, dbody, self.llvmVersion)) return name
def unreference(v, mtype, cx): mtype = cx.s[mtype] if canonicalStorage(mtype, cx.s) is StorageType.POINTER: sizep, refc = cx.local(), cx.local() return [inst.bitcast('i1*', '%size_t*', v, sizep), inst.linearGEP(sizep, '%size_t', refc, -1)] + \ heapRefcountDecrement(refc, ['call void %s(i1* %s)' % (cx.getDestructor(mtype), v)], cx) elif isinstance(mtype, types.Product): code = [] for i in 0, 1: r = cx.local() refcode = unreference(r, mtype.parms[i], cx) if refcode: code += lu.extractProductElement(mtype, v, i, cx, r) code += refcode return code elif isinstance(mtype, types.Arrow): r, prefc = cx.local(), cx.local() return lu.funcObjClosure(v, mtype, cx, r) + nullChecked( r, cx.voidptr, getPtrToRefcount(r, cx.voidptr, cx, prefc) + heapRefcountDecrement(prefc, destroyClosure(prefc, cx), cx), cx) return []
def getPtrToRefcount(addr, ptrType, cx, out): sizeptr = cx.local() return [ inst.bitcast(ptrType, '%size_t*', addr, sizeptr), inst.linearGEP(sizeptr, '%size_t', out, -1) ]