diff options
author | dmichael@google.com <dmichael@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-14 22:35:06 +0000 |
---|---|---|
committer | dmichael@google.com <dmichael@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-14 22:35:06 +0000 |
commit | 8d672b5d62afdf1571a23ddd004294d0b0e8c1d8 (patch) | |
tree | 7c71d87af454bdb9b973ce82012690062d643f6a /ppapi/generate_ppapi_size_checks.py | |
parent | c1b9277f706fb46cfe8a492ab8b95316955b302c (diff) | |
download | chromium_src-8d672b5d62afdf1571a23ddd004294d0b0e8c1d8.zip chromium_src-8d672b5d62afdf1571a23ddd004294d0b0e8c1d8.tar.gz chromium_src-8d672b5d62afdf1571a23ddd004294d0b0e8c1d8.tar.bz2 |
Revert 69187, http://codereview.chromium.org/5730003/. DEPS check failed due to unrecognized Clang includes.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/5703008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69191 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/generate_ppapi_size_checks.py')
-rw-r--r-- | ppapi/generate_ppapi_size_checks.py | 348 |
1 files changed, 0 insertions, 348 deletions
diff --git a/ppapi/generate_ppapi_size_checks.py b/ppapi/generate_ppapi_size_checks.py deleted file mode 100644 index d9d1dea..0000000 --- a/ppapi/generate_ppapi_size_checks.py +++ /dev/null @@ -1,348 +0,0 @@ -#!/usr/bin/python - -# Copyright (c) 2010 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. - -"""This script should be run manually on occasion to make sure all PPAPI types -have appropriate size checking. - -""" - -import optparse -import os -import subprocess -import sys - - -# The string that the PrintNamesAndSizes plugin uses to indicate whether or not -# a type has a pointer. Types that have pointers are not expected to have the -# same size on 32-bit and 64-bit architectures. -HAS_POINTER_STRING = "HasPointer" - -# These are types that don't include a pointer but nonetheless have -# architecture-dependent size. They all are ultimately typedefs to 'long' or -# 'unsigned long'. If there get to be too many types that use 'long' or -# 'unsigned long', we can add detection of them to the plugin to automate this. -ARCH_DEPENDENT_TYPES = set(["khronos_intptr_t", - "khronos_uintptr_t", - "khronos_ssize_t", - "khronos_usize_t", - "GLintptr", - "GLsizeiptr" - ]) - - - -class SourceLocation: - - """A class representing the source location of a definiton.""" - - def __init__(self, filename="", start_line=-1, end_line=-1): - self.filename = os.path.normpath(filename) - self.start_line = start_line - self.end_line = end_line - - - -class TypeInfo: - - """A class representing information about a C++ type.""" - - def __init__(self, info_string, target): - [self.kind, self.name, self.size, has_pointer_string, source_file, - start_line, end_line] = info_string.split(',') - self.target = target - self.parsed_line = info_string - # Note that Clang counts line numbers from 1, but we want to count from 0. - self.source_location = SourceLocation(source_file, - int(start_line)-1, - int(end_line)-1) - # If the type is one of our known special cases, mark it as architecture- - # dependent. - if self.name in ARCH_DEPENDENT_TYPES: - self.arch_dependent = True - # Otherwise, its size can be architecture dependent if it contains one or - # more pointers (or is a pointer). - else: - self.arch_dependent = (has_pointer_string == HAS_POINTER_STRING) - self.target = target - self.parsed_line = info_string - - - -class FilePatch: - - """A class representing a set of line-by-line changes to a particular file. - None - of the changes are applied until Apply is called. All line numbers are - counted from 0. - """ - - def __init__(self, filename): - self.filename = filename - self.linenums_to_delete = set() - # A dictionary from line number to an array of strings to be inserted at - # that line number. - self.lines_to_add = {} - - def Delete(self, start_line, end_line): - """Make the patch delete the lines [start_line, end_line).""" - self.linenums_to_delete |= set(range(start_line, end_line)) - - def Add(self, text, line_number): - """Add the given text before the text on the given line number.""" - if line_number in self.lines_to_add: - self.lines_to_add[line_number].append(text) - else: - self.lines_to_add[line_number] = [text] - - def Apply(self): - """Apply the patch by writing it to self.filename""" - # Read the lines of the existing file in to a list. - sourcefile = open(self.filename, "r") - file_lines = sourcefile.readlines() - sourcefile.close() - # Now apply the patch. Our strategy is to keep the array at the same size, - # and just edit strings in the file_lines list as necessary. When we delete - # lines, we just blank the line and keep it in the list. When we add lines, - # we just prepend the added source code to the start of the existing line at - # that line number. This way, all the line numbers we cached from calls to - # Add and Delete remain valid list indices, and we don't have to worry about - # maintaining any offsets. Each element of file_lines at the end may - # contain any number of lines (0 or more) delimited by carriage returns. - for linenum_to_delete in self.linenums_to_delete: - file_lines[linenum_to_delete] = ""; - for linenum, sourcelines in self.lines_to_add.items(): - # Sort the lines we're adding so we get relatively consistent results. - sourcelines.sort() - # Prepend the new lines. When we output - file_lines[linenum] = "".join(sourcelines) + file_lines[linenum] - newsource = open(self.filename, "w") - for line in file_lines: - newsource.write(line) - newsource.close() - - -def CheckAndInsert(typeinfo, typeinfo_map): - """Check if a TypeInfo exists already in the given map with the same name. If - so, make sure the size is consistent. - - If the name exists but the sizes do not match, print a message and - exit with non-zero exit code. - - If the name exists and the sizes match, do nothing. - - If the name does not exist, insert the typeinfo in to the map. - - """ - # If the type is unnamed, ignore it. - if typeinfo.name == "": - return - # If the size is 0, ignore it. - elif int(typeinfo.size) == 0: - return - # If the type is not defined under ppapi, ignore it. - elif typeinfo.source_location.filename.find("ppapi") == -1: - return - # If the type is defined under GLES2, ignore it. - elif typeinfo.source_location.filename.find("GLES2") > -1: - return - # If the type is an interface (by convention, starts with PPP_ or PPB_), - # ignore it. - elif (typeinfo.name[:4] == "PPP_") or (typeinfo.name[:4] == "PPB_"): - return - elif typeinfo.name in typeinfo_map: - if typeinfo.size != typeinfo_map[typeinfo.name].size: - print "Error: '" + typeinfo.name + "' is", \ - typeinfo_map[typeinfo.name].size, \ - "bytes on target '" + typeinfo_map[typeinfo.name].target + \ - "', but", typeinfo.size, "on target '" + typeinfo.target + "'" - print typeinfo_map[typeinfo.name].parsed_line - print typeinfo.parsed_line - sys.exit(1) - else: - # It's already in the map and the sizes match. - pass - else: - typeinfo_map[typeinfo.name] = typeinfo - - -def ProcessTarget(clang_command, target, arch_types, ind_types): - """Run clang using the given clang_command for the given target string. Parse - the output to create TypeInfos for each discovered type. Insert each type in - to the appropriate dictionary. For each type that has architecture-dependent - size, insert it in to arch_types. Types with independent size go in to - ind_types. If the type already exists in the appropriate map, make sure that - the size matches what's already in the map. If not, the script terminates - with an error message. - """ - p = subprocess.Popen(clang_command + " -triple " + target, - shell=True, - stdout=subprocess.PIPE) - lines = p.communicate()[0].split() - for line in lines: - typeinfo = TypeInfo(line, target) - # Put types which have architecture-specific size in to arch_types. All - # other types are 'architecture-independent' and get put in ind_types. - # in the appropraite dictionary. - if typeinfo.arch_dependent: - CheckAndInsert(typeinfo, arch_types) - else: - CheckAndInsert(typeinfo, ind_types) - - -def ToAssertionCode(typeinfo): - """Convert the TypeInfo to an appropriate C compile assertion. - If it's a struct (Record in Clang terminology), we want a line like this: - PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(<name>, <size>);\n - Enums: - PP_COMPILE_ASSERT_ENUM_SIZE_IN_BYTES(<name>, <size>);\n - Typedefs: - PP_COMPILE_ASSERT_SIZE_IN_BYTES(<name>, <size>);\n - - """ - line = "PP_COMPILE_ASSERT_" - if typeinfo.kind == "Enum": - line += "ENUM_" - elif typeinfo.kind == "Record": - line += "STRUCT_" - line += "SIZE_IN_BYTES(" - line += typeinfo.name - line += ", " - line += typeinfo.size - line += ");\n" - return line - - -def IsMacroDefinedName(typename): - """Return true iff the given typename came from a PPAPI compile assertion.""" - return typename.find("PP_Dummy_Struct_For_") == 0 - - -COPYRIGHT_STRING_C = \ -"""/* Copyright (c) 2010 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. - * - * This file has compile assertions for the sizes of types that are dependent - * on the architecture for which they are compiled (i.e., 32-bit vs 64-bit). - */ - -""" - - -def WriteArchSpecificCode(types, root, filename): - """Write a header file that contains a compile-time assertion for the size of - each of the given typeinfos, in to a file named filename rooted at root. - """ - assertion_lines = [ToAssertionCode(typeinfo) for typeinfo in types] - assertion_lines.sort() - outfile = open(os.path.join(root, filename), "w") - header_guard = "PPAPI_TESTS_" + filename.upper().replace(".", "_") + "_" - outfile.write(COPYRIGHT_STRING_C) - outfile.write('#ifndef ' + header_guard + '\n') - outfile.write('#define ' + header_guard + '\n\n') - outfile.write('#include "ppapi/tests/test_struct_sizes.c"\n\n') - for line in assertion_lines: - outfile.write(line) - outfile.write('\n#endif /* ' + header_guard + ' */\n') - - -def main(argv): - parser = optparse.OptionParser() - parser.add_option( - '-c', '--clang-path', dest='clang_path', - default=(''), - help='the path to the clang binary (default is to get it from your path)') - parser.add_option( - '-p', '--plugin', dest='plugin', - default='tests/clang/libPrintNamesAndSizes.so', - help='The path to the PrintNamesAndSizes plugin library.') - parser.add_option( - '--targets32', dest='targets32', - default='i386-pc-linux,arm-pc-linux,i386-pc-win32', - help='Which 32-bit target triples to provide to clang.') - parser.add_option( - '--targets64', dest='targets64', - default='x86_64-pc-linux,x86_64-pc-win', - help='Which 32-bit target triples to provide to clang.') - parser.add_option( - '-r', '--ppapi-root', dest='ppapi_root', - default='.', - help='The root directory of ppapi.') - options, args = parser.parse_args(argv) - if args: - parser.print_help() - print 'ERROR: invalid argument' - sys.exit(1) - - clang_executable = os.path.join(options.clang_path, 'clang') - clang_command = clang_executable + " -cc1" \ - + " -load " + options.plugin \ - + " -plugin PrintNamesAndSizes" \ - + " -I" + os.path.join(options.ppapi_root, "..") \ - + " " \ - + os.path.join(options.ppapi_root, "tests", "test_struct_sizes.c") - - # Dictionaries mapping type names to TypeInfo objects. - # Types that have size dependent on architecture, for 32-bit - types32 = {} - # Types that have size dependent on architecture, for 64-bit - types64 = {} - # Note that types32 and types64 should contain the same types, but with - # different sizes. - - # Types whose size should be consistent regardless of architecture. - types_independent = {} - - # Now run clang for each target. Along the way, make sure architecture- - # dependent types are consistent sizes on all 32-bit platforms and consistent - # on all 64-bit platforms. Any types in 'types_independent' are checked for - # all targets to make sure their size is consistent across all of them. - targets32 = options.targets32.split(','); - for target in targets32: - ProcessTarget(clang_command, target, types32, types_independent) - targets64 = options.targets64.split(','); - for target in targets64: - ProcessTarget(clang_command, target, types64, types_independent) - - # This dictionary maps file names to FilePatch objects. - file_patches = {} - - # Find locations of existing macros, and just delete them all. - for name, typeinfo in \ - types_independent.items() + types32.items() + types64.items(): - if IsMacroDefinedName(name): - sourcefile = typeinfo.source_location.filename - if sourcefile not in file_patches: - file_patches[sourcefile] = FilePatch(sourcefile) - file_patches[sourcefile].Delete(typeinfo.source_location.start_line, - typeinfo.source_location.end_line+1) - - # Add a compile-time assertion for each type whose size is independent of - # architecture. These assertions go immediately after the class definition. - for name, typeinfo in types_independent.items(): - # Ignore macros and types that are 0 bytes (i.e., typedefs to void) - if not IsMacroDefinedName(name) and typeinfo.size > 0: - sourcefile = typeinfo.source_location.filename - if sourcefile not in file_patches: - file_patches[sourcefile] = FilePatch(sourcefile) - # Add the assertion code just after the definition of the type. - file_patches[sourcefile].Add(ToAssertionCode(typeinfo), - typeinfo.source_location.end_line+1) - - for filename, patch in file_patches.items(): - patch.Apply() - - c_source_root = os.path.join(options.ppapi_root, "tests") - WriteArchSpecificCode(types32.values(), - c_source_root, - "arch_dependent_sizes_32.h") - WriteArchSpecificCode(types64.values(), - c_source_root, - "arch_dependent_sizes_64.h") - - return 0 - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) - |