Refactor the syscall generation script.

Primarily so that the new x86_64 alias functionality is now available for
all architectures.

Change-Id: I9fde59093a1d08de98923f121a6e3d05ec5801d2
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 386a8db..d31af9d 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -23,6 +23,7 @@
             make_dir(parent)
         os.mkdir(path)
 
+
 def create_file(relpath):
     dir = os.path.dirname(bionic_temp + relpath)
     make_dir(dir)
@@ -34,21 +35,85 @@
 #include <linux/err.h>
 #include <machine/asm.h>
 
-ENTRY(%(fname)s)
+ENTRY(%(func)s)
 """
 
+
 function_alias = """
     .globl _C_LABEL(%(alias)s)
-    .equ _C_LABEL(%(alias)s), _C_LABEL(%(fname)s)
+    .equ _C_LABEL(%(alias)s), _C_LABEL(%(func)s)
 """
 
+
+#
+# ARM assembler templates for each syscall stub
+#
+
+arm_eabi_call_default = syscall_stub_header + """\
+    mov     ip, r7
+    ldr     r7, =%(__NR_name)s
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(%(func)s)
+"""
+
+arm_eabi_call_long = syscall_stub_header + """\
+    mov     ip, sp
+    .save   {r4, r5, r6, r7}
+    stmfd   sp!, {r4, r5, r6, r7}
+    ldmfd   ip, {r4, r5, r6}
+    ldr     r7, =%(__NR_name)s
+    swi     #0
+    ldmfd   sp!, {r4, r5, r6, r7}
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(%(func)s)
+"""
+
+
+#
+# MIPS assembler templates for each syscall stub
+#
+
+mips_call = """/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+    .text
+    .globl %(func)s
+    .align 4
+    .ent %(func)s
+
+%(func)s:
+    .set noreorder
+    .cpload $t9
+    li $v0, %(__NR_name)s
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end %(func)s
+"""
+
+
 #
 # x86 assembler templates for each syscall stub
 #
 
 x86_registers = [ "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp" ]
 
-x86_call = """    movl    $%(idname)s, %%eax
+x86_call = """\
+    movl    $%(__NR_name)s, %%eax
     int     $0x80
     cmpl    $-MAX_ERRNO, %%eax
     jb      1f
@@ -60,15 +125,18 @@
 1:
 """
 
-x86_return = """    ret
-END(%(fname)s)
+x86_return = """\
+    ret
+END(%(func)s)
 """
 
+
 #
 # x86_64 assembler templates for each syscall stub
 #
 
-x86_64_call = """    movl    $%(idname)s, %%eax
+x86_64_call = """\
+    movl    $%(__NR_name)s, %%eax
     syscall
     cmpq    $-MAX_ERRNO, %%rax
     jb      1f
@@ -78,67 +146,9 @@
     orq     $-1, %%rax
 1:
     ret
-END(%(fname)s)
+END(%(func)s)
 """
 
-#
-# ARM assembler templates for each syscall stub
-#
-
-arm_eabi_call_default = syscall_stub_header + """\
-    mov     ip, r7
-    ldr     r7, =%(idname)s
-    swi     #0
-    mov     r7, ip
-    cmn     r0, #(MAX_ERRNO + 1)
-    bxls    lr
-    neg     r0, r0
-    b       __set_errno
-END(%(fname)s)
-"""
-
-arm_eabi_call_long = syscall_stub_header + """\
-    mov     ip, sp
-    .save   {r4, r5, r6, r7}
-    stmfd   sp!, {r4, r5, r6, r7}
-    ldmfd   ip, {r4, r5, r6}
-    ldr     r7, =%(idname)s
-    swi     #0
-    ldmfd   sp!, {r4, r5, r6, r7}
-    cmn     r0, #(MAX_ERRNO + 1)
-    bxls    lr
-    neg     r0, r0
-    b       __set_errno
-END(%(fname)s)
-"""
-
-#
-# mips assembler templates for each syscall stub
-#
-
-mips_call = """/* autogenerated by gensyscalls.py */
-#include <asm/unistd.h>
-    .text
-    .globl %(fname)s
-    .align 4
-    .ent %(fname)s
-
-%(fname)s:
-    .set noreorder
-    .cpload $t9
-    li $v0, %(idname)s
-    syscall
-    bnez $a3, 1f
-    move $a0, $v0
-    j $ra
-    nop
-1:
-    la $t9,__set_errno
-    j $t9
-    nop
-    .set reorder
-    .end %(fname)s
-"""
 
 def param_uses_64bits(param):
     """Returns True iff a syscall parameter description corresponds
@@ -160,6 +170,7 @@
     # Ok
     return True
 
+
 def count_arm_param_registers(params):
     """This function is used to count the number of register used
        to pass parameters when invoking an ARM system call.
@@ -184,6 +195,7 @@
             count += 1
     return count
 
+
 def count_generic_param_registers(params):
     count = 0
     for param in params:
@@ -193,12 +205,14 @@
             count += 1
     return count
 
+
 def count_generic_param_registers64(params):
     count = 0
     for param in params:
         count += 1
     return count
 
+
 # This lets us support regular system calls like __NR_write and also weird
 # ones like __ARM_NR_cacheflush, where the NR doesn't come at the start.
 def make__NR_name(name):
@@ -207,6 +221,90 @@
     else:
         return "__NR_%s" % (name)
 
+
+def add_aliases(stub, syscall):
+    aliases = syscall["aliases"]
+    for alias in aliases:
+        stub += function_alias % { "func" : syscall["func"], "alias" : alias }
+    return stub
+
+
+def arm_eabi_genstub(syscall):
+    num_regs = count_arm_param_registers(syscall["params"])
+    if num_regs > 4:
+        return arm_eabi_call_long % syscall
+    return arm_eabi_call_default % syscall
+
+
+def mips_genstub(syscall):
+    return mips_call % syscall
+
+
+def x86_genstub(syscall):
+    result     = syscall_stub_header % syscall
+    stack_bias = 4
+
+    numparams = count_generic_param_registers(syscall["params"])
+    for r in range(numparams):
+        result     += "    pushl   " + x86_registers[r] + "\n"
+        stack_bias += 4
+
+    for r in range(numparams):
+        result += "    mov     %d(%%esp), %s" % (stack_bias+r*4, x86_registers[r]) + "\n"
+
+    result += x86_call % syscall
+
+    for r in range(numparams):
+        result += "    popl    " + x86_registers[numparams-r-1] + "\n"
+
+    result += x86_return % syscall
+    return result
+
+def x86_genstub_socketcall(syscall):
+    #   %ebx <--- Argument 1 - The call id of the needed vectored
+    #                          syscall (socket, bind, recv, etc)
+    #   %ecx <--- Argument 2 - Pointer to the rest of the arguments
+    #                          from the original function called (socket())
+
+    result = syscall_stub_header % syscall
+    stack_bias = 4
+
+    # save the regs we need
+    result += "    pushl   %ebx" + "\n"
+    stack_bias += 4
+    result += "    pushl   %ecx" + "\n"
+    stack_bias += 4
+
+    # set the call id (%ebx)
+    result += "    mov     $%d, %%ebx" % syscall["socketcall_id"] + "\n"
+
+    # set the pointer to the rest of the args into %ecx
+    result += "    mov     %esp, %ecx" + "\n"
+    result += "    addl    $%d, %%ecx" % (stack_bias) + "\n"
+
+    # now do the syscall code itself
+    result += x86_call % syscall
+
+    # now restore the saved regs
+    result += "    popl    %ecx" + "\n"
+    result += "    popl    %ebx" + "\n"
+
+    # epilog
+    result += x86_return % syscall
+    return result
+
+
+def x86_64_genstub(syscall):
+    result = syscall_stub_header % syscall
+    num_regs = count_generic_param_registers64(syscall["params"])
+    if (num_regs > 3):
+        # rcx is used as 4th argument. Kernel wants it at r10.
+        result += "    movq    %rcx, %r10\n"
+
+    result += x86_64_call % syscall
+    return result
+
+
 class State:
     def __init__(self):
         self.old_stubs = []
@@ -214,126 +312,34 @@
         self.other_files = []
         self.syscalls = []
 
-    def x86_64_genstub(self, fname, numparams, idname, aliases):
-        t = { "fname"  : fname, "idname" : idname }
 
-        result = syscall_stub_header % t
-        # rcx is used as 4th argument. Kernel wants it at r10.
-        if (numparams > 3):
-            result += "    movq    %rcx, %r10\n"
-
-        result += x86_64_call % t
-        for alias in aliases:
-            t = { "fname" : fname, "alias" : alias }
-            result += function_alias % t
-
-        return result
-
-    def x86_genstub(self, fname, numparams, idname):
-        t = { "fname"  : fname,
-              "idname" : idname }
-
-        result     = syscall_stub_header % t
-        stack_bias = 4
-        for r in range(numparams):
-            result     += "    pushl   " + x86_registers[r] + "\n"
-            stack_bias += 4
-
-        for r in range(numparams):
-            result += "    mov     %d(%%esp), %s" % (stack_bias+r*4, x86_registers[r]) + "\n"
-
-        result += x86_call % t
-
-        for r in range(numparams):
-            result += "    popl    " + x86_registers[numparams-r-1] + "\n"
-
-        result += x86_return % t
-        return result
-
-    def x86_genstub_socketcall(self, fname, idname, socketcall_id):
-        #   %ebx <--- Argument 1 - The call id of the needed vectored
-        #                          syscall (socket, bind, recv, etc)
-        #   %ecx <--- Argument 2 - Pointer to the rest of the arguments
-        #                          from the original function called (socket())
-        t = { "fname"  : fname,
-              "idname" : idname }
-
-        result = syscall_stub_header % t
-        stack_bias = 4
-
-        # save the regs we need
-        result += "    pushl   %ebx" + "\n"
-        stack_bias += 4
-        result += "    pushl   %ecx" + "\n"
-        stack_bias += 4
-
-        # set the call id (%ebx)
-        result += "    mov     $%d, %%ebx" % (socketcall_id) + "\n"
-
-        # set the pointer to the rest of the args into %ecx
-        result += "    mov     %esp, %ecx" + "\n"
-        result += "    addl    $%d, %%ecx" % (stack_bias) + "\n"
-
-        # now do the syscall code itself
-        result += x86_call % t
-
-        # now restore the saved regs
-        result += "    popl    %ecx" + "\n"
-        result += "    popl    %ebx" + "\n"
-
-        # epilog
-        result += x86_return % t
-        return result
-
-
-    def arm_eabi_genstub(self,fname, flags, idname):
-        t = { "fname"  : fname,
-              "idname" : idname }
-        if flags:
-            numargs = int(flags)
-            if numargs > 4:
-                return arm_eabi_call_long % t
-        return arm_eabi_call_default % t
-
-
-    def mips_genstub(self,fname, idname):
-        t = { "fname"  : fname,
-              "idname" : idname }
-        return mips_call % t
-
-    def process_file(self,input):
+    def process_file(self, input):
         parser = SysCallsTxtParser()
         parser.parse_file(input)
         self.syscalls = parser.syscalls
         parser = None
 
-        for t in self.syscalls:
-            syscall_func   = t["func"]
-            syscall_aliases = t["aliases"]
-            syscall_params = t["params"]
-            syscall_name   = t["name"]
-            __NR_name = make__NR_name(t["name"])
+        for syscall in self.syscalls:
+            syscall["__NR_name"] = make__NR_name(syscall["name"])
 
-            if t.has_key("arm"):
-                num_regs = count_arm_param_registers(syscall_params)
-                t["asm-arm"] = self.arm_eabi_genstub(syscall_func, num_regs, __NR_name)
+            if syscall.has_key("arm"):
+                syscall["asm-arm"] = add_aliases(arm_eabi_genstub(syscall), syscall)
 
-            if t.has_key("x86"):
-                num_regs = count_generic_param_registers(syscall_params)
-                if t["socketcall_id"] >= 0:
-                    t["asm-x86"] = self.x86_genstub_socketcall(syscall_func, __NR_name, t["socketcall_id"])
+            if syscall.has_key("x86"):
+                if syscall["socketcall_id"] >= 0:
+                    syscall["asm-x86"] = add_aliases(x86_genstub_socketcall(syscall), syscall)
                 else:
-                    t["asm-x86"] = self.x86_genstub(syscall_func, num_regs, __NR_name)
-            elif t["socketcall_id"] >= 0:
+                    syscall["asm-x86"] = add_aliases(x86_genstub(syscall), syscall)
+            elif syscall["socketcall_id"] >= 0:
                 E("socketcall_id for dispatch syscalls is only supported for x86 in '%s'" % t)
                 return
 
-            if t.has_key("mips"):
-                t["asm-mips"] = self.mips_genstub(syscall_func, make__NR_name(syscall_name))
+            if syscall.has_key("mips"):
+                syscall["asm-mips"] = add_aliases(mips_genstub(syscall), syscall)
 
-            if t.has_key("x86_64"):
-                num_regs = count_generic_param_registers64(syscall_params)
-                t["asm-x86_64"] = self.x86_64_genstub(syscall_func, num_regs, __NR_name, syscall_aliases)
+            if syscall.has_key("x86_64"):
+                syscall["asm-x86_64"] = add_aliases(x86_64_genstub(syscall), syscall)
+
 
     # Scan a Linux kernel asm/unistd.h file containing __NR_* constants
     # and write out equivalent SYS_* constants for glibc source compatibility.
@@ -379,22 +385,22 @@
         fp = create_file(path)
         fp.write("# Auto-generated by gensyscalls.py. Do not edit.\n")
         fp.write("syscall_src :=\n")
-        for sc in self.syscalls:
-            if sc.has_key("asm-%s" % arch):
-                fp.write("syscall_src += arch-%s/syscalls/%s.S\n" % (arch, sc["func"]))
+        for syscall in self.syscalls:
+            if syscall.has_key("asm-%s" % arch):
+                fp.write("syscall_src += arch-%s/syscalls/%s.S\n" % (arch, syscall["func"]))
         fp.close()
         self.other_files.append(path)
 
 
     # Write each syscall stub.
     def gen_syscall_stubs(self):
-        for sc in self.syscalls:
+        for syscall in self.syscalls:
             for arch in all_arches:
-                if sc.has_key("asm-%s" % arch):
-                    filename = "arch-%s/syscalls/%s.S" % (arch, sc["func"])
+                if syscall.has_key("asm-%s" % arch):
+                    filename = "arch-%s/syscalls/%s.S" % (arch, syscall["func"])
                     D2(">>> generating " + filename)
                     fp = create_file(filename)
-                    fp.write(sc["asm-%s" % arch])
+                    fp.write(syscall["asm-%s" % arch])
                     fp.close()
                     self.new_stubs.append(filename)