[pypy-svn] r18227 - in pypy/dist/pypy/translator/js: . test

ericvrp at codespeak.net ericvrp at codespeak.net
Thu Oct 6 22:24:07 CEST 2005


Author: ericvrp
Date: Thu Oct  6 22:24:04 2005
New Revision: 18227

Added:
   pypy/dist/pypy/translator/js/
   pypy/dist/pypy/translator/js/__init__.py   (contents, props changed)
   pypy/dist/pypy/translator/js/arraynode.py   (contents, props changed)
   pypy/dist/pypy/translator/js/codewriter.py   (contents, props changed)
   pypy/dist/pypy/translator/js/database.py   (contents, props changed)
   pypy/dist/pypy/translator/js/exception.py   (contents, props changed)
   pypy/dist/pypy/translator/js/extfuncnode.py   (contents, props changed)
   pypy/dist/pypy/translator/js/funcnode.py   (contents, props changed)
   pypy/dist/pypy/translator/js/gc.py   (contents, props changed)
   pypy/dist/pypy/translator/js/js.py   (contents, props changed)
   pypy/dist/pypy/translator/js/log.py   (contents, props changed)
   pypy/dist/pypy/translator/js/node.py   (contents, props changed)
   pypy/dist/pypy/translator/js/opaquenode.py   (contents, props changed)
   pypy/dist/pypy/translator/js/opwriter.py   (contents, props changed)
   pypy/dist/pypy/translator/js/structnode.py   (contents, props changed)
   pypy/dist/pypy/translator/js/test/
   pypy/dist/pypy/translator/js/test/__init__.py   (contents, props changed)
   pypy/dist/pypy/translator/js/test/runtest.py   (contents, props changed)
   pypy/dist/pypy/translator/js/test/test_trivial.py   (contents, props changed)
   pypy/dist/pypy/translator/js/varsize.py   (contents, props changed)
Log:
Let me be ambitious by adding a Javascript backend.

This is at the moment still a stripped down version of the llvm backend
and as such does not work!



Added: pypy/dist/pypy/translator/js/__init__.py
==============================================================================

Added: pypy/dist/pypy/translator/js/arraynode.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/arraynode.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,198 @@
+import py
+from pypy.rpython import lltype
+from pypy.translator.llvm.log import log
+from pypy.translator.llvm.node import LLVMNode, ConstantLLVMNode
+from pypy.translator.llvm import varsize 
+log = log.structnode
+
+class ArrayTypeNode(LLVMNode):
+    __slots__ = "db array arraytype ref constructor_ref constructor_decl".split()
+
+    def __init__(self, db, array):
+        assert isinstance(array, lltype.Array)
+        self.db = db
+        self.array = array
+        self.arraytype = arraytype = array.OF
+        # ref is used to reference the arraytype in llvm source 
+        # constructor_ref is used to reference the constructor 
+        # for the array type in llvm source code 
+        # constructor_decl is used to declare the constructor
+        # for the array type (see writeimpl)
+        name = ""        
+        if isinstance(arraytype, lltype.Ptr):
+            name += "ptr_"
+            arraytype = arraytype.TO
+        if hasattr(arraytype, "_name"):            
+            name += arraytype._name
+        else:
+            name += str(arraytype)
+
+        self.ref = self.make_ref('%arraytype.', name)
+        self.constructor_ref = self.make_ref('%new.array.', name)
+        self.constructor_decl = "%s * %s(%s %%len)" % \
+                                (self.ref,
+                                 self.constructor_ref,
+                                 self.db.get_machine_word())
+
+    def __str__(self):
+        return "<ArrayTypeNode %r>" % self.ref
+        
+    def setup(self):
+        self.db.prepare_type(self.arraytype)
+
+    # ______________________________________________________________________
+    # entry points from genllvm
+    #
+    def writedatatypedecl(self, codewriter):
+        codewriter.arraydef(self.ref,
+                            self.db.get_machine_word(),
+                            self.db.repr_type(self.arraytype))
+
+    def writedecl(self, codewriter): 
+        # declaration for constructor
+        codewriter.declare(self.constructor_decl)
+
+    def writeimpl(self, codewriter):
+        log.writeimpl(self.ref)
+        varsize.write_constructor(self.db, codewriter, self.ref, 
+                                  self.constructor_decl,
+                                  self.array)
+
+
+class VoidArrayTypeNode(LLVMNode):
+    __slots__ = "db array ref".split()
+
+    def __init__(self, db, array):
+        assert isinstance(array, lltype.Array)
+        self.db = db
+        self.array = array
+        self.ref = "%arraytype.Void"
+
+    def writedatatypedecl(self, codewriter):
+        td = "%s = type { %s }" % (self.ref, self.db.get_machine_word())
+        codewriter.append(td)
+        
+class ArrayNode(ConstantLLVMNode):
+    """ An arraynode.  Elements can be
+    a primitive,
+    a struct,
+    pointer to struct/array
+    """
+    __slots__ = "db value arraytype ref".split()
+    
+    def __init__(self, db, value):
+        assert isinstance(lltype.typeOf(value), lltype.Array)
+        self.db = db
+        self.value = value
+        self.arraytype = lltype.typeOf(value).OF
+        prefix = '%arrayinstance'
+        name = '' #str(value).split()[1]
+        self.ref = self.make_ref(prefix, name)
+
+    def __str__(self):
+        return "<ArrayNode %r>" % (self.ref,)
+
+    def setup(self):
+        for item in self.value.items:
+            self.db.prepare_constant(self.arraytype, item)
+
+        p, c = lltype.parentlink(self.value)
+        p, c = lltype.parentlink(self.value)
+        if p is not None:
+            self.db.prepare_constant(lltype.typeOf(p), p)
+
+    def get_length(self):
+        """ returns logical length of array """
+        items = self.value.items
+        return len(items)
+
+    def get_arrayvalue(self):
+        items = self.value.items
+        l = len(items)
+        r = "[%s]" % ", ".join([self.db.repr_constant(v)[1] for v in items])
+        return l, r 
+
+    def get_typerepr(self):
+        arraylen = self.get_arrayvalue()[0]
+        typeval = self.db.repr_type(self.arraytype)
+        return "{ %s, [%s x %s] }" % (self.db.get_machine_word(),
+                                      arraylen, typeval)
+
+    def get_ref(self):
+        typeval = self.db.repr_type(lltype.typeOf(self.value))
+        ref = "cast (%s* %s to %s*)" % (self.get_typerepr(),
+                                        self.ref,
+                                        typeval)
+
+        p, c = lltype.parentlink(self.value)
+        assert p is None, "child arrays are NOT needed by rtyper"
+        return ref
+
+    def get_pbcref(self, toptr):
+        ref = self.ref
+        p, c = lltype.parentlink(self.value)
+        assert p is None, "child arrays are NOT needed by rtyper"
+
+        fromptr = "%s*" % self.get_typerepr()
+        ref = "cast(%s %s to %s)" % (fromptr, ref, toptr)
+        return ref
+
+    def get_childref(self, index):
+        return "getelementptr(%s* %s, int 0, uint 1, int %s)" %(
+            self.get_typerepr(),
+            self.ref,
+            index)
+    
+    def constantvalue(self):
+        physicallen, arrayrepr = self.get_arrayvalue()
+        typeval = self.db.repr_type(self.arraytype)
+
+        # first length is logical, second is physical
+        value = "%s %s, [%s x %s] %s" % (self.db.get_machine_word(),
+                                         self.get_length(),
+                                         physicallen,
+                                         typeval,
+                                         arrayrepr)
+
+        s = "%s {%s}" % (self.get_typerepr(), value)
+        return s
+    
+class StrArrayNode(ArrayNode):
+    __slots__ = "".split()
+
+    printables = dict([(ord(i), None) for i in
+      ("0123456789abcdefghijklmnopqrstuvwxyz" +
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+       "!#$%&()*+,-./:;<=>?@[]^_`{|}~ '")])
+
+    def get_arrayvalue(self):
+        items = self.value.items
+        item_length = len(items)
+        if item_length == 0 or items[-1] != chr(0):
+            items = items + [chr(0)]
+            item_length += 1
+        s = []
+        for c in items:
+            if ord(c) in StrArrayNode.printables:
+                s.append(c)
+            else:
+                s.append("\\%02x" % ord(c))
+                
+        r = 'c"%s"' % "".join(s)
+        return item_length, r
+
+class VoidArrayNode(ConstantLLVMNode):
+    __slots__ = "db value ref".split()
+
+    def __init__(self, db, value):
+        assert isinstance(lltype.typeOf(value), lltype.Array)
+        self.db = db
+        self.value = value
+        prefix = '%arrayinstance'
+        name = '' #str(value).split()[1]
+        self.ref = self.make_ref(prefix, name)
+
+    def constantvalue(self):
+        return "{ %s } {%s %s}" % (self.db.get_machine_word(),
+                                   self.db.get_machine_word(),
+                                   len(self.value.items))

