Chromium Code Reviews| Index: mojo/monacl/gen/generate_monacl_bindings.py |
| diff --git a/mojo/monacl/gen/generate_monacl_bindings.py b/mojo/monacl/gen/generate_monacl_bindings.py |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..6157e50287d0f2489f2fc4dca63a8c7a5c543938 |
| --- /dev/null |
| +++ b/mojo/monacl/gen/generate_monacl_bindings.py |
| @@ -0,0 +1,284 @@ |
| +#!/usr/bin/python |
| +# Copyright 2014 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +import os.path |
| +import string |
| +import sys |
| + |
| +import interface |
| + |
| +class CodeWriter(object): |
| + def __init__(self): |
| + self.lines = [] |
| + self.margin = "" |
| + self.margin_stack = [] |
| + |
| + def __lshift__(self, line): |
| + self.lines.append((self.margin + line).rstrip()) |
| + |
| + def pushMargin(self): |
| + self.margin_stack.append(self.margin) |
| + self.margin += " " |
| + |
| + def popMargin(self): |
| + self.margin = self.margin_stack.pop() |
| + |
| + def getValue(self): |
| + return "\n".join(self.lines).rstrip() + "\n" |
| + |
| +class Indent(object): |
| + def __init__(self, writer): |
| + self.writer = writer |
| + |
| + def __enter__(self): |
| + self.writer.pushMargin() |
| + |
| + def __exit__(self, type, value, traceback): |
| + self.writer.popMargin() |
| + |
| +def templateFile(name): |
| + return os.path.join(os.path.dirname(__file__), name) |
| + |
| +def wrap(pre, items, post): |
| + complete = pre + ", ".join(items) + post |
| + if len(complete) <= 80: |
| + return [complete] |
| + lines = [pre] |
| + indent = " " |
| + for i, item in enumerate(items): |
| + if i < len(items) - 1: |
| + lines.append(indent + item + ",") |
| + else: |
| + lines.append(indent + item + post) |
| + return lines |
| + |
| +def iovDecl(param): |
| + if param.isPassedByValue(): |
| + return "{&%s, sizeof(%s)}" % (param.name, param.name) |
| + elif param.isArray: |
| + sp = param.getSizeParam() |
| + if sp.isPassedByValue(): |
| + size = sp.name |
| + else: |
| + # TODO volatile read? |
| + size = "(*%s)" % sp.name |
| + if param.baseType == "void": |
| + return "{(void*)%s, %s}" % (param.name, size) |
| + else: |
| + return "{(void*)%s, sizeof(*%s)*%s}" % (param.name, param.name, size) |
| + else: |
| + return "{(void*)%s, sizeof(*%s)}" % (param.name, param.name) |
| + |
| +def loadTemplate(filename): |
| + data = open(templateFile(filename)).read() |
| + template = string.Template(data) |
| + return template |
| + |
| +def generateLibMojo(functions, out): |
| + template = loadTemplate("libmojo.cc.template") |
| + |
| + code = CodeWriter() |
| + |
| + for f in functions: |
| + for line in wrap("%s %s(" % (f.returnType, f.name), f.paramList(), "){"): |
| + code << line |
| + numParams = len(f.params) + 2 |
| + |
| + with Indent(code): |
| + code << "uint32_t params[%d];" % numParams |
| + code << f.returnType + " result;" |
| + |
| + # Message ID |
| + code << "params[0] = %d;" % f.uid |
| + # Parameter pointers |
| + castTemplate = "params[%d] = reinterpret_cast<uint32_t>(%s);" |
| + for p in f.params: |
| + ptr = p.name |
| + if p.isPassedByValue(): |
| + ptr = "&" + ptr |
| + code << castTemplate % (p.uid + 1, ptr) |
| + # Return value pointer |
| + code << castTemplate % (numParams - 1, "&result") |
| + |
| + iovLength = 1 |
| + code << "NaClAbiNaClImcMsgIoVec iov[%d] = {" % iovLength |
| + with Indent(code): |
| + code << "{params, sizeof(params)}" |
| + code << "};" |
| + |
| + code << "NaClAbiNaClImcMsgHdr msgh = {iov, %d, NULL, 0};" % iovLength |
| + code << "if (imc_sendmsg(NACL_MOJO_DESC, &msgh, 0) < 0) {" |
| + with Indent(code): |
| + code << "result = MOJO_RESULT_INVALID_ARGUMENT;" |
| + code << "}" |
| + |
| + code << "return result;" |
| + |
| + code << "}" |
| + code << "" |
| + |
| + body = code.getValue() |
| + |
| + |
| + text = template.substitute( |
| + script_name=os.path.basename(__file__), |
| + body=body) |
| + |
| + print >>out, text |
| + |
| +def paramPtr(param): |
| + ptr = param.paramType |
| + if param.isPassedByValue(): |
| + ptr += " volatile*" |
| + return ptr |
| + |
| +def generateMojoSyscall(functions, out): |
| + template = loadTemplate("mojo_syscall.cc.template") |
| + |
| + code = CodeWriter() |
| + code.pushMargin() |
| + |
| + for f in functions: |
| + code << "case %d:" % f.uid |
| + |
| + code.pushMargin() |
| + |
| + code << "{" |
| + |
| + with Indent(code): |
| + numParams = len(f.params) + 2 |
| + code << "if (numParams != %d) {" % numParams |
| + with Indent(code): |
| + code << "return -1;" |
| + code << "}" |
| + |
| + def scalarNull(param): |
| + code << "%s_ptr = NULL;" % (param.name) |
| + if param.isInput: |
| + if param.isScalar(): |
| + # TODO can we alway zero scalar values? |
| + code << "%s = 0;" % (param.name) |
| + |
| + def scalarFinalize(param, src): |
| + if param.isOutput: |
| + # For outputs, we need to retain the pointer for later. |
| + code << "%s_ptr = reinterpret_cast<%s>(%s);" % (param.name, paramPtr(param), src) |
|
Mark Seaborn
2014/07/21 16:31:39
Lines >80 chars (and elsewhere too)
Nick Bray (chromium)
2014/07/21 22:38:36
This file needs to be cleaned up before commit, as
|
| + if param.isInput: |
| + code << "// In/Out" |
| + code << "%s = *%s_ptr;" % (param.name, param.name) |
| + else: |
| + # For pure inputs, no need to retain the pointer |
| + code << "%s = *reinterpret_cast<%s>(%s);" % (param.name, paramPtr(param), src) |
| + |
| + def convertParam(param): |
| + if param.isScalar(): |
| + code << "uintptr_t temp = NaClUserToSysAddrRange(nap, params[%d], sizeof(%s));" % (param.uid + 1, param.name) |
| + elif param.isArray: |
| + if param.baseType == "void": |
| + code << "uintptr_t temp = NaClUserToSysAddrRange(nap, params[%d], %s);" % (param.uid + 1, param.size) |
| + else: |
| + code << "uintptr_t temp = NaClUserToSysAddrArray(nap, params[%d], %s, sizeof(*%s));" % (param.uid + 1, param.size, param.name) |
| + else: |
| + code << "uintptr_t temp = NaClUserToSysAddrRange(nap, params[%d], sizeof(*%s));" % (param.uid + 1, param.name) |
| + |
| + code << "if (temp == kNaClBadAddress) {" |
| + with Indent(code): |
| + code << "return -1;" |
| + code << "}" |
| + if param.isScalar(): |
| + scalarFinalize(param, 'temp') |
| + else: |
| + code << "%s = reinterpret_cast<%s>(%s);" % (param.name, param.paramType, 'temp') |
| + |
| + def convertPtr(param): |
| + if param.isScalar(): |
| + if param.isOutput: |
| + code << "%s %s_ptr;" % (paramPtr(param), param.name) |
| + code << "%s %s;" % (param.baseType, param.name) |
| + else: |
| + code << "%s %s;" % (param.paramType, param.name) |
| + |
| + code << "if (params[%d] == 0) {" % (param.uid + 1) |
| + with Indent(code): |
| + if param.isOptional: |
| + if param.isScalar(): |
| + scalarNull(param) |
| + else: |
| + code << "%s = NULL;" % (param.name) |
| + else: |
| + code << "return -1;" |
| + code << "} else {" |
| + with Indent(code): |
| + convertParam(param) |
| + code << "}" |
| + |
| + # Convert and validate pointers in two passes. |
| + # Arrays cannot be validated util the size parameter has been converted. |
| + code << "NaClCopyTakeLock(nap);" |
| + for param in f.params: |
| + if not param.isArray: |
| + convertPtr(param) |
| + for param in f.params: |
| + if param.isArray: |
| + convertPtr(param) |
| + convertPtr(f.resultParam) |
| + code << "NaClCopyDropLock(nap);" |
| + code << "" |
| + |
| + # Call |
| + getParams = [] |
| + for param in f.params: |
| + if param.isScalar() and not param.isPassedByValue(): |
| + if param.isOptional: |
| + getParams.append("%s_ptr ? &%s : NULL" % (param.name, param.name)) |
| + else: |
| + getParams.append("&%s" % (param.name)) |
| + else: |
| + getParams.append(param.name) |
| + |
| + code << "result = %s(%s);" % (f.name, ", ".join(getParams)) |
| + code << "" |
| + |
| + def copyOut(param): |
| + if param.isScalar(): |
| + if param.isOutput: |
| + if param.isOptional: |
| + code << "if (%s_ptr != NULL) {" % (param.name) |
| + with Indent(code): |
| + code << "*%s_ptr = %s;" % (param.name, param.name) |
| + code << "}" |
| + else: |
| + code << "*%s_ptr = %s;" % (param.name, param.name) |
| + |
| + # Write outputs |
| + code << "NaClCopyTakeLock(nap);" |
| + for param in f.params: |
| + copyOut(param) |
| + copyOut(f.resultParam) |
| + code << "NaClCopyDropLock(nap);" |
| + code << "" |
| + |
| + code << "return 0;" |
| + code << "}" |
| + |
| + code.popMargin() |
| + |
| + body = code.getValue() |
| + |
| + text = template.substitute( |
| + script_name=os.path.basename(__file__), |
| + body=body) |
| + |
| + print >>out, text |
| + |
| +def main(): |
| + outdir = os.path.dirname(os.path.dirname(__file__)) |
| + |
| + mojo = interface.makeInterface() |
| + generateLibMojo(mojo.functions, open(os.path.join(outdir, "libmojo.cc"), "w")) |
| + generateMojoSyscall(mojo.functions, open(os.path.join(outdir, "mojo_syscall.cc"), "w")) |
| + |
| +if __name__ == "__main__": |
| + main() |