1#!/usr/bin/env python2.7 2# 3# Copyright 2017 Google Inc. 4# 5# Use of this source code is governed by a BSD-style license that can be 6# found in the LICENSE file. 7 8import re 9import subprocess 10import sys 11 12#clang = ['clang++'] 13clang = ['ccache', 'clang-4.0', '-x', 'c++'] 14 15ndk = '/Users/mtklein/brew/opt/android-ndk/' 16objdump = 'gobjdump' 17 18#ndk = '/home/mtklein/ndk/' 19#objdump = '/home/mtklein/binutils-2.27/binutils/objdump' 20 21cflags = ['-std=c++11', '-Os', '-DJUMPER', 22 '-fomit-frame-pointer', '-ffp-contract=fast' ] 23 24sse2 = '-mno-red-zone -msse2 -mno-sse3 -mno-ssse3 -mno-sse4.1'.split() 25subprocess.check_call(clang + cflags + sse2 + 26 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 27 ['-o', 'sse2.o']) 28subprocess.check_call(clang + cflags + sse2 + ['-DWIN'] + 29 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 30 ['-o', 'win_sse2.o']) 31 32sse41 = '-mno-red-zone -msse4.1'.split() 33subprocess.check_call(clang + cflags + sse41 + 34 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 35 ['-o', 'sse41.o']) 36subprocess.check_call(clang + cflags + sse41 + ['-DWIN'] + 37 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 38 ['-o', 'win_sse41.o']) 39 40avx = '-mno-red-zone -mavx'.split() 41subprocess.check_call(clang + cflags + avx + 42 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 43 ['-o', 'avx.o']) 44subprocess.check_call(clang + cflags + avx + ['-DWIN'] + 45 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 46 ['-o', 'win_avx.o']) 47 48hsw = '-mno-red-zone -mavx2 -mfma -mf16c'.split() 49subprocess.check_call(clang + cflags + hsw + 50 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 51 ['-o', 'hsw.o']) 52subprocess.check_call(clang + cflags + hsw + ['-DWIN'] + 53 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 54 ['-o', 'win_hsw.o']) 55 56aarch64 = [ 57 '--target=aarch64-linux-android', 58 '--sysroot=' + ndk + 'platforms/android-21/arch-arm64', 59] 60subprocess.check_call(clang + cflags + aarch64 + 61 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 62 ['-o', 'aarch64.o']) 63 64vfp4 = [ 65 '--target=armv7a-linux-android', 66 '--sysroot=' + ndk + 'platforms/android-18/arch-arm', 67 '-mfpu=neon-vfpv4', 68 '-mfloat-abi=hard', 69] 70subprocess.check_call(clang + cflags + vfp4 + 71 ['-c', 'src/jumper/SkJumper_stages.cpp'] + 72 ['-o', 'vfp4.o']) 73 74def parse_object_file(dot_o, array_type, target=None): 75 cmd = [objdump] 76 if target: 77 cmd += ['--target', target] 78 79 # Look for sections we know we can't handle. 80 section_headers = subprocess.check_output(cmd + ['-h', dot_o]) 81 for snippet in ['.literal', '.const', '.rodata']: 82 if snippet in section_headers: 83 print >>sys.stderr, 'Found %s in section.' % snippet 84 assert snippet not in section_headers 85 86 # Ok. Let's disassemble. 87 active = False 88 disassemble = ['-d', '--insn-width=10', dot_o] 89 for line in subprocess.check_output(cmd + disassemble).split('\n'): 90 line = line.strip() 91 92 if not line or line.startswith(dot_o) or line.startswith('Disassembly'): 93 continue 94 95 # E.g. 00000000000003a4 <_load_f16>: 96 m = re.match('''[0-9a-f]+ <_?(.*)>:''', line) 97 if m: 98 if active: 99 print '};' 100 print 101 print 'CODE const', array_type, m.group(1) + '[] = {' 102 active = True 103 continue 104 105 columns = line.split('\t') 106 code = columns[1] 107 if len(columns) >= 4: 108 inst = columns[2] 109 args = columns[3] 110 else: 111 inst, args = columns[2], '' 112 if ' ' in columns[2]: 113 inst, args = columns[2].split(' ', 1) 114 code, inst, args = code.strip(), inst.strip(), args.strip() 115 116 dehex = lambda x: '0x'+x 117 if array_type == 'uint8_t': 118 dehex = lambda x: str(int(x, 16)) 119 120 hexed = ''.join(dehex(x) + ',' for x in code.split(' ')) 121 print ' ' + hexed + ' '*(40-len(hexed)) + \ 122 '//' + inst + (' '*(14-len(inst)) + args if args else '') 123 print '};' 124 125sys.stdout = open('src/jumper/SkJumper_generated.cpp', 'w') 126 127print '''/* 128 * Copyright 2017 Google Inc. 129 * 130 * Use of this source code is governed by a BSD-style license that can be 131 * found in the LICENSE file. 132 */ 133 134// This file is generated semi-automatically with this command: 135// $ src/jumper/build_stages.py 136 137#include <stdint.h> 138 139#if defined(_MSC_VER) 140 #pragma section("code", read,execute) 141 #define CODE extern "C" __declspec(allocate("code")) 142#elif defined(__MACH__) 143 #define CODE extern "C" __attribute__((section("__TEXT,__text"))) 144#else 145 #define CODE extern "C" __attribute__((section(".text"))) 146#endif 147''' 148print '#if defined(__aarch64__)' 149parse_object_file('aarch64.o', 'uint32_t') 150 151print '#elif defined(__arm__)' 152parse_object_file('vfp4.o', 'uint32_t', target='elf32-littlearm') 153 154print '#elif defined(__x86_64__)' 155parse_object_file('hsw.o', 'uint8_t') 156parse_object_file('avx.o', 'uint8_t') 157parse_object_file('sse41.o', 'uint8_t') 158parse_object_file('sse2.o', 'uint8_t') 159 160print '#elif defined(_M_X64)' 161parse_object_file('win_hsw.o', 'uint8_t') 162parse_object_file('win_avx.o', 'uint8_t') 163parse_object_file('win_sse41.o', 'uint8_t') 164parse_object_file('win_sse2.o', 'uint8_t') 165 166print '#endif' 167