Added: pypy/dist/pypy/translator/js/codewriter.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/codewriter.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,154 @@
+import py
+from itertools import count
+from pypy.translator.llvm.log import log 
+
+log = log.codewriter 
+
+DEFAULT_TAIL     = ''       #/tail
+DEFAULT_CCONV    = 'fastcc'    #ccc/fastcc
+
+class CodeWriter(object): 
+    def __init__(self, f, genllvm): 
+        self.f = f
+        self.genllvm = genllvm
+        self.word  = genllvm.db.get_machine_word()
+        self.uword = genllvm.db.get_machine_uword()
+
+    def append(self, line): 
+        self.f.write(line + '\n')
+
+    def comment(self, line, indent=True):
+        line = ";; " + line
+        if indent:
+            self.indent(line)
+        else:
+            self.append(line)
+
+    def newline(self):
+        self.append("")
+
+    def indent(self, line): 
+        self.append("        " + line) 
+
+    def label(self, name):
+        self.newline()
+        self.append("    %s:" % name)
+
+    def globalinstance(self, name, typeandata):
+        self.append("%s = %s global %s" % (name, "internal", typeandata))
+
+    def structdef(self, name, typereprs):
+        self.append("%s = type { %s }" %(name, ", ".join(typereprs)))
+
+    def arraydef(self, name, lentype, typerepr):
+        self.append("%s = type { %s, [0 x %s] }" % (name, lentype, typerepr))
+
+    def funcdef(self, name, rettyperepr, argtypereprs):
+        self.append("%s = type %s (%s)" % (name, rettyperepr,
+                                           ", ".join(argtypereprs)))
+
+    def declare(self, decl, cconv=DEFAULT_CCONV):
+        self.append("declare %s %s" %(cconv, decl,))
+
+    def startimpl(self):
+        self.newline()
+        self.append("implementation")
+        self.newline()
+
+    def br_uncond(self, blockname): 
+        self.indent("br label %%%s" %(blockname,))
+
+    def br(self, cond, blockname_false, blockname_true):
+        self.indent("br bool %s, label %%%s, label %%%s"
+                    % (cond, blockname_true, blockname_false))
+
+    def switch(self, intty, cond, defaultdest, value_label):
+        labels = ''
+        for value, label in value_label:
+            labels += ' %s %s, label %%%s' % (intty, value, label)
+        self.indent("switch %s %s, label %%%s [%s ]"
+                    % (intty, cond, defaultdest, labels))
+
+    def openfunc(self, decl, is_entrynode=False, cconv=DEFAULT_CCONV): 
+        self.newline()
+        #if is_entrynode:
+        #    linkage_type = ''
+        #else:
+        #    linkage_type = 'internal '
+        linkage_type = 'internal '
+        self.append("%s%s %s {" % (linkage_type, cconv, decl,))
+
+    def closefunc(self): 
+        self.append("}") 
+
+    def ret(self, type_, ref): 
+        if type_ == 'void':
+            self.indent("ret void")
+        else:
+            self.indent("ret %s %s" % (type_, ref))
+
+    def phi(self, targetvar, type_, refs, blocknames): 
+        assert targetvar.startswith('%')
+        assert refs and len(refs) == len(blocknames), "phi node requires blocks" 
+        mergelist = ", ".join(
+            ["[%s, %%%s]" % item 
+                for item in zip(refs, blocknames)])
+        s = "%s = phi %s %s" % (targetvar, type_, mergelist)
+        self.indent(s)
+
+    def binaryop(self, name, targetvar, type_, ref1, ref2):
+        self.indent("%s = %s %s %s, %s" % (targetvar, name, type_, ref1, ref2))
+
+    def shiftop(self, name, targetvar, type_, ref1, ref2):
+        self.indent("%s = %s %s %s, ubyte %s" % (targetvar, name, type_, ref1, ref2))
+
+    #from: http://llvm.cs.uiuc.edu/docs/LangRef.html
+    #The optional "tail" marker indicates whether the callee function accesses any
+    # allocas or varargs in the caller. If the "tail" marker is present, the function
+    # call is eligible for tail call optimization. Note that calls may be marked
+    # "tail" even if they do not occur before a ret instruction. 
+    def call(self, targetvar, returntype, functionref, argrefs, argtypes, label=None, except_label=None, tail=DEFAULT_TAIL, cconv=DEFAULT_CCONV):
+        if cconv is not 'fastcc':
+            tail_ = ''
+        else:
+            tail_ = tail
+	if tail_:
+		tail_ += ' '
+        args = ", ".join(["%s %s" % item for item in zip(argtypes, argrefs)])
+        if except_label:
+            self.genllvm.exceptionpolicy.invoke(self, targetvar, tail_, cconv, returntype, functionref, args, label, except_label)
+        else:
+            if returntype == 'void':
+                self.indent("%scall %s void %s(%s)" % (tail_, cconv, functionref, args))
+            else:
+                self.indent("%s = %scall %s %s %s(%s)" % (targetvar, tail_, cconv, returntype, functionref, args))
+
+    def cast(self, targetvar, fromtype, fromvar, targettype):
+    	if fromtype == 'void' and targettype == 'void':
+		return
+        self.indent("%(targetvar)s = cast %(fromtype)s "
+                        "%(fromvar)s to %(targettype)s" % locals())
+
+    def malloc(self, targetvar, type_, size=1, atomic=False, cconv=DEFAULT_CCONV):
+        for s in self.genllvm.gcpolicy.malloc(targetvar, type_, size, atomic, self.word, self.uword).split('\n'):
+            self.indent(s)
+
+    def getelementptr(self, targetvar, type, typevar, *indices):
+        word = self.word
+        res = "%(targetvar)s = getelementptr %(type)s %(typevar)s, %(word)s 0, " % locals()
+        res += ", ".join(["%s %s" % (t, i) for t, i in indices])
+        self.indent(res)
+
+    def load(self, targetvar, targettype, ptr):
+        self.indent("%(targetvar)s = load %(targettype)s* %(ptr)s" % locals())
+
+    def store(self, valuetype, valuevar, ptr): 
+        self.indent("store %(valuetype)s %(valuevar)s, "
+                    "%(valuetype)s* %(ptr)s" % locals())
+
+    def debugcomment(self, tempname, len, tmpname):
+        word = self.word
+        res = "%s = call ccc %(word)s (sbyte*, ...)* %%printf(" % locals()
+        res += "sbyte* getelementptr ([%s x sbyte]* %s, %(word)s 0, %(word)s 0) )" % locals()
+        res = res % (tmpname, len, tmpname)
+        self.indent(res)

Added: pypy/dist/pypy/translator/js/database.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/database.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,369 @@
+
+import sys
+
+from pypy.translator.llvm.log import log 
+from pypy.translator.llvm.funcnode import FuncNode, FuncTypeNode
+from pypy.translator.llvm.extfuncnode import ExternalFuncNode
+from pypy.translator.llvm.structnode import StructNode, StructVarsizeNode, \
+     StructTypeNode, StructVarsizeTypeNode
+from pypy.translator.llvm.arraynode import ArrayNode, StrArrayNode, \
+     VoidArrayNode, ArrayTypeNode, VoidArrayTypeNode
+from pypy.translator.llvm.opaquenode import OpaqueNode, OpaqueTypeNode
+from pypy.translator.llvm.node import ConstantLLVMNode
+from pypy.rpython import lltype
+from pypy.objspace.flow.model import Constant, Variable
+            
+log = log.database 
+
+class Database(object): 
+    def __init__(self, genllvm, translator): 
+        self.genllvm = genllvm
+        self.translator = translator
+        self.obj2node = {}
+        self._pendingsetup = []
+        self._tmpcount = 1
+
+        # debug operation comments
+        self._opcomments = {}
+
+        self.primitives_init()
+
+    def primitives_init(self):
+        primitives = {
+            lltype.Char: "sbyte",
+            lltype.Bool: "bool",
+            lltype.Float: "double",
+            lltype.UniChar: "uint",
+            lltype.Void: "void"}
+
+        # 32 bit platform
+        if sys.maxint == 2**31-1:
+            primitives.update({
+                lltype.Signed: "int",
+                lltype.Unsigned: "uint" })
+            
+        # 64 bit platform
+        elif sys.maxint == 2**63-1:        
+            primitives.update({
+                lltype.Signed: "long",
+                lltype.Unsigned: "ulong" })
+            
+        else:
+            assert False, "Unsupported platform"        
+
+        self.primitives = primitives
+        
+    #_______for debugging llvm code_________________________
+
+    def add_op2comment(self, lenofopstr, op):
+        """ internal method for adding comments on each operation """
+        tmpname = self.repr_tmpvar() + ".comment"
+        self._opcomments[op] = (lenofopstr, tmpname)
+        return tmpname
+        
+    def get_op2comment(self, op):
+        """ internal method for adding comments on each operation """
+        return self._opcomments.get(op, None)
+    
+    #_______debuggging______________________________________
+
+    def dump_pbcs(self):
+        r = ""
+        for k, v in self.obj2node.iteritems():
+            
+            if isinstance(k, lltype.LowLevelType):
+                continue
+
+            assert isinstance(lltype.typeOf(k), lltype.ContainerType)
+            # Only dump top levels
+            p, _ = lltype.parentlink(k)
+            if p is None:
+                ref = v.get_ref()
+                pbc_ref = v.get_ref()
+                
+                r += "\ndump_pbcs %s (%s)\n" \
+                     "getref -> %s \n" \
+                     "pbcref -> %s \n" % (v, k, ref, pbc_ref)
+            return r
+    
+    #_______setting up and preperation______________________________
+
+    def create_constant_node(self, type_, value):
+        node = None
+        if isinstance(type_, lltype.FuncType):
+            if getattr(value._callable, "suggested_primitive", False):
+                node = ExternalFuncNode(self, value)
+            else:
+                node = FuncNode(self, value)
+
+        elif isinstance(type_, lltype.Struct):
+            if type_._arrayfld:
+                node = StructVarsizeNode(self, value)
+            else:
+                node = StructNode(self, value)
+                    
+        elif isinstance(type_, lltype.Array):
+            if type_.OF is lltype.Char:
+                node = StrArrayNode(self, value)
+            elif type_.OF is lltype.Void:
+                node = VoidArrayNode(self, value)
+            else:
+                node = ArrayNode(self, value)
+
+        elif isinstance(type_, lltype.OpaqueType):
+            node = OpaqueNode(self, value)
+
+        assert node is not None, "%s not supported" % (type_)
+        return node
+
+    def addpending(self, key, node):
+        # santity check we at least have a key of the right type
+        assert (isinstance(key, lltype.LowLevelType) or
+                isinstance(lltype.typeOf(key), lltype.ContainerType))
+
+        assert key not in self.obj2node, (
+            "node with key %r already known!" %(key,))
+        
+        #log("added to pending nodes:", type(key), node)        
+
+        self.obj2node[key] = node 
+        self._pendingsetup.append(node)
+        
+    def prepare_type(self, type_):
+        if type_ in self.obj2node:
+            return
+        if isinstance(type_, lltype.Primitive):
+            pass
+        elif isinstance(type_, lltype.Ptr): 
+            self.prepare_type(type_.TO)
+
+        elif isinstance(type_, lltype.Struct):
+            if type_._arrayfld:
+                self.addpending(type_, StructVarsizeTypeNode(self, type_))
+            else:
+                self.addpending(type_, StructTypeNode(self, type_))                
+        elif isinstance(type_, lltype.FuncType): 
+            self.addpending(type_, FuncTypeNode(self, type_))
+
+        elif isinstance(type_, lltype.Array): 
+            if type_.OF is lltype.Void:
+                self.addpending(type_, VoidArrayTypeNode(self, type_))
+            else:
+                self.addpending(type_, ArrayTypeNode(self, type_))
+
+        elif isinstance(type_, lltype.OpaqueType):
+            self.addpending(type_, OpaqueTypeNode(self, type_))            
+
+        else:
+            assert False, "need to prepare typerepr %s %s" % (type_, type(type_))
+
+    def prepare_type_multi(self, types):
+        for type_ in types:
+            self.prepare_type(type_)
+
+    def prepare_constant(self, type_, value):
+        if isinstance(type_, lltype.Primitive):
+            #log.prepareconstant(value, "(is primitive)")
+            return
+        
+        if isinstance(type_, lltype.Ptr):        
+            
+            type_ = type_.TO
+            value = value._obj
+
+            #log.prepareconstant("preparing ptr", value)
+
+            # we dont need a node for nulls
+            if value is None:
+                return
+
+        # we can share data via pointers
+        if value not in self.obj2node: 
+            self.addpending(value, self.create_constant_node(type_, value))
+
+        # always add type (it is safe)
+        self.prepare_type(type_)
+        
+    def prepare_arg_value(self, const_or_var):
+        """if const_or_var is not already in a dictionary self.obj2node,
+        the appropriate node gets constructed and gets added to
+        self._pendingsetup and to self.obj2node"""
+        if isinstance(const_or_var, Constant):
+            ct = const_or_var.concretetype
+            if isinstance(ct, lltype.Primitive):
+                #log.prepare(const_or_var, "(is primitive)")
+                return
+
+            assert isinstance(ct, lltype.Ptr), "Preparation of non primitive and non pointer" 
+            value = const_or_var.value._obj
+
+            # Only prepare root values at this point 
+            if isinstance(ct, lltype.Array) or isinstance(ct, lltype.Struct):
+                p, c = lltype.parentlink(value)
+                if p is None:
+                    #log.prepareargvalue("skipping preparing non root", value)
+                    return
+
+            if value is not None and value not in self.obj2node:
+                self.addpending(value, self.create_constant_node(ct.TO, value))
+        else:
+            assert isinstance(const_or_var, Variable)
+
+
+    def prepare_arg(self, const_or_var):
+        #log.prepare(const_or_var)
+        self.prepare_type(const_or_var.concretetype)
+        self.prepare_arg_value(const_or_var)
+
+
+    def setup_all(self):
+        while self._pendingsetup: 
+            node = self._pendingsetup.pop()
+            #log.settingup(node)
+            node.setup()
+
+    def set_entrynode(self, key):
+        self.entrynode = self.obj2node[key]    
+        return self.entrynode
+
+    def getnodes(self):
+        return self.obj2node.itervalues()
+        
+    # __________________________________________________________
+    # Representing variables and constants in LLVM source code 
+
+    def repr_arg(self, arg):
+        if isinstance(arg, Constant):
+            if isinstance(arg.concretetype, lltype.Primitive):
+                return self.primitive_to_str(arg.concretetype, arg.value)
+            else:
+                assert isinstance(arg.value, lltype._ptr)
+                node = self.obj2node.get(arg.value._obj)
+                if node is None:
+                    return 'null'
+                else:
+                    return node.get_ref()
+        else:
+            assert isinstance(arg, Variable)
+            return "%" + str(arg)
+
+    def repr_arg_type(self, arg):
+        assert isinstance(arg, (Constant, Variable))
+        ct = arg.concretetype 
+        return self.repr_type(ct)
+    
+    def repr_type(self, type_):
+        try:
+            return self.obj2node[type_].ref 
+        except KeyError: 
+            if isinstance(type_, lltype.Primitive):
+                return self.primitives[type_]
+            elif isinstance(type_, lltype.Ptr):
+                return self.repr_type(type_.TO) + '*'
+            else: 
+                raise TypeError("cannot represent %r" %(type_,))
+            
+    def repr_argwithtype(self, arg):
+        return self.repr_arg(arg), self.repr_arg_type(arg)
+            
+    def repr_arg_multi(self, args):
+        return [self.repr_arg(arg) for arg in args]
+
+    def repr_arg_type_multi(self, args):
+        return [self.repr_arg_type(arg) for arg in args]
+
+    def repr_constant(self, value):
+        " returns node and repr as tuple "
+        type_ = lltype.typeOf(value)
+        if isinstance(type_, lltype.Primitive):
+            repr = self.primitive_to_str(type_, value)
+            return None, "%s %s" % (self.repr_type(type_), repr)
+
+        elif isinstance(type_, lltype.Ptr):
+            toptr = self.repr_type(type_)
+            value = value._obj
+
+            # special case, null pointer
+            if value is None:
+                return None, "%s null" % (toptr,)
+
+            node = self.obj2node[value]
+            ref = node.get_pbcref(toptr)
+            return node, "%s %s" % (toptr, ref)
+
+        elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct):
+            node = self.obj2node[value]
+            return node, node.constantvalue()
+
+        assert False, "%s not supported" % (type(value))
+
+    def repr_tmpvar(self): 
+        count = self._tmpcount 
+        self._tmpcount += 1
+        return "%tmp." + str(count) 
+
+    def repr_constructor(self, type_):
+        return self.obj2node[type_].constructor_ref
+
+    def repr_name(self, obj):
+        return self.obj2node[obj].ref
+
+    # __________________________________________________________
+    # Primitive stuff
+
+    def float_to_str(self, value):
+        repr = "%f" % value
+        # llvm requires a . when using e notation
+        if "e" in repr and "." not in repr:
+            repr = repr.replace("e", ".0e")
+        elif repr in ["inf", "nan"]:
+            # Need hex repr
+            import struct
+            packed = struct.pack("d", value)
+            if sys.byteorder == 'little':
+                packed = packed[::-1]
+            
+            repr = "0x" + "".join([("%02x" % ord(ii)) for ii in packed])
+        return repr
+
+    def char_to_str(self, value):
+        x = ord(value)
+        if x >= 128:
+            r = "cast (ubyte %s to sbyte)" % x
+        else:
+            r = str(x)
+        return r
+    
+    def primitive_to_str(self, type_, value):
+        if type_ is lltype.Bool:
+            repr = str(value).lower() #False --> false
+        elif type_ is lltype.Char:
+            repr = self.char_to_str(value)
+        elif type_ is lltype.UniChar:
+            repr = str(ord(value))
+        elif type_ is lltype.Float:
+            repr = self.float_to_str(value)
+        else:
+            repr = str(value)
+        return repr
+
+    def get_machine_word(self):
+        return self.primitives[lltype.Signed]
+
+    def get_machine_uword(self):
+        return self.primitives[lltype.Unsigned]
+
+    # __________________________________________________________
+    # Other helpers
+
+    def is_function_ptr(self, arg):
+        if isinstance(arg, (Constant, Variable)): 
+            arg = arg.concretetype 
+            if isinstance(arg, lltype.Ptr):
+                if isinstance(arg.TO, lltype.FuncType):
+                    return True
+        return False
+
+    def get_childref(self, parent, child):
+        node = self.obj2node[parent]
+        return node.get_childref(child)

Added: pypy/dist/pypy/translator/js/exception.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/exception.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,248 @@
+from pypy.translator.llvm.codewriter import DEFAULT_CCONV
+
+
+class ExceptionPolicy:
+    RINGBUGGER_SIZE          = 8192
+    RINGBUFFER_ENTRY_MAXSIZE = 16
+    RINGBUGGER_OVERSIZE      = RINGBUGGER_SIZE + RINGBUFFER_ENTRY_MAXSIZE
+    RINGBUFFER_LLVMCODE      = '''
+internal fastcc sbyte* %%malloc_exception(uint %%nbytes) {
+    %%cond = setle uint %%nbytes, %d
+    br bool %%cond, label %%then, label %%else
+
+then:
+    %%tmp.3 = load uint* %%exception_ringbuffer_index
+    %%tmp.4 = getelementptr [%d x sbyte]* %%exception_ringbuffer, int 0, uint %%tmp.3
+    %%tmp.6 = add uint %%tmp.3, %%nbytes
+    %%tmp.7 = and uint %%tmp.6, %d
+    store uint %%tmp.7, uint* %%exception_ringbuffer_index
+    ret sbyte* %%tmp.4
+
+else:
+    %%tmp.8  = call ccc sbyte* %%GC_malloc(uint %%nbytes)
+    ret sbyte* %%tmp.8
+}
+''' % (RINGBUFFER_ENTRY_MAXSIZE, RINGBUGGER_OVERSIZE, RINGBUGGER_SIZE-1)
+
+    def __init__(self):
+        raise Exception, 'ExceptionPolicy should not be used directly'
+
+    def transform(self, translator, graph=None):
+        return
+
+    def _noresult(self, returntype):
+        r = returntype.strip()
+        if r == 'void':
+            return 'void'
+        elif r == 'bool':
+            return 'bool false'
+        elif r in 'float double'.split():
+            return r + ' 0.0'
+        elif r in 'ubyte sbyte ushort short uint int ulong long'.split():
+            return r + ' 0'
+        return r + ' null'
+
+    def _nonoderesult(self, node):
+        decl = node.getdecl()
+        returntype, name = decl.split(' ', 1)
+        noresult = self._noresult(returntype)
+        return noresult
+
+    def new(exceptionpolicy=None):  #factory
+        exceptionpolicy = exceptionpolicy or 'fast'
+        if exceptionpolicy == 'cpython':
+            from pypy.translator.llvm.exception import CPythonExceptionPolicy
+            exceptionpolicy = CPythonExceptionPolicy()
+        elif exceptionpolicy == 'fast':
+            from pypy.translator.llvm.exception import FastExceptionPolicy
+            exceptionpolicy = FastExceptionPolicy()
+        elif exceptionpolicy == 'none':
+            from pypy.translator.llvm.exception import NoneExceptionPolicy
+            exceptionpolicy = NoneExceptionPolicy()
+        else:
+            raise Exception, 'unknown exceptionpolicy: ' + str(exceptionpolicy)
+        return exceptionpolicy
+    new = staticmethod(new)
+
+
+class NoneExceptionPolicy(ExceptionPolicy): #XXX untested
+    def __init__(self):
+        pass
+
+
+class CPythonExceptionPolicy(ExceptionPolicy):  #uses issubclass() and llvm invoke&unwind
+    def __init__(self):
+        pass
+
+    def llvmcode(self, entrynode):
+        returntype, entrypointname =  entrynode.getdecl().split('%', 1)
+        noresult = self._noresult(returntype)
+        cconv = DEFAULT_CCONV
+        return '''
+ccc %(returntype)s%%__entrypoint__%(entrypointname)s {
+    %%result = invoke %(cconv)s %(returntype)s%%%(entrypointname)s to label %%no_exception except label %%exception
+
+no_exception:
+    store %%RPYTHON_EXCEPTION_VTABLE* null, %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
+    ret %(returntype)s %%result
+
+exception:
+    ret %(noresult)s
+}
+
+ccc int %%__entrypoint__raised_LLVMException() {
+    %%tmp    = load %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
+    %%result = cast %%RPYTHON_EXCEPTION_VTABLE* %%tmp to int
+    ret int %%result
+}
+
+internal fastcc void %%unwind() {
+    unwind
+}
+''' % locals() + self.RINGBUFFER_LLVMCODE
+
+    def invoke(self, codewriter, targetvar, tail_, cconv, returntype, functionref, args, label, except_label):
+        labels = 'to label %%%s except label %%%s' % (label, except_label)
+        if returntype == 'void':
+            codewriter.indent('%sinvoke %s void %s(%s) %s' % (tail_, cconv, functionref, args, labels))
+        else:
+            codewriter.indent('%s = %sinvoke %s %s %s(%s) %s' % (targetvar, tail_, cconv, returntype, functionref, args, labels))
+
+    def _is_raise_new_exception(self, db, graph, block):
+        from pypy.objspace.flow.model import mkentrymap
+        is_raise_new = False
+        entrylinks = mkentrymap(graph)[block]
+        entrylinks = [x for x in entrylinks if x.prevblock is not None]
+        inputargs = db.repr_arg_multi(block.inputargs)
+        for i, arg in enumerate(inputargs):
+            names = db.repr_arg_multi([link.args[i] for link in entrylinks])
+            for name in names:  #These tests-by-name are a bit yikes, but I don't see a better way right now
+                if not name.startswith('%last_exception_') and not name.startswith('%last_exc_value_'):
+                    is_raise_new = True
+        return is_raise_new
+
+    def write_exceptblock(self, funcnode, codewriter, block):
+        assert len(block.inputargs) == 2
+
+        db    = funcnode.db
+        graph = funcnode.graph
+
+        if self._is_raise_new_exception(db, graph, block):
+            funcnode.write_block_phi_nodes(codewriter, block)
+
+            inputargs     = db.repr_arg_multi(block.inputargs)
+            inputargtypes = db.repr_arg_type_multi(block.inputargs)
+
+            codewriter.store(inputargtypes[0], inputargs[0], '%last_exception_type')
+            codewriter.store(inputargtypes[1], inputargs[1], '%last_exception_value')
+        else:
+            codewriter.comment('reraise last exception')
+            #Reraising last_exception.
+            #Which is already stored in the global variables.
+            #So nothing needs to happen here!
+
+        codewriter.indent('unwind')
+
+    def fetch_exceptions(self, codewriter, exc_found_labels, lltype_of_exception_type, lltype_of_exception_value):
+        for label, target, last_exc_type_var, last_exc_value_var in exc_found_labels:
+            codewriter.label(label)
+            if last_exc_type_var:    
+                codewriter.load(last_exc_type_var, lltype_of_exception_type, '%last_exception_type')
+            if last_exc_value_var:   
+                codewriter.load(last_exc_value_var, lltype_of_exception_value, '%last_exception_value')
+            codewriter.br_uncond(target)
+
+    def reraise(self, funcnode, codewriter):
+        codewriter.comment('reraise when exception is not caught')
+        codewriter.indent('unwind')
+
+    def llc_options(self):
+        return '-enable-correct-eh-support'
+
+
+class FastExceptionPolicy(ExceptionPolicy):    #uses issubclass() and last_exception tests after each call
+    def __init__(self):
+        self.invoke_count = 0
+
+    def llvmcode(self, entrynode):
+        returntype, entrypointname = entrynode.getdecl().split('%', 1)
+        noresult = self._noresult(returntype)
+        cconv = DEFAULT_CCONV
+        return '''
+ccc %(returntype)s%%__entrypoint__%(entrypointname)s {
+    store %%RPYTHON_EXCEPTION_VTABLE* null, %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
+    %%result = call %(cconv)s %(returntype)s%%%(entrypointname)s
+    %%tmp    = load %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
+    %%exc    = seteq %%RPYTHON_EXCEPTION_VTABLE* %%tmp, null
+    br bool %%exc, label %%no_exception, label %%exception
+
+no_exception:
+    ret %(returntype)s %%result
+
+exception:
+    ret %(noresult)s
+}
+
+ccc int %%__entrypoint__raised_LLVMException() {
+    %%tmp    = load %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
+    %%result = cast %%RPYTHON_EXCEPTION_VTABLE* %%tmp to int
+    ret int %%result
+}
+
+internal fastcc void %%unwind() {
+    ret void
+}
+''' % locals() + self.RINGBUFFER_LLVMCODE
+
+    def transform(self, translator, graph=None):
+        from pypy.translator.llvm.backendopt.exception import create_exception_handling
+        if graph:
+            create_exception_handling(translator, graph)
+        else:
+            for graph in translator.flowgraphs.itervalues():
+                create_exception_handling(translator, graph)
+            #translator.view()
+
+    def invoke(self, codewriter, targetvar, tail_, cconv, returntype, functionref, args, label, except_label):
+        if returntype == 'void':
+            codewriter.indent('%scall %s void %s(%s)' % (tail_, cconv, functionref, args))
+        else:
+            codewriter.indent('%s = %scall %s %s %s(%s)' % (targetvar, tail_, cconv, returntype, functionref, args))
+        tmp = '%%invoke.tmp.%d' % self.invoke_count
+        exc = '%%invoke.exc.%d' % self.invoke_count
+        self.invoke_count += 1
+        codewriter.indent('%(tmp)s = load %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type' % locals())
+        codewriter.indent('%(exc)s = seteq %%RPYTHON_EXCEPTION_VTABLE* %(tmp)s, null'         % locals())
+        codewriter.indent('br bool %(exc)s, label %%%(label)s, label %%%(except_label)s'      % locals())
+
+    def write_exceptblock(self, funcnode, codewriter, block):
+        assert len(block.inputargs) == 2
+
+        noresult = self._nonoderesult(funcnode)
+
+        funcnode.write_block_phi_nodes(codewriter, block)
+
+        inputargs     = funcnode.db.repr_arg_multi(block.inputargs)
+        inputargtypes = funcnode.db.repr_arg_type_multi(block.inputargs)
+
+        codewriter.store(inputargtypes[0], inputargs[0], '%last_exception_type')
+        codewriter.store(inputargtypes[1], inputargs[1], '%last_exception_value')
+        codewriter.indent('ret ' + noresult)
+
+    def fetch_exceptions(self, codewriter, exc_found_labels, lltype_of_exception_type, lltype_of_exception_value):
+        for label, target, last_exc_type_var, last_exc_value_var in exc_found_labels:
+            codewriter.label(label)
+            if last_exc_type_var:    
+                codewriter.load(last_exc_type_var, lltype_of_exception_type, '%last_exception_type')
+            if last_exc_value_var:   
+                codewriter.load(last_exc_value_var, lltype_of_exception_value, '%last_exception_value')
+            codewriter.store(lltype_of_exception_type , 'null', '%last_exception_type')
+            codewriter.store(lltype_of_exception_value, 'null', '%last_exception_value')
+            codewriter.br_uncond(target)
+
+    def reraise(self, funcnode, codewriter):
+        noresult = self._nonoderesult(funcnode)
+        codewriter.indent('ret ' + noresult)
+
+    def llc_options(self):
+        return ''

Added: pypy/dist/pypy/translator/js/extfuncnode.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/extfuncnode.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,30 @@
+import py
+from pypy.translator.llvm.node import ConstantLLVMNode
+from pypy.translator.llvm.log import log 
+log = log.extfuncnode
+
+class ExternalFuncNode(ConstantLLVMNode):
+    used_external_functions = {}
+
+    def __init__(self, db, value):
+        self.db = db
+        self.value = value
+        name = value._callable.__name__
+        assert name.startswith("ll")
+        name = "LL" + name[2:] 
+        self.ref = self.make_ref("%", name)
+        self.used_external_functions[self.ref] = True
+
+    def getdecl(self):
+        T = self.value._TYPE
+        args = [self.db.repr_type(a) for a in T.ARGS]
+        decl = "%s %s(%s)" % (self.db.repr_type(T.RESULT),
+                              self.ref,
+                              ", ".join(args))
+        return decl
+
+    def writedecl(self, codewriter): 
+        codewriter.declare(self.getdecl())
+
+    def writeglobalconstants(self, codewriter):
+        pass

Added: pypy/dist/pypy/translator/js/funcnode.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/funcnode.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,217 @@
+import py
+import sys
+from pypy.objspace.flow.model import Block, Constant, Variable, Link
+from pypy.objspace.flow.model import flatten, mkentrymap, traverse, last_exception
+from pypy.rpython import lltype
+from pypy.translator.llvm.node import LLVMNode, ConstantLLVMNode
+from pypy.translator.llvm.opwriter import OpWriter
+from pypy.translator.llvm.log import log 
+from pypy.translator.llvm.backendopt.removeexcmallocs import remove_exception_mallocs
+from pypy.translator.llvm.backendopt.mergemallocs import merge_mallocs
+from pypy.translator.unsimplify import remove_double_links
+log = log.funcnode
+
+class FuncTypeNode(LLVMNode):
+    __slots__ = "db type_ ref".split()
+    
+    def __init__(self, db, type_):
+        self.db = db
+        assert isinstance(type_, lltype.FuncType)
+        self.type_ = type_
+        self.ref = self.make_ref('%functiontype', '')
+
+    def __str__(self):
+        return "<FuncTypeNode %r>" % self.ref
+
+    def setup(self):
+        self.db.prepare_type(self.type_.RESULT)
+        self.db.prepare_type_multi(self.type_._trueargs())
+
+    def writedatatypedecl(self, codewriter):
+        returntype = self.db.repr_type(self.type_.RESULT)
+        inputargtypes = [self.db.repr_type(a) for a in self.type_._trueargs()]
+        codewriter.funcdef(self.ref, returntype, inputargtypes)
+
+class FuncNode(ConstantLLVMNode):
+    __slots__ = "db value ref graph block_to_name".split()
+
+    def __init__(self, db, value):
+        self.db = db
+        self.value = value
+        self.ref   = self.make_ref('%pypy_', value.graph.name)
+        self.graph = value.graph
+
+        self.db.genllvm.exceptionpolicy.transform(self.db.translator, self.graph)
+        remove_exception_mallocs(self.db.translator, self.graph, self.ref)
+        #merge_mallocs(self.db.translator, self.graph, self.ref)
+
+        remove_double_links(self.db.translator, self.graph)
+
+    def __str__(self):
+        return "<FuncNode %r>" %(self.ref,)
+    
+    def setup(self):
+        #log("setup", self)
+        def visit(node):
+            if isinstance(node, Link):
+                map(self.db.prepare_arg, node.args)
+            elif isinstance(node, Block):
+                block = node
+                map(self.db.prepare_arg, block.inputargs)
+                for op in block.operations:
+                    map(self.db.prepare_arg, op.args)
+                    self.db.prepare_arg(op.result)
+                    if block.exitswitch != Constant(last_exception):
+                        continue
+                    for link in block.exits[1:]:
+                        self.db.prepare_constant(lltype.typeOf(link.llexitcase),
+                                                 link.llexitcase)
+                                            
+        assert self.graph, "cannot traverse"
+        traverse(visit, self.graph)
+
+    # ______________________________________________________________________
+    # main entry points from genllvm 
+    def writedecl(self, codewriter): 
+        codewriter.declare(self.getdecl())
+
+    def writeimpl(self, codewriter):
+        graph = self.graph
+        log.writeimpl(graph.name)
+        codewriter.openfunc(self.getdecl(), self is self.db.entrynode)
+        nextblock = graph.startblock
+        args = graph.startblock.inputargs 
+        l = [x for x in flatten(graph) if isinstance(x, Block)]
+        self.block_to_name = {}
+        for i, block in enumerate(l):
+            self.block_to_name[block] = "block%s" % i
+        for block in l:
+            codewriter.label(self.block_to_name[block])
+            for name in 'startblock returnblock exceptblock'.split():
+                if block is getattr(graph, name):
+                    getattr(self, 'write_' + name)(codewriter, block)
+                    break
+            else:
+                self.write_block(codewriter, block)
+        codewriter.closefunc()
+
+    def writecomments(self, codewriter):
+        """ write operations strings for debugging purposes. """ 
+        blocks = [x for x in flatten(self.graph) if isinstance(x, Block)]
+        for block in blocks:
+            for op in block.operations:
+                strop = str(op) + "\n\x00"
+                l = len(strop)
+                if strop.find("direct_call") == -1:
+                    continue
+                tempname = self.db.add_op2comment(l, op)
+                printables = dict([(ord(i), None) for i in
+                                   ("0123456789abcdefghijklmnopqrstuvwxyz" +
+                                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+                                    "!#$%&()*+,-./:;<=>?@[\\]^_`{|}~ '")])
+                s = []
+                for c in strop:
+                    if ord(c) in printables:
+                        s.append(c)
+                    else:
+                        s.append("\\%02x" % ord(c))
+                r = 'c"%s"' % "".join(s)
+                typeandata = '[%s x sbyte] %s' % (l, r)
+                codewriter.globalinstance(tempname, typeandata)
+
+    def writeglobalconstants(self, codewriter):
+        pass
+    
+    # ______________________________________________________________________
+    # writing helpers for entry points
+
+    def getdecl(self):
+        startblock = self.graph.startblock
+        returnblock = self.graph.returnblock
+        startblock_inputargs = [a for a in startblock.inputargs
+                                if a.concretetype is not lltype.Void]
+
+        inputargs = self.db.repr_arg_multi(startblock_inputargs)
+        inputargtypes = self.db.repr_arg_type_multi(startblock_inputargs)
+        returntype = self.db.repr_arg_type(self.graph.returnblock.inputargs[0])
+        result = "%s %s" % (returntype, self.ref)
+        args = ["%s %s" % item for item in zip(inputargtypes, inputargs)]
+        result += "(%s)" % ", ".join(args)
+        return result 
+
+    def write_block(self, codewriter, block):
+        self.write_block_phi_nodes(codewriter, block)
+        self.write_block_operations(codewriter, block)
+        self.write_block_branches(codewriter, block)
+
+    def get_phi_data(self, block):
+        data = []
+        entrylinks = mkentrymap(self.graph)[block]
+        entrylinks = [x for x in entrylinks if x.prevblock is not None]
+        inputargs = self.db.repr_arg_multi(block.inputargs)
+        inputargtypes = self.db.repr_arg_type_multi(block.inputargs)
+        for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)):
+            names = self.db.repr_arg_multi([link.args[i] for link in entrylinks])
+            blocknames = [self.block_to_name[link.prevblock]
+                              for link in entrylinks]
+            for i, link in enumerate(entrylinks):   #XXX refactor into a transformation
+                if link.prevblock.exitswitch == Constant(last_exception) and \
+                   link.prevblock.exits[0].target != block:
+                    blocknames[i] += '_exception_found_branchto_' + self.block_to_name[block]
+            data.append( (arg, type_, names, blocknames) )
+        return data
+
+    def write_block_phi_nodes(self, codewriter, block):
+        for arg, type_, names, blocknames in self.get_phi_data(block):
+            if type_ != "void":
+                codewriter.phi(arg, type_, names, blocknames)
+
+    def write_block_branches(self, codewriter, block):
+        #assert len(block.exits) <= 2    #more exits are possible (esp. in combination with exceptions)
+        if block.exitswitch == Constant(last_exception):
+            #codewriter.comment('FuncNode(ConstantLLVMNode) *last_exception* write_block_branches @%s@' % str(block.exits))
+            return
+        if len(block.exits) == 1:
+            codewriter.br_uncond(self.block_to_name[block.exits[0].target])
+        elif len(block.exits) == 2:
+            cond = self.db.repr_arg(block.exitswitch)
+            codewriter.br(cond, self.block_to_name[block.exits[0].target],
+                          self.block_to_name[block.exits[1].target])
+
+    def write_block_operations(self, codewriter, block):
+        opwriter = OpWriter(self.db, codewriter, self, block)
+        if block.exitswitch == Constant(last_exception):
+            last_op_index = len(block.operations) - 1
+        else:
+            last_op_index = None
+        for op_index, op in enumerate(block.operations):
+            if False:   # print out debug string
+                codewriter.newline()
+                codewriter.comment("** %s **" % str(op))
+                info = self.db.get_op2comment(op)
+                if info is not None:
+                    lenofopstr, opstrname = info
+                    codewriter.debugcomment(self.db.repr_tmpvar(),
+                                            lenofopstr,
+                                            opstrname)
+            if op_index == last_op_index:
+                #could raise an exception and should therefor have a function
+                #implementation that can be invoked by the llvm-code.
+                invoke_prefix = 'invoke:'
+                assert not op.opname.startswith(invoke_prefix)
+                op.opname = invoke_prefix + op.opname
+            opwriter.write_operation(op)
+
+    def write_startblock(self, codewriter, block):
+        self.write_block_operations(codewriter, block)
+        self.write_block_branches(codewriter, block)
+
+    def write_returnblock(self, codewriter, block):
+        assert len(block.inputargs) == 1
+        self.write_block_phi_nodes(codewriter, block)
+        inputargtype = self.db.repr_arg_type(block.inputargs[0])
+        inputarg = self.db.repr_arg(block.inputargs[0])
+        codewriter.ret(inputargtype, inputarg)
+
+    def write_exceptblock(self, codewriter, block):
+        self.db.genllvm.exceptionpolicy.write_exceptblock(self, codewriter, block)

Added: pypy/dist/pypy/translator/js/gc.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/gc.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,95 @@
+import py
+from pypy.tool.ansi_print import ansi_log
+log = py.log.Producer("llvm")
+log.setconsumer("llvm", ansi_log)
+
+
+class GcPolicy:
+    def __init__(self):
+        raise Exception, 'GcPolicy should not be used directly'
+
+    def gc_libraries(self):
+        return []
+
+    def declarations(self):
+        return ''
+
+    def malloc(self, targetvar, type_, size, is_atomic, word, uword):
+        s = str(size)
+        return '%(targetvar)s = malloc %(type_)s, uint %(s)s' % locals()
+
+    def pyrex_code(self):
+        return ''
+
+    def new(gcpolicy=None):  #factory
+        gcpolicy = gcpolicy or 'boehm'
+        
+        from os.path import exists
+        boehm_on_path = exists('/usr/lib/libgc.so') or exists('/usr/lib/libgc.a')
+        if gcpolicy == 'boehm' and not boehm_on_path:
+            log.gc.WARNING('warning: Boehm GC libary not found in /usr/lib, falling back on no gc')
+            gcpolicy = 'none'
+
+        if gcpolicy == 'boehm':
+            from pypy.translator.llvm.gc import BoehmGcPolicy
+            gcpolicy = BoehmGcPolicy()
+        elif gcpolicy == 'ref':
+            from pypy.translator.llvm.gc import RefcountingGcPolicy
+            gcpolicy = RefcountingGcPolicy()
+        elif gcpolicy == 'none':
+            from pypy.translator.llvm.gc import NoneGcPolicy
+            gcpolicy = NoneGcPolicy()
+        else:
+            raise Exception, 'unknown gcpolicy: ' + str(gcpolicy)
+        return gcpolicy
+    new = staticmethod(new)
+
+
+class NoneGcPolicy(GcPolicy):
+    def __init__(self):
+        pass
+
+
+class BoehmGcPolicy(GcPolicy):
+    def __init__(self):
+        self.n_malloced = 0
+
+    def gc_libraries(self):
+        return ['gc'] # xxx on windows?
+
+    def declarations(self):
+        return '''
+declare ccc sbyte* %GC_malloc(uint)
+declare ccc sbyte* %GC_malloc_atomic(uint)
+%GC_all_interior_pointers = external global int
+'''
+
+    def malloc(self, targetvar, type_, size, is_atomic, word, uword):
+        s = str(size)
+        self.n_malloced += 1
+        cnt = '.%d' % self.n_malloced
+        atomic = is_atomic and '_atomic' or ''
+        t = '''
+%%malloc.Size%(cnt)s  = getelementptr %(type_)s* null, %(uword)s %(s)s
+%%malloc.SizeU%(cnt)s = cast %(type_)s* %%malloc.Size%(cnt)s to %(uword)s
+%%malloc.Ptr%(cnt)s   = call ccc sbyte* %%GC_malloc%(atomic)s(%(uword)s %%malloc.SizeU%(cnt)s)
+%(targetvar)s = cast sbyte* %%malloc.Ptr%(cnt)s to %(type_)s*
+''' % locals()
+        if is_atomic:
+            t += '''
+call ccc void %%llvm.memset(sbyte* %%malloc.Ptr%(cnt)s, ubyte 0, uint %%malloc.SizeU%(cnt)s, uint 0)
+''' % locals()
+        return t
+
+    def pyrex_code(self):
+        return '''
+cdef extern int GC_get_heap_size()
+
+def GC_get_heap_size_wrapper():
+    return GC_get_heap_size()
+'''
+
+
+class RefcountingGcPolicy(GcPolicy):
+    def __init__(self):
+        raise NotImplementedError, 'RefcountingGcPolicy'

Added: pypy/dist/pypy/translator/js/js.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/js.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,152 @@
+'''
+reference material:
+    http://webreference.com/javascript/reference/core_ref/
+    http://webreference.com/programming/javascript/
+    http://mochikit.com/
+    
+'''
+
+#import os
+#import time
+#import types
+#import urllib
+
+import py
+
+#from pypy.translator.llvm import build_llvm_module
+from pypy.translator.llvm.database import Database 
+#from pypy.translator.llvm.pyxwrapper import write_pyx_wrapper 
+from pypy.rpython.rmodel import inputconst, getfunctionptr
+from pypy.rpython import lltype
+from pypy.tool.udir import udir
+from pypy.translator.llvm.codewriter import CodeWriter
+#from pypy.translator.llvm.codewriter import , DEFAULT_TAIL, DEFAULT_CCONV
+#from pypy.translator.llvm import extfuncnode
+#from pypy.translator.llvm.module.extfunction import extdeclarations, extfunctions, dependencies
+#from pypy.translator.llvm.node import JSNode
+#from pypy.translator.llvm.structnode import StructNode
+#from pypy.translator.llvm.externs2ll import post_setup_externs, generate_llfile
+from pypy.translator.llvm.gc import GcPolicy
+from pypy.translator.llvm.exception import ExceptionPolicy
+#from pypy.translator.translator import Translator
+
+from pypy.translator.js.log import log
+
+function_count = {}
+#llexterns_header = llexterns_functions = None
+
+
+class JS(object):   # JS = Javascript
+
+    def __init__(self, translator, func=None, gcpolicy=None, exceptionpolicy=None, debug=False):
+        self.db = Database(self, translator)
+        self.translator = translator
+        self.gcpolicy = GcPolicy.new(gcpolicy)
+        self.exceptionpolicy = ExceptionPolicy.new(exceptionpolicy)
+        #extfuncnode.ExternalFuncNode.used_external_functions = {}
+        self.debug = debug # for debug we create comments of every operation that may be executed
+        if debug:
+            translator.checkgraphs()
+
+        if func is None:
+            func = self.translator.entrypoint
+        self.entrypoint = func
+
+        ptr = getfunctionptr(self.translator, func)
+        c = inputconst(lltype.typeOf(ptr), ptr)
+        entry_point = c.value._obj
+        self.db.prepare_arg_value(c)
+
+        # set up all nodes
+        self.db.setup_all()
+        self.entrynode = self.db.set_entrynode(entry_point)
+        entryfunc_name = self.entrynode.getdecl().split('%', 1)[1].split('(')[0]
+
+        ## post set up externs
+        #extern_decls = post_setup_externs(self.db)
+        #self.translator.rtyper.specialize_more_blocks()
+        #self.db.setup_all()
+        #using_external_functions = extfuncnode.ExternalFuncNode.used_external_functions.keys() != []
+        #
+        #support_functions = "%raisePyExc_IOError %raisePyExc_ValueError "\
+        #                    "%raisePyExc_OverflowError %raisePyExc_ZeroDivisionError "\
+        #                    "%prepare_ZeroDivisionError %prepare_OverflowError %prepare_ValueError "\
+        #                    "%RPyString_FromString %RPyString_AsString %RPyString_Size".split()
+        #
+        #global llexterns_header, llexterns_functions
+        #if llexterns_header is None and using_external_functions:
+        #    llexterns_header, llexterns_functions = generate_llfile(self.db, extern_decls, support_functions, self.debug)
+ 
+        # prevent running the same function twice in a test
+        if func.func_name in function_count:
+            postfix = '_%d' % function_count[func.func_name]
+            function_count[func.func_name] += 1
+        else:
+            postfix = ''
+            function_count[func.func_name] = 1
+        filename = udir.join(func.func_name + postfix).new(ext='.js')
+        f = open(str(filename),'w')
+        codewriter = CodeWriter(f, self)
+        comment = codewriter.comment
+        nl = codewriter.newline
+
+        #if using_external_functions:
+        #    nl(); comment("External Function Declarations") ; nl()
+        #    codewriter.append(llexterns_header)
+
+        nl(); comment("Type Declarations"); nl()
+        #for c_name, obj in extern_decls:
+        #    if isinstance(obj, lltype.LowLevelType):
+        #        if isinstance(obj, lltype.Ptr):
+        #            obj = obj.TO
+        #        l = "%%%s = type %s" % (c_name, self.db.repr_type(obj))
+        #        codewriter.append(l)
+
+        for typ_decl in self.db.getnodes():
+            typ_decl.writedatatypedecl(codewriter)
+
+        nl(); comment("Global Data") ; nl()
+        for typ_decl in self.db.getnodes():
+            typ_decl.writeglobalconstants(codewriter)
+
+        nl(); comment("Function Prototypes") ; nl()
+        #codewriter.append(extdeclarations)
+        #codewriter.append(self.gcpolicy.declarations())
+
+        for typ_decl in self.db.getnodes():
+            typ_decl.writedecl(codewriter)
+
+        nl(); comment("Function Implementation") 
+        codewriter.startimpl()
+        
+        for typ_decl in self.db.getnodes():
+            typ_decl.writeimpl(codewriter)
+
+        #codewriter.append(self.exceptionpolicy.llvmcode(self.entrynode))
+        #
+        ## XXX we need to create our own main() that calls the actual entry_point function
+        #if entryfunc_name == 'pypy_entry_point': #XXX just to get on with translate_pypy
+        #    extfuncnode.ExternalFuncNode.used_external_functions['%main'] = True
+        #
+        #elif entryfunc_name == 'pypy_main_noargs': #XXX just to get on with bpnn & richards
+        #    extfuncnode.ExternalFuncNode.used_external_functions['%main_noargs'] = True
+        #
+        #for f in support_functions:
+        #    extfuncnode.ExternalFuncNode.used_external_functions[f] = True
+        #
+        #depdone = {}
+        #for funcname,value in extfuncnode.ExternalFuncNode.used_external_functions.iteritems():
+        #    deps = dependencies(funcname,[])
+        #    deps.reverse()
+        #    for dep in deps:
+        #        if dep not in depdone:
+        #            if dep in extfunctions: #else external function that is shared with genc
+        #                codewriter.append(extfunctions[dep][1])
+        #            depdone[dep] = True
+        #
+        #if using_external_functions:
+        #    nl(); comment("External Function Implementation") ; nl()
+        #    codewriter.append(llexterns_functions)
+
+        comment("End of file") ; nl()
+        self.filename = filename

Added: pypy/dist/pypy/translator/js/log.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/log.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,4 @@
+import py
+from pypy.tool.ansi_print import ansi_log
+log = py.log.Producer("js")
+log.setconsumer("js", ansi_log)

Added: pypy/dist/pypy/translator/js/node.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/node.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,67 @@
+from pypy.rpython import lltype
+
+class LLVMNode(object):
+    __slots__ = "".split()
+
+    nodename_count = {}
+
+    def make_name(self, name):
+        " helper for creating names"
+        if " " in name or "<" in name: 
+            name = '"%s"' % name
+            
+        if name in self.nodename_count:
+            postfix = '.%d' % self.nodename_count[name]
+            self.nodename_count[name] += 1
+        else:
+            postfix = ''
+            self.nodename_count[name] = 1
+        return name + postfix
+
+    def make_ref(self, prefix, name):
+        return self.make_name(prefix + name)
+
+    def setup(self):
+        pass
+
+    # __________________ before "implementation" ____________________
+    def writedatatypedecl(self, codewriter):
+        """ write out declare names of data types 
+            (structs/arrays/function pointers)
+        """
+
+    def writeglobalconstants(self, codewriter):
+        """ write out global values.  """
+
+    def writedecl(self, codewriter):
+        """ write function forward declarations. """ 
+
+    def writecomments(self, codewriter):
+        """ write operations strings for debugging purposes. """ 
+
+    # __________________ after "implementation" ____________________
+    def writeimpl(self, codewriter):
+        """ write function implementations. """ 
+
+class ConstantLLVMNode(LLVMNode):
+    __slots__ = "".split()
+
+    def get_ref(self):
+        """ Returns a reference as used for operations in blocks. """        
+        return self.ref
+
+    def get_pbcref(self, toptr):
+        """ Returns a reference as a pointer used per pbc. """        
+        return self.ref
+
+    def constantvalue(self):
+        """ Returns the constant representation for this node. """
+        raise AttributeError("Must be implemented in subclass")
+
+    # ______________________________________________________________________
+    # entry points from genllvm
+
+    def writeglobalconstants(self, codewriter):
+        p, c = lltype.parentlink(self.value)
+        if p is None:
+            codewriter.globalinstance(self.ref, self.constantvalue())

Added: pypy/dist/pypy/translator/js/opaquenode.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/opaquenode.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,33 @@
+from pypy.translator.llvm.node import LLVMNode, ConstantLLVMNode
+from pypy.rpython import lltype
+
+class OpaqueTypeNode(LLVMNode):
+
+    def __init__(self, db, opaquetype): 
+        assert isinstance(opaquetype, lltype.OpaqueType)
+        self.db = db
+        self.opaquetype = opaquetype
+        self.ref = "%%opaquetype.%s" % (opaquetype.tag)
+        
+    def __str__(self):
+        return "<OpaqueNode %r>" %(self.ref,)
+
+    # ______________________________________________________________________
+    # main entry points from genllvm 
+
+    def writedatatypedecl(self, codewriter):
+        # XXX Dummy - not sure what what we want
+        codewriter.funcdef(self.ref, 'sbyte*', ['sbyte *'])
+
+
+class OpaqueNode(ConstantLLVMNode):
+    def __init__(self, db, value):
+        self.db = db
+        self.value = value
+        self.ref = "null"
+    # ______________________________________________________________________
+    # main entry points from genllvm 
+
+    def writeglobalconstants(self, codewriter):
+        # XXX Dummy - not sure what what we want
+        pass

Added: pypy/dist/pypy/translator/js/opwriter.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/opwriter.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,514 @@
+import py
+from pypy.objspace.flow.model import Constant
+from pypy.rpython import lltype
+from pypy.translator.llvm.module.extfunction import extfunctions
+from pypy.translator.llvm.extfuncnode import ExternalFuncNode
+from pypy.translator.llvm.log import log 
+log = log.opwriter
+
+class OpWriter(object):
+    binary_operations = {'int_mul': 'mul',
+                         'int_add': 'add',
+                         'int_sub': 'sub',
+                         'int_floordiv': 'div',
+                         'int_mod': 'rem',
+                         'int_and': 'and',
+                         'int_or': 'or',
+                         'int_xor': 'xor',
+                         'int_lt': 'setlt',
+                         'int_le': 'setle',
+                         'int_eq': 'seteq',
+                         'int_ne': 'setne',
+                         'int_ge': 'setge',
+                         'int_gt': 'setgt',
+
+                         'uint_mul': 'mul',
+                         'uint_add': 'add',
+                         'uint_sub': 'sub',
+                         'uint_floordiv': 'div',
+                         'uint_mod': 'rem',
+                         'uint_and': 'and',
+                         'uint_or': 'or',
+                         'uint_xor': 'xor',
+                         'uint_lt': 'setlt',
+                         'uint_le': 'setle',
+                         'uint_eq': 'seteq',
+                         'uint_ne': 'setne',
+                         'uint_ge': 'setge',
+                         'uint_gt': 'setgt',
+
+                         'unichar_lt': 'setlt',
+                         'unichar_le': 'setle',
+                         'unichar_eq': 'seteq',
+                         'unichar_ne': 'setne',
+                         'unichar_ge': 'setge',
+                         'unichar_gt': 'setgt',
+
+                         'float_mul': 'mul',
+                         'float_add': 'add',
+                         'float_sub': 'sub',
+                         'float_truediv': 'div',
+                         'float_mod': 'rem',
+                         'float_lt': 'setlt',
+                         'float_le': 'setle',
+                         'float_eq': 'seteq',
+                         'float_ne': 'setne',
+                         'float_ge': 'setge',
+                         'float_gt': 'setgt',
+
+                         'ptr_eq': 'seteq',
+                         'ptr_ne': 'setne',
+                         }
+
+    shift_operations  = {'int_lshift': 'shl',
+                         'int_rshift': 'shr',
+
+                         'uint_lshift': 'shl',
+                         'uint_rshift': 'shr',
+                         }
+
+
+    char_operations  = {'char_lt': 'setlt',
+                        'char_le': 'setle',
+                        'char_eq': 'seteq',
+                        'char_ne': 'setne',
+                        'char_ge': 'setge',
+                        'char_gt': 'setgt'}
+
+    def __init__(self, db, codewriter, node, block):
+        self.db = db
+        self.codewriter = codewriter
+        self.node = node
+        self.block = block
+
+    def write_operation(self, op):
+        invoke = op.opname.startswith('invoke:')
+        if invoke:
+            self.invoke(op)
+        else:
+            if op.opname in self.binary_operations:
+                self.binaryop(op)
+            elif op.opname in self.shift_operations:
+                self.shiftop(op)
+            elif op.opname in self.char_operations:
+                self.char_binaryop(op)
+            elif op.opname.startswith('cast_'):
+                if op.opname == 'cast_char_to_int':
+                    self.cast_char_to_int(op)
+                else:
+                    self.cast_primitive(op)
+            else:
+                meth = getattr(self, op.opname, None)
+                if not meth:
+                    raise Exception, "operation %s not found" % op.opname
+                    return
+                meth(op)    
+
+    def _generic_pow(self, op, onestr): 
+        mult_type = self.db.repr_arg_type(op.args[0])
+        mult_val = self.db.repr_arg(op.args[0])
+        last_val = mult_val
+        try:
+            value = "NO VALUE"
+            value = op.args[1].value
+            operand = int(value)
+        except Exception, exc:
+            msg = 'XXX: Error: _generic_pow: Variable '\
+                  '%s - failed to convert to int %s' % (value, str(exc))
+            self.codewriter.comment(msg)
+            return
+        if operand < 1:
+            res_val = onestr
+        else:
+            res_val = mult_val
+            for ii in range(operand - 1):
+                res_val = self.db.repr_tmpvar()
+                self.codewriter.binaryop("mul", 
+                                         res_val,
+                                         mult_type,
+                                         last_val,
+                                         mult_val)
+                last_val = res_val
+        targetvar = self.db.repr_arg(op.result)
+        self.codewriter.cast(targetvar, mult_type, res_val, mult_type)        
+
+    def int_abs(self, op):
+        functionref = '%' + op.opname
+        ExternalFuncNode.used_external_functions[functionref] = True
+        self.codewriter.call(self.db.repr_arg(op.result),
+                             self.db.repr_arg_type(op.result),
+                             functionref,
+                             [self.db.repr_arg(op.args[0])],
+                             [self.db.repr_arg_type(op.args[0])])
+    float_abs = int_abs
+
+    def int_pow(self, op):
+        self._generic_pow(op, "1") 
+    uint_pow = int_pow
+    
+    def float_pow(self, op):
+        self._generic_pow(op, "1.0") 
+
+    def _generic_neg(self, op, zerostr): 
+        self.codewriter.binaryop("sub", 
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 zerostr, 
+                                 self.db.repr_arg(op.args[0]),
+                                 )
+    def int_neg(self, op):
+        self._generic_neg(op, "0")
+
+    #this is really generated, don't know why
+    # XXX rxe: Surely that cant be right?
+    uint_neg = int_neg
+
+    def float_neg(self, op):
+        self._generic_neg(op, "0.0") 
+
+    def bool_not(self, op):
+        self.codewriter.binaryop("xor",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]), 
+                                 "true")
+
+    def int_invert(self, op):
+        self.codewriter.binaryop("xor",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]), 
+                                 -1)
+
+    def uint_invert(self, op):
+        self.codewriter.binaryop("xor",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]), 
+                                 str((1L<<32) - 1))
+
+    def binaryop(self, op):
+        name = self.binary_operations[op.opname]
+        assert len(op.args) == 2
+        self.codewriter.binaryop(name,
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]),
+                                 self.db.repr_arg(op.args[1]))
+
+    def char_binaryop(self, op):
+        name = self.char_operations[op.opname]
+        assert len(op.args) == 2
+        res = self.db.repr_arg(op.result)
+        c1 = self.db.repr_tmpvar()
+        c2 = self.db.repr_tmpvar()
+        self.codewriter.cast(c1, "sbyte", self.db.repr_arg(op.args[0]), "ubyte")
+        self.codewriter.cast(c2, "sbyte", self.db.repr_arg(op.args[1]), "ubyte")
+        self.codewriter.binaryop(name, res, "ubyte", c1, c2)
+
+
+    def shiftop(self, op):
+        name = self.shift_operations[op.opname]
+        assert len(op.args) == 2
+        if isinstance(op.args[1], Constant):
+            tmpvar = self.db.repr_arg(op.args[1])
+        else:
+            tmpvar = self.db.repr_tmpvar()
+            self.codewriter.cast(tmpvar, self.db.repr_arg_type(op.args[1]), self.db.repr_arg(op.args[1]), 'ubyte')
+        self.codewriter.shiftop(name,
+                                self.db.repr_arg(op.result),
+                                self.db.repr_arg_type(op.args[0]),
+                                self.db.repr_arg(op.args[0]),
+                                tmpvar)
+
+    def cast_char_to_int(self, op):
+        " works for all casts "
+        assert len(op.args) == 1
+        targetvar = self.db.repr_arg(op.result)
+        targettype = self.db.repr_arg_type(op.result)
+        fromvar = self.db.repr_arg(op.args[0])
+        fromtype = self.db.repr_arg_type(op.args[0])
+        intermediate = self.db.repr_tmpvar()
+        self.codewriter.cast(intermediate, fromtype, fromvar, "ubyte")
+        self.codewriter.cast(targetvar, "ubyte", intermediate, targettype)
+
+    def cast_primitive(self, op):
+        " works for all casts "
+        assert len(op.args) == 1
+        targetvar = self.db.repr_arg(op.result)
+        targettype = self.db.repr_arg_type(op.result)
+        fromvar = self.db.repr_arg(op.args[0])
+        fromtype = self.db.repr_arg_type(op.args[0])
+        self.codewriter.cast(targetvar, fromtype, fromvar, targettype)
+    same_as = cast_primitive
+
+    def int_is_true(self, op):
+        self.codewriter.binaryop("setne",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]),
+                                 "0")
+    uint_is_true = int_is_true
+
+    def float_is_true(self, op):
+        self.codewriter.binaryop("setne",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]),
+                                 "0.0")
+
+    def ptr_nonzero(self, op):
+        self.codewriter.binaryop("setne",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]),
+                                 "null")
+
+    def ptr_iszero(self, op):
+        self.codewriter.binaryop("seteq",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]),
+                                 "null")
+
+    def direct_call(self, op):
+        op_args = [arg for arg in op.args
+                   if arg.concretetype is not lltype.Void]
+        assert len(op_args) >= 1
+        targetvar = self.db.repr_arg(op.result)
+        returntype = self.db.repr_arg_type(op.result)
+        functionref = self.db.repr_arg(op_args[0])
+        argrefs = self.db.repr_arg_multi(op_args[1:])
+        argtypes = self.db.repr_arg_type_multi(op_args[1:])
+        if self.db.is_function_ptr(op.result):
+            returntype = "%s (%s)*" % (returntype, ", ".join(argtypes))
+        self.codewriter.call(targetvar,returntype,functionref,argrefs,argtypes)
+
+    def last_exception_type_ptr(self, op):
+        e = self.db.translator.rtyper.getexceptiondata()
+        lltype_of_exception_type = ('%structtype.' + e.lltype_of_exception_type.TO.__name__ + '*')
+        self.codewriter.load('%'+str(op.result), lltype_of_exception_type, '%last_exception_type')
+
+    def invoke(self, op):
+        op_args = [arg for arg in op.args
+                   if arg.concretetype is not lltype.Void]
+
+        if op.opname == 'invoke:direct_call':
+            functionref = self.db.repr_arg(op_args[0])
+        else:   #operation
+            opname = op.opname.split(':',1)[1]
+            op_args = ['%' + opname] + op_args
+            functionref = op_args[0]
+            if functionref in extfunctions:
+                ExternalFuncNode.used_external_functions[functionref] = True
+            else:
+                msg = "exception raising operation %s not found" %(op.opname,)
+                self.codewriter.comment('XXX: Error: ' + msg)
+                # XXX commented out for testing
+                #assert functionref in extfunctions, msg
+        
+        assert len(op_args) >= 1
+        # at least one label and one exception label
+        assert len(self.block.exits) >= 2   
+
+        link = self.block.exits[0]
+        assert link.exitcase is None
+
+        targetvar   = self.db.repr_arg(op.result)
+        returntype  = self.db.repr_arg_type(op.result)
+        argrefs     = self.db.repr_arg_multi(op_args[1:])
+        argtypes    = self.db.repr_arg_type_multi(op_args[1:])
+
+        none_label  = self.node.block_to_name[link.target]
+        block_label = self.node.block_to_name[self.block]
+        exc_label   = block_label + '_exception_handling'
+
+        if self.db.is_function_ptr(op.result):  #use longhand form
+            returntype = "%s (%s)*" % (returntype, ", ".join(argtypes))
+        self.codewriter.call(targetvar, returntype, functionref, argrefs,
+                             argtypes, none_label, exc_label)
+
+        e = self.db.translator.rtyper.getexceptiondata()
+        ll_exception_match       = '%pypy_' + e.ll_exception_match.__name__
+        lltype_of_exception_type = ('%structtype.' +
+                                    e.lltype_of_exception_type.TO.__name__
+                                    + '*')
+        lltype_of_exception_value = ('%structtype.' +
+                                    e.lltype_of_exception_value.TO.__name__
+                                    + '*')
+
+        self.codewriter.label(exc_label)
+
+        exc_found_labels, last_exception_type = [], None
+        catch_all = False
+        for link in self.block.exits[1:]:
+            assert issubclass(link.exitcase, Exception)
+
+            etype = self.db.obj2node[link.llexitcase._obj]
+            current_exception_type = etype.get_ref()
+            target          = self.node.block_to_name[link.target]
+            exc_found_label = block_label + '_exception_found_branchto_' + target
+            last_exc_type_var, last_exc_value_var = None, None
+
+            for p in self.node.get_phi_data(link.target):
+                arg, type_, names, blocknames = p
+                for name, blockname in zip(names, blocknames):
+                    if blockname != exc_found_label:
+                        continue
+                    if name.startswith('%last_exception_'):
+                        last_exc_type_var = name
+                    if name.startswith('%last_exc_value_'):
+                        last_exc_value_var = name
+
+            t = (exc_found_label,target,last_exc_type_var,last_exc_value_var)
+            exc_found_labels.append(t)
+
+            not_this_exception_label = block_label + '_not_exception_' + etype.ref[1:]
+
+            if current_exception_type.find('getelementptr') == -1:  #catch all (except:)
+                catch_all = True
+                self.codewriter.br_uncond(exc_found_label)
+            else:   #catch specific exception (class) type
+                if not last_exception_type: #load pointer only once
+                    last_exception_type = self.db.repr_tmpvar()
+                    self.codewriter.load(last_exception_type, lltype_of_exception_type, '%last_exception_type')
+                    self.codewriter.newline()
+                ll_issubclass_cond = self.db.repr_tmpvar()
+                self.codewriter.call(ll_issubclass_cond,
+                                     'bool',
+                                     ll_exception_match,
+                                     [last_exception_type, current_exception_type],
+                                     [lltype_of_exception_type, lltype_of_exception_type])
+                self.codewriter.br(ll_issubclass_cond, not_this_exception_label, exc_found_label)
+                self.codewriter.label(not_this_exception_label)
+
+        ep = self.codewriter.genllvm.exceptionpolicy
+        if not catch_all:
+            ep.reraise(self.node, self.codewriter)
+        ep.fetch_exceptions(self.codewriter, exc_found_labels, lltype_of_exception_type, lltype_of_exception_value)
+
+    def malloc_exception(self, op): 
+        arg_type = op.args[0].value
+        targetvar = self.db.repr_arg(op.result) 
+        type_ = self.db.repr_type(arg_type)
+        tmpvar1 = self.db.repr_tmpvar()
+        tmpvar2 = self.db.repr_tmpvar()
+        tmpvar3 = self.db.repr_tmpvar()
+        self.codewriter.indent('%(tmpvar1)s = getelementptr %(type_)s* null, int 1' % locals())
+        self.codewriter.cast(tmpvar2, type_+'*', tmpvar1, 'uint')
+        self.codewriter.call(tmpvar3, 'sbyte*', '%malloc_exception', [tmpvar2], ['uint'])
+        self.codewriter.cast(targetvar, 'sbyte*', tmpvar3, type_+'*')
+
+    def malloc(self, op): 
+        arg_type = op.args[0].value
+        targetvar = self.db.repr_arg(op.result) 
+        type_ = self.db.repr_type(arg_type)
+        self.codewriter.malloc(targetvar, type_, atomic=arg_type._is_atomic())
+
+    def malloc_varsize(self, op):
+        arg_type = op.args[0].value
+        if isinstance(arg_type, lltype.Array) and arg_type.OF is lltype.Void:
+            # This is a backend decision to NOT represent a void array with
+            # anything and save space - therefore not varsized anymore
+            self.malloc(op)
+            return
+        
+        targetvar = self.db.repr_arg(op.result)
+        type_ = self.db.repr_type(arg_type) + "*"
+        type_cons = self.db.repr_constructor(arg_type)
+        argrefs = self.db.repr_arg_multi(op.args[1:])
+        argtypes = self.db.repr_arg_type_multi(op.args[1:])
+        self.codewriter.call(targetvar, type_, type_cons, argrefs, argtypes)
+
+    def _getindexhelper(self, name, struct):
+        assert name in list(struct._names)
+
+        fieldnames = struct._names_without_voids()
+        try:
+            index = fieldnames.index(name)
+        except ValueError:
+            index = -1
+        return index
+
+    def getfield(self, op): 
+        tmpvar = self.db.repr_tmpvar()
+        struct, structtype = self.db.repr_argwithtype(op.args[0])
+        index = self._getindexhelper(op.args[1].value, op.args[0].concretetype.TO)
+        targetvar = self.db.repr_arg(op.result)
+        targettype = self.db.repr_arg_type(op.result)
+        if targettype != "void":
+            assert index != -1
+            self.codewriter.getelementptr(tmpvar, structtype, struct,
+                                          ("uint", index))        
+            self.codewriter.load(targetvar, targettype, tmpvar)
+        else:
+            self.codewriter.comment("***Skipping operation getfield()***")
+ 
+    def getsubstruct(self, op): 
+        struct, structtype = self.db.repr_argwithtype(op.args[0])
+        index = self._getindexhelper(op.args[1].value, op.args[0].concretetype.TO)
+        targetvar = self.db.repr_arg(op.result)
+        targettype = self.db.repr_arg_type(op.result)
+        assert targettype != "void"
+        self.codewriter.getelementptr(targetvar, structtype, 
+                                      struct, ("uint", index))        
+         
+    def setfield(self, op): 
+        tmpvar = self.db.repr_tmpvar()
+        struct, structtype = self.db.repr_argwithtype(op.args[0])
+        index = self._getindexhelper(op.args[1].value, op.args[0].concretetype.TO)
+        valuevar, valuetype = self.db.repr_argwithtype(op.args[2])
+        if valuetype != "void": 
+            #Structure types require uint constants!
+            #see: http://llvm.cs.uiuc.edu/docs/LangRef.html#i_getelementptr
+            self.codewriter.getelementptr(tmpvar, structtype, struct,
+                                          ("uint", index))
+            self.codewriter.store(valuetype, valuevar, tmpvar) 
+        else:
+            self.codewriter.comment("***Skipping operation setfield()***")
+            
+    def getarrayitem(self, op):        
+        array, arraytype = self.db.repr_argwithtype(op.args[0])
+        index = self.db.repr_arg(op.args[1])
+        indextype = self.db.repr_arg_type(op.args[1])
+        tmpvar = self.db.repr_tmpvar()
+        targetvar = self.db.repr_arg(op.result)
+        targettype = self.db.repr_arg_type(op.result)
+        if targettype != "void":
+            self.codewriter.getelementptr(tmpvar, arraytype, array,
+                                          ("uint", 1), (indextype, index))
+            self.codewriter.load(targetvar, targettype, tmpvar)
+        else:
+            self.codewriter.comment("***Skipping operation getarrayitem()***")
+
+    def getarraysubstruct(self, op):        
+        array, arraytype = self.db.repr_argwithtype(op.args[0])
+        index = self.db.repr_arg(op.args[1])
+        indextype = self.db.repr_arg_type(op.args[1])
+        targetvar = self.db.repr_arg(op.result)
+        self.codewriter.getelementptr(targetvar, arraytype, array,
+                                      ("uint", 1), (indextype, index))
+
+    def setarrayitem(self, op):
+        array, arraytype = self.db.repr_argwithtype(op.args[0])
+        index = self.db.repr_arg(op.args[1])
+        indextype = self.db.repr_arg_type(op.args[1])
+
+        tmpvar = self.db.repr_tmpvar()
+
+        valuevar = self.db.repr_arg(op.args[2]) 
+        valuetype = self.db.repr_arg_type(op.args[2])
+        if valuetype != "void":
+            self.codewriter.getelementptr(tmpvar, arraytype, array,
+                                      ("uint", 1), (indextype, index))
+            self.codewriter.store(valuetype, valuevar, tmpvar) 
+        else:
+            self.codewriter.comment("***Skipping operation setarrayitem()***")
+
+    def getarraysize(self, op):
+        array, arraytype = self.db.repr_argwithtype(op.args[0])
+        tmpvar = self.db.repr_tmpvar()
+        self.codewriter.getelementptr(tmpvar, arraytype, array, ("uint", 0))
+        targetvar = self.db.repr_arg(op.result)
+        targettype = self.db.repr_arg_type(op.result)
+        self.codewriter.load(targetvar, targettype, tmpvar)

Added: pypy/dist/pypy/translator/js/structnode.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/structnode.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,235 @@
+import py
+from pypy.translator.llvm.log import log
+from pypy.translator.llvm.node import LLVMNode, ConstantLLVMNode
+from pypy.translator.llvm import varsize
+from pypy.rpython import lltype
+
+log = log.structnode 
+
+class StructTypeNode(LLVMNode):
+    __slots__ = "db struct ref name".split()
+
+    def __init__(self, db, struct): 
+        assert isinstance(struct, lltype.Struct)
+        self.db = db
+        self.struct = struct
+        prefix = '%structtype.'
+        name = self.struct._name
+        self.ref = self.make_ref(prefix, name)
+        self.name = self.ref[len(prefix):]
+        
+    def __str__(self):
+        return "<StructTypeNode %r>" %(self.ref,)
+
+    def _fields(self):
+        return [getattr(self.struct, name) 
+                for name in self.struct._names_without_voids()]
+    
+    def setup(self):
+        # Recurse
+        for field in self._fields():
+            self.db.prepare_type(field)
+
+    # ______________________________________________________________________
+    # main entry points from genllvm 
+
+    def writedatatypedecl(self, codewriter):
+        fields_types = [self.db.repr_type(f) for f in self._fields()]
+        codewriter.structdef(self.ref, fields_types)
+
+class StructVarsizeTypeNode(StructTypeNode):
+    __slots__ = "constructor_ref constructor_decl".split()
+
+    def __init__(self, db, struct): 
+        super(StructVarsizeTypeNode, self).__init__(db, struct)
+        prefix = '%new.varsizestruct.'
+        self.constructor_ref = self.make_ref(prefix, self.name)
+        self.constructor_decl = "%s * %s(%s %%len)" % \
+                                (self.ref,
+                                 self.constructor_ref,
+                                 self.db.get_machine_word())
+
+    def __str__(self):
+        return "<StructVarsizeTypeNode %r>" %(self.ref,)
+        
+    # ______________________________________________________________________
+    # main entry points from genllvm 
+
+    def writedecl(self, codewriter): 
+        # declaration for constructor
+        codewriter.declare(self.constructor_decl)
+
+    def writeimpl(self, codewriter):
+        log.writeimpl(self.ref)
+
+        # build up a list of indices to get to the last 
+        # var-sized struct (or rather the according array) 
+        indices_to_array = []
+        current = self.struct
+        while isinstance(current, lltype.Struct):
+            last_pos = len(current._names_without_voids()) - 1
+            indices_to_array.append(("uint", last_pos)) #struct requires uint consts
+            name = current._names_without_voids()[-1]
+            current = current._flds[name]
+        assert isinstance(current, lltype.Array)
+        varsize.write_constructor(self.db,
+                                  codewriter, 
+                                  self.ref,
+                                  self.constructor_decl,
+                                  current, 
+                                  indices_to_array)
+
+class StructNode(ConstantLLVMNode):
+    """ A struct constant.  Can simply contain
+    a primitive,
+    a struct,
+    pointer to struct/array
+    """
+    __slots__ = "db value structtype ref _get_ref_cache _get_types".split()
+
+    def __init__(self, db, value):
+        self.db = db
+        self.value = value
+        self.structtype = self.value._TYPE
+        prefix = '%structinstance.'
+        name = str(value).split()[1]
+        self.ref = self.make_ref(prefix, name)
+        self._get_ref_cache = None
+        self._get_types = self._compute_types()
+
+    def __str__(self):
+        return "<StructNode %r>" % (self.ref,)
+
+    def _compute_types(self):
+        return [(name, self.structtype._flds[name])
+                for name in self.structtype._names_without_voids()]
+
+    def _getvalues(self):
+        values = []
+        for name, T in self._get_types:
+            value = getattr(self.value, name)
+            values.append(self.db.repr_constant(value)[1])
+        return values
+    
+    def setup(self):
+        for name, T in self._get_types:
+            assert T is not lltype.Void
+            value = getattr(self.value, name)
+            self.db.prepare_constant(T, value)
+
+        p, c = lltype.parentlink(self.value)
+        if p is not None:
+            self.db.prepare_constant(lltype.typeOf(p), p)
+            
+    def get_typerepr(self):
+        return self.db.repr_type(self.structtype)
+
+    def get_childref(self, index):
+        pos = 0
+        found = False
+        for name in self.structtype._names_without_voids():
+            if name == index:
+                found = True
+                break
+            pos += 1
+        #Structure types require uint constants!
+        #see: http://llvm.cs.uiuc.edu/docs/LangRef.html#i_getelementptr
+        return "getelementptr(%s* %s, int 0, uint %s)" %(
+            self.get_typerepr(),
+            self.get_ref(),
+            pos)
+
+    def get_ref(self):
+        """ Returns a reference as used for operations in blocks. """        
+        if self._get_ref_cache:
+            return self._get_ref_cache
+        p, c = lltype.parentlink(self.value)
+        if p is None:
+            ref = self.ref
+        else:
+            ref = self.db.get_childref(p, c)
+        self._get_ref_cache = ref
+        return ref
+
+    def get_pbcref(self, toptr):
+        """ Returns a reference as used per pbc. """        
+        return self.get_ref()
+    
+    def constantvalue(self):
+        """ Returns the constant representation for this node. """
+        values = self._getvalues()
+        all_values = ",\n  ".join(values)
+        return "%s {\n  %s\n  }\n" % (self.get_typerepr(), all_values)
+                
+                
+class StructVarsizeNode(StructNode):
+    """ A varsize struct constant.  Can simply contain
+    a primitive,
+    a struct,
+    pointer to struct/array
+
+    and the last element *must* be
+    an array
+    OR
+    a series of embedded structs, which has as its last element an array.
+    """
+
+    def __str__(self):
+        return "<StructVarsizeNode %r>" % (self.ref,)
+
+    def _getvalues(self):
+        values = []
+        for name, T in self._get_types[:-1]:
+            value = getattr(self.value, name)
+            values.append(self.db.repr_constant(value)[1])
+        values.append(self._get_lastnoderepr())
+        return values
+
+    def _get_lastnode_helper(self):
+        lastname, LASTT = self._get_types[-1]
+        assert isinstance(LASTT, lltype.Array) or (
+            isinstance(LASTT, lltype.Struct) and LASTT._arrayfld)
+        value = getattr(self.value, lastname)
+        return self.db.repr_constant(value)
+
+    def _get_lastnode(self):
+        return self._get_lastnode_helper()[0]
+
+    def _get_lastnoderepr(self):
+        return self._get_lastnode_helper()[1]
+
+    def setup(self):
+        super(StructVarsizeNode, self).setup()
+    
+    def get_typerepr(self):
+            try:
+                return self._get_typerepr_cache
+            except:
+                # last type is a special case and need to be worked out recursively
+                types = self._get_types[:-1]
+                types_repr = [self.db.repr_type(T) for name, T in types]
+                types_repr.append(self._get_lastnode().get_typerepr())
+                result = "{%s}" % ", ".join(types_repr)
+                self._get_typerepr_cache = result
+                return result
+         
+    def get_ref(self):
+        if self._get_ref_cache:
+            return self._get_ref_cache
+        ref = super(StructVarsizeNode, self).get_ref()
+        typeval = self.db.repr_type(lltype.typeOf(self.value))
+        ref = "cast (%s* %s to %s*)" % (self.get_typerepr(),
+                                        ref,
+                                        typeval)
+        self._get_ref_cache = ref
+        return ref
+    
+    def get_pbcref(self, toptr):
+        """ Returns a reference as used per pbc. """        
+        ref = self.ref
+        p, c = lltype.parentlink(self.value)
+        assert p is None, "child arrays are NOT needed by rtyper"
+        fromptr = "%s*" % self.get_typerepr()
+        refptr = "getelementptr (%s %s, int 0)" % (fromptr, ref)
+        ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr)
+        return ref

Added: pypy/dist/pypy/translator/js/test/__init__.py
==============================================================================

Added: pypy/dist/pypy/translator/js/test/runtest.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/test/runtest.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,49 @@
+import py, os
+from pypy.translator.translator import Translator
+from pypy.translator.js.js import JS
+from pypy.translator.js.log import log
+log = log.runtest
+
+
+def _CLI_is_on_path():
+    try:
+        py.path.local.sysfind('js') #we recommend Spidermonkey
+    except py.error.ENOENT:
+        return False
+    return True
+
+def write_wrapper(js_filename):
+    jswrapper_filename = js_filename.new(ext='_wrapper.js')
+    f = open(str(jswrapper_filename), 'w')
+    f.write('print(42);\n')
+    f.close()
+    log('Written:', jswrapper_filename)
+    return jswrapper_filename
+
+class jscallable(object):
+    def __init__(self, jswrapper_filename):
+        self.jswrapper_filename = jswrapper_filename
+        
+    def __call__(self):
+        cmd = 'js "%s"' % str(self.jswrapper_filename)
+        s   = os.popen(cmd).read()
+        e   = eval(s)
+        return e
+    
+def compile(function, annotation=[], view=False):
+    if not _CLI_is_on_path():
+        py.test.skip('Javascript CLI (js) not found')
+
+    t = Translator(function)
+    a = t.annotate(annotation)
+    a.simplify()
+    t.specialize()
+    t.backend_optimizations()
+    if view:
+        t.view()
+
+    js = JS(t, function)
+    log('Written:', js.filename)
+
+    jswrapper_filename = write_wrapper(js.filename)
+    return jscallable(jswrapper_filename)

Added: pypy/dist/pypy/translator/js/test/test_trivial.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/test/test_trivial.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,8 @@
+import py
+from pypy.translator.js.test.runtest import compile
+
+def test_CLI():
+    def simple1():
+        return 42
+    f = compile(simple1)
+    assert f() == simple1()

Added: pypy/dist/pypy/translator/js/varsize.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/varsize.py	Thu Oct  6 22:24:04 2005
@@ -0,0 +1,38 @@
+from pypy.rpython.rstr import STR
+
+def write_constructor(db, codewriter, ref, constructor_decl, ARRAY, 
+                      indices_to_array=()): 
+
+    #varsized arrays and structs look like this: 
+    #Array: {int length , elemtype*}
+    #Struct: {...., Array}
+
+    # the following indices access the last element in the array
+    elemtype = db.repr_type(ARRAY.OF)
+    word = lentype = db.get_machine_word()
+    uword = db.get_machine_uword()
+
+    codewriter.openfunc(constructor_decl)    
+
+    # Need room for NUL terminator
+    if ARRAY is STR.chars:
+        codewriter.binaryop("add", "%actuallen", lentype, "%len", 1)
+    else:
+        codewriter.cast("%actuallen", lentype, "%len", lentype)
+
+    elemindices = list(indices_to_array) + [("uint", 1), (lentype, "%actuallen")]
+    codewriter.getelementptr("%size", ref + "*", "null", *elemindices) 
+    codewriter.cast("%usize", elemtype + "*", "%size", uword)
+    codewriter.malloc("%ptr", "sbyte", "%usize", atomic=ARRAY._is_atomic())
+    codewriter.cast("%result", "sbyte*", "%ptr", ref + "*")
+
+    indices_to_arraylength = tuple(indices_to_array) + (("uint", 0),)
+    # the following accesses the length field of the array 
+    codewriter.getelementptr("%arraylength", ref + "*", 
+                             "%result", 
+                             *indices_to_arraylength)
+    codewriter.store(lentype, "%len", "%arraylength")
+
+    codewriter.ret(ref + "*", "%result")
+    codewriter.closefunc()
+



More information about the Pypy-commit mailing list