def compile(self, expr): from mlbuiltins import definition expr.markDepth(0) xreg = self.local() compiled = expr.compile(self, xreg) + mem.unreference( xreg, expr.type, self) + [inst.ret()] out = initial_typedefs + '%%size_t = type %s\n\n' % self.size_t for n in self.freeTypeNums: out += '%%free_type_%d = type i1\n' % n out += '\n' for b in self.builtins: out += definition[b] for nam, tp in self.funcTypeDeclarations.values(): out += '\n' + nam + ' = ' + tp out += '\n\n' for l in self.lambdaDefinitions: out += l out += '\n' for d in self.destructorDefinitions: out += d out += '\n' + formatFunctionDef('void @ml_program()', compiled, self.llvmVersion) out += '\n' + formatFunctionDef( 'i32 @main()', ['call void @ml_program()', 'ret i32 0'], self.llvmVersion) return out
def regBinaryIntOp(name, instr, type): ltype = type.llvm(None) mIntpair = types.Product(types.Int, types.Int) intpair = mIntpair.llvm(None) sig = '%s @%s(%%voidptr, %s %%args)' % (ltype, name, intpair) lines = [inst.extractvalue(intpair, '%args', 0, '%x'), inst.extractvalue(intpair, '%args', 1, '%y'), '%%result = %s %%Int %%x, %%y' % instr, inst.ret(ltype, '%result')] reg(name, types.Arrow(mIntpair, type), lu.formatFunctionDef(sig, lines, 0))
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
''') reg('ml_getchar', types.Arrow(types.Unit(), types.Int), ''' declare i32 @getchar() define %Int @ml_getchar(%voidptr, %Unit) { %c32 = call i32 @getchar() %c64 = sext i32 %c32 to %Int ret %Int %c64 } ''') reg('integer_negate', types.Arrow(types.Int, types.Int), lu.formatFunctionDef('%Int @integer_negate(%voidptr, %Int %n)', [inst.sub_nsw('%Int', 0, '%n', '%result'), inst.ret('%Int', '%result')], 0)) reg('~malloc', None, 'declare %voidptr @malloc(%size_t)') reg('~free', None, 'declare void @free(%voidptr)') def regBinaryIntOp(name, instr, type): ltype = type.llvm(None) mIntpair = types.Product(types.Int, types.Int) intpair = mIntpair.llvm(None) sig = '%s @%s(%%voidptr, %s %%args)' % (ltype, name, intpair) lines = [inst.extractvalue(intpair, '%args', 0, '%x'), inst.extractvalue(intpair, '%args', 1, '%y'), '%%result = %s %%Int %%x, %%y' % instr, inst.ret(ltype, '%result')] reg(name, types.Arrow(mIntpair, type), lu.formatFunctionDef(sig, lines, 0))
def compile(self, cx, out): name = cx.lamb() arg = cx.local() retLtype = self.type.result().llvm(cx) fsig = '%s %s(%%voidptr %%cl0, %s %s)' % ( retLtype, name, self.type.argument().llvm(cx), arg) fout = cx.local() k = (self.var, cx.canonicalStr(self.var.type)) cx.bindings[k] = (arg, self.var.type.llvm(cx)) cx.bindings2[k] = (lu.reusable(mem.reference(arg, self.var.type, cx), arg), lu.reusable(mem.unreference(arg, self.var.type, cx), arg)) exprCode = self.expr.compile(cx, fout) del cx.bindings[k], cx.bindings2[k] cv0 = set(self.closedVars()) cv = [(var, ltype, cstr, reg) for (var, cstr), (reg, ltype) in cx.bindings.items() if var in cv0] if cv: clTypes = list(zip(*cv))[1] clType = lu.closureType(clTypes, cx) loadClosure = [ '%%clPtr = bitcast %%voidptr %%cl0 to %s*' % clType, inst.load(clType, '%clPtr', '%cl') ] clTypedPtr, clPtr = cx.local(), cx.local() storeClosure = [] builder = 'undef' copiedRegs = set() closureItems = [] for i, (var, ltype, cstr, rBound) in enumerate(cv): reg = cx.local() if rBound in copiedRegs: continue copiedRegs.add(rBound) ref, unref = cx.bindings2[(var, cstr)] closureItems.append((ltype, unref, rBound)) loadClosure.append(inst.extractvalue(clType, '%cl', i, rBound)) storeClosure.append('%s = insertvalue %s %s, %s %s, %d' % (reg, clType, builder, ltype, rBound, i)) builder = reg storeClosure += ref(cx) destruc = cx.closureDestructor() storeClosure += mem.createClosure(clType, builder, destruc, cx, clTypedPtr) storeClosure += [ '%s = bitcast %s* %s to %%voidptr' % (clPtr, clType, clTypedPtr) ] cx.destructorDefinitions.append( mem.closureDestructorDefinition(destruc, clType, closureItems, cx)) else: loadClosure = storeClosure = [] clPtr = 'null' fbody = loadClosure + exprCode + [inst.ret(retLtype, fout)] cx.lambdaDefinitions.append( lu.formatFunctionDef(fsig, fbody, cx.llvmVersion)) return storeClosure + lu.makeFuncObj(name, self.type, clPtr, cx, out)