Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/python | |
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 import os.path | |
| 7 import string | |
| 8 import sys | |
| 9 | |
| 10 import interface | |
| 11 | |
| 12 class CodeWriter(object): | |
| 13 def __init__(self): | |
| 14 self.lines = [] | |
| 15 self.margin = "" | |
| 16 self.margin_stack = [] | |
| 17 | |
| 18 def __lshift__(self, line): | |
| 19 self.lines.append((self.margin + line).rstrip()) | |
| 20 | |
| 21 def pushMargin(self): | |
| 22 self.margin_stack.append(self.margin) | |
| 23 self.margin += " " | |
| 24 | |
| 25 def popMargin(self): | |
| 26 self.margin = self.margin_stack.pop() | |
| 27 | |
| 28 def getValue(self): | |
| 29 return "\n".join(self.lines).rstrip() + "\n" | |
| 30 | |
| 31 class Indent(object): | |
| 32 def __init__(self, writer): | |
| 33 self.writer = writer | |
| 34 | |
| 35 def __enter__(self): | |
| 36 self.writer.pushMargin() | |
| 37 | |
| 38 def __exit__(self, type, value, traceback): | |
| 39 self.writer.popMargin() | |
| 40 | |
| 41 def templateFile(name): | |
| 42 return os.path.join(os.path.dirname(__file__), name) | |
| 43 | |
| 44 def wrap(pre, items, post): | |
| 45 complete = pre + ", ".join(items) + post | |
| 46 if len(complete) <= 80: | |
| 47 return [complete] | |
| 48 lines = [pre] | |
| 49 indent = " " | |
| 50 for i, item in enumerate(items): | |
| 51 if i < len(items) - 1: | |
| 52 lines.append(indent + item + ",") | |
| 53 else: | |
| 54 lines.append(indent + item + post) | |
| 55 return lines | |
| 56 | |
| 57 def iovDecl(param): | |
| 58 if param.isPassedByValue(): | |
| 59 return "{&%s, sizeof(%s)}" % (param.name, param.name) | |
| 60 elif param.isArray: | |
| 61 sp = param.getSizeParam() | |
| 62 if sp.isPassedByValue(): | |
| 63 size = sp.name | |
| 64 else: | |
| 65 # TODO volatile read? | |
| 66 size = "(*%s)" % sp.name | |
| 67 if param.baseType == "void": | |
| 68 return "{(void*)%s, %s}" % (param.name, size) | |
| 69 else: | |
| 70 return "{(void*)%s, sizeof(*%s)*%s}" % (param.name, param.name, size) | |
| 71 else: | |
| 72 return "{(void*)%s, sizeof(*%s)}" % (param.name, param.name) | |
| 73 | |
| 74 def loadTemplate(filename): | |
| 75 data = open(templateFile(filename)).read() | |
| 76 template = string.Template(data) | |
| 77 return template | |
| 78 | |
| 79 def generateLibMojo(functions, out): | |
| 80 template = loadTemplate("libmojo.cc.template") | |
| 81 | |
| 82 code = CodeWriter() | |
| 83 | |
| 84 for f in functions: | |
| 85 for line in wrap("%s %s(" % (f.returnType, f.name), f.paramList(), "){"): | |
| 86 code << line | |
| 87 numParams = len(f.params) + 2 | |
| 88 | |
| 89 with Indent(code): | |
| 90 code << "uint32_t params[%d];" % numParams | |
| 91 code << f.returnType + " result;" | |
| 92 | |
| 93 # Message ID | |
| 94 code << "params[0] = %d;" % f.uid | |
| 95 # Parameter pointers | |
| 96 castTemplate = "params[%d] = reinterpret_cast<uint32_t>(%s);" | |
| 97 for p in f.params: | |
| 98 ptr = p.name | |
| 99 if p.isPassedByValue(): | |
| 100 ptr = "&" + ptr | |
| 101 code << castTemplate % (p.uid + 1, ptr) | |
| 102 # Return value pointer | |
| 103 code << castTemplate % (numParams - 1, "&result") | |
| 104 | |
| 105 iovLength = 1 | |
| 106 code << "NaClAbiNaClImcMsgIoVec iov[%d] = {" % iovLength | |
| 107 with Indent(code): | |
| 108 code << "{params, sizeof(params)}" | |
| 109 code << "};" | |
| 110 | |
| 111 code << "NaClAbiNaClImcMsgHdr msgh = {iov, %d, NULL, 0};" % iovLength | |
| 112 code << "if (imc_sendmsg(NACL_MOJO_DESC, &msgh, 0) < 0) {" | |
| 113 with Indent(code): | |
| 114 code << "result = MOJO_RESULT_INVALID_ARGUMENT;" | |
| 115 code << "}" | |
| 116 | |
| 117 code << "return result;" | |
| 118 | |
| 119 code << "}" | |
| 120 code << "" | |
| 121 | |
| 122 body = code.getValue() | |
| 123 | |
| 124 | |
| 125 text = template.substitute( | |
| 126 script_name=os.path.basename(__file__), | |
| 127 body=body) | |
| 128 | |
| 129 print >>out, text | |
| 130 | |
| 131 def paramPtr(param): | |
| 132 ptr = param.paramType | |
| 133 if param.isPassedByValue(): | |
| 134 ptr += " volatile*" | |
| 135 return ptr | |
| 136 | |
| 137 def generateMojoSyscall(functions, out): | |
| 138 template = loadTemplate("mojo_syscall.cc.template") | |
| 139 | |
| 140 code = CodeWriter() | |
| 141 code.pushMargin() | |
| 142 | |
| 143 for f in functions: | |
| 144 code << "case %d:" % f.uid | |
| 145 | |
| 146 code.pushMargin() | |
| 147 | |
| 148 code << "{" | |
| 149 | |
| 150 with Indent(code): | |
| 151 numParams = len(f.params) + 2 | |
| 152 code << "if (numParams != %d) {" % numParams | |
| 153 with Indent(code): | |
| 154 code << "return -1;" | |
| 155 code << "}" | |
| 156 | |
| 157 def scalarNull(param): | |
| 158 code << "%s_ptr = NULL;" % (param.name) | |
| 159 if param.isInput: | |
| 160 if param.isScalar(): | |
| 161 # TODO can we alway zero scalar values? | |
| 162 code << "%s = 0;" % (param.name) | |
| 163 | |
| 164 def scalarFinalize(param, src): | |
| 165 if param.isOutput: | |
| 166 # For outputs, we need to retain the pointer for later. | |
| 167 code << "%s_ptr = reinterpret_cast<%s>(%s);" % (param.name, paramPtr(p aram), 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
| |
| 168 if param.isInput: | |
| 169 code << "// In/Out" | |
| 170 code << "%s = *%s_ptr;" % (param.name, param.name) | |
| 171 else: | |
| 172 # For pure inputs, no need to retain the pointer | |
| 173 code << "%s = *reinterpret_cast<%s>(%s);" % (param.name, paramPtr(para m), src) | |
| 174 | |
| 175 def convertParam(param): | |
| 176 if param.isScalar(): | |
| 177 code << "uintptr_t temp = NaClUserToSysAddrRange(nap, params[%d], size of(%s));" % (param.uid + 1, param.name) | |
| 178 elif param.isArray: | |
| 179 if param.baseType == "void": | |
| 180 code << "uintptr_t temp = NaClUserToSysAddrRange(nap, params[%d], %s );" % (param.uid + 1, param.size) | |
| 181 else: | |
| 182 code << "uintptr_t temp = NaClUserToSysAddrArray(nap, params[%d], %s , sizeof(*%s));" % (param.uid + 1, param.size, param.name) | |
| 183 else: | |
| 184 code << "uintptr_t temp = NaClUserToSysAddrRange(nap, params[%d], size of(*%s));" % (param.uid + 1, param.name) | |
| 185 | |
| 186 code << "if (temp == kNaClBadAddress) {" | |
| 187 with Indent(code): | |
| 188 code << "return -1;" | |
| 189 code << "}" | |
| 190 if param.isScalar(): | |
| 191 scalarFinalize(param, 'temp') | |
| 192 else: | |
| 193 code << "%s = reinterpret_cast<%s>(%s);" % (param.name, param.paramTyp e, 'temp') | |
| 194 | |
| 195 def convertPtr(param): | |
| 196 if param.isScalar(): | |
| 197 if param.isOutput: | |
| 198 code << "%s %s_ptr;" % (paramPtr(param), param.name) | |
| 199 code << "%s %s;" % (param.baseType, param.name) | |
| 200 else: | |
| 201 code << "%s %s;" % (param.paramType, param.name) | |
| 202 | |
| 203 code << "if (params[%d] == 0) {" % (param.uid + 1) | |
| 204 with Indent(code): | |
| 205 if param.isOptional: | |
| 206 if param.isScalar(): | |
| 207 scalarNull(param) | |
| 208 else: | |
| 209 code << "%s = NULL;" % (param.name) | |
| 210 else: | |
| 211 code << "return -1;" | |
| 212 code << "} else {" | |
| 213 with Indent(code): | |
| 214 convertParam(param) | |
| 215 code << "}" | |
| 216 | |
| 217 # Convert and validate pointers in two passes. | |
| 218 # Arrays cannot be validated util the size parameter has been converted. | |
| 219 code << "NaClCopyTakeLock(nap);" | |
| 220 for param in f.params: | |
| 221 if not param.isArray: | |
| 222 convertPtr(param) | |
| 223 for param in f.params: | |
| 224 if param.isArray: | |
| 225 convertPtr(param) | |
| 226 convertPtr(f.resultParam) | |
| 227 code << "NaClCopyDropLock(nap);" | |
| 228 code << "" | |
| 229 | |
| 230 # Call | |
| 231 getParams = [] | |
| 232 for param in f.params: | |
| 233 if param.isScalar() and not param.isPassedByValue(): | |
| 234 if param.isOptional: | |
| 235 getParams.append("%s_ptr ? &%s : NULL" % (param.name, param.name)) | |
| 236 else: | |
| 237 getParams.append("&%s" % (param.name)) | |
| 238 else: | |
| 239 getParams.append(param.name) | |
| 240 | |
| 241 code << "result = %s(%s);" % (f.name, ", ".join(getParams)) | |
| 242 code << "" | |
| 243 | |
| 244 def copyOut(param): | |
| 245 if param.isScalar(): | |
| 246 if param.isOutput: | |
| 247 if param.isOptional: | |
| 248 code << "if (%s_ptr != NULL) {" % (param.name) | |
| 249 with Indent(code): | |
| 250 code << "*%s_ptr = %s;" % (param.name, param.name) | |
| 251 code << "}" | |
| 252 else: | |
| 253 code << "*%s_ptr = %s;" % (param.name, param.name) | |
| 254 | |
| 255 # Write outputs | |
| 256 code << "NaClCopyTakeLock(nap);" | |
| 257 for param in f.params: | |
| 258 copyOut(param) | |
| 259 copyOut(f.resultParam) | |
| 260 code << "NaClCopyDropLock(nap);" | |
| 261 code << "" | |
| 262 | |
| 263 code << "return 0;" | |
| 264 code << "}" | |
| 265 | |
| 266 code.popMargin() | |
| 267 | |
| 268 body = code.getValue() | |
| 269 | |
| 270 text = template.substitute( | |
| 271 script_name=os.path.basename(__file__), | |
| 272 body=body) | |
| 273 | |
| 274 print >>out, text | |
| 275 | |
| 276 def main(): | |
| 277 outdir = os.path.dirname(os.path.dirname(__file__)) | |
| 278 | |
| 279 mojo = interface.makeInterface() | |
| 280 generateLibMojo(mojo.functions, open(os.path.join(outdir, "libmojo.cc"), "w")) | |
| 281 generateMojoSyscall(mojo.functions, open(os.path.join(outdir, "mojo_syscall.cc "), "w")) | |
| 282 | |
| 283 if __name__ == "__main__": | |
| 284 main() | |
| OLD | NEW |