Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Unified Diff: mojo/monacl/gen/generate_monacl_bindings.py

Issue 385983008: Mojo + NaCl prototype. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Better diff Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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()

Powered by Google App Engine
This is Rietveld 408576698