def test_TempFileNotTooLong(self): '''Test that temp files with too-long names are not generated''' if not driver_test_utils.CanRunHost() or driver_tools.IsWindowsPython( ): return # This name is chosen such that the .c file has the maximum length. pnacl-ld # should not generate any temp names longer than that. shortname = os.path.join(self.LongTempDir, 'a' * 12) self.WriteCFile(shortname + '.c') driver_tools.RunDriver( 'pnacl-clang', [shortname + '.c', '-c', '-o', shortname + '.o']) driver_tools.RunDriver('pnacl-ld', [shortname + '.o', '-o', shortname]) # If it's impossible to generate a temp file short enough using our scheme # (i.e. the directory name is so long that 8 chars will be over the limit), # make sure we still fail the right way. longerdir = os.path.join(self.LongTempDir, 'a' * 8) os.mkdir(longerdir) longname = os.path.join(longerdir, 'a' * 3) os.rename(shortname + '.o', longname + '.o') output = self.AssertRaisesAndReturnOutput( driver_test_utils.DriverExitException, driver_tools.RunDriver, 'pnacl-ld', [longname + '.o', '-o', longname]) self.assertIn('.pexe is too long', output)
def test_compile_native_objects(self): s = self.getFakeSourceFile() with self.getTemp(suffix='.o') as obj: # TODO(dschuff): Use something more descriptive instead of -arch # (i.e. something that indicates that a translation is requested) # and remove pnacl-allow-translate driver_tools.RunDriver('clang', [ s.name, '-c', '-o', obj.name, '--target=x86_64-unknown-nacl', '-arch', 'x86-64', '--pnacl-allow-translate' ]) self.assertTrue(filetype.IsNativeObject(obj.name)) self.assertEqual(elftools.GetELFHeader(obj.name).arch, 'X8664') driver_tools.RunDriver('clang', [ s.name, '-c', '-o', obj.name, '--target=i686-unknown-nacl', '-arch', 'x86-32', '--pnacl-allow-translate' ]) self.assertTrue(filetype.IsNativeObject(obj.name)) self.assertEqual(elftools.GetELFHeader(obj.name).arch, 'X8632') driver_tools.RunDriver('clang', [ s.name, '-c', '-o', obj.name, '--target=armv7-unknown-nacl-gnueabi', '-arch', 'arm', '--pnacl-allow-translate' ]) self.assertTrue(filetype.IsNativeObject(obj.name)) self.assertEqual(elftools.GetELFHeader(obj.name).arch, 'ARM') # TODO(dschuff): This should be an error. driver_tools.RunDriver('clang', [ s.name, '-c', '-o', obj.name, '--target=x86_64-unknown-nacl', '-arch', 'x86-32', '--pnacl-allow-translate' ]) self.assertTrue(filetype.IsNativeObject(obj.name)) self.assertEqual(elftools.GetELFHeader(obj.name).arch, 'X8632')
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, PrepPatterns) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) != 1: Log.Fatal('Can only have one input') f_input = inputs[0] # Allow in-place file changes if output isn't specified.. if output != '': f_output = output else: f_output = f_input if env.getbool('DISABLE_FINALIZE') or filetype.IsPNaClBitcode(f_input): # Just copy the input file to the output file. if f_input != f_output: shutil.copyfile(f_input, f_output) return 0 opt_flags = [ '-disable-opt', '-strip', '-strip-metadata', '--bitcode-format=pnacl', f_input, '-o', f_output ] # Transform the file, and convert it to a PNaCl bitcode file. driver_tools.RunDriver('opt', opt_flags) # Compress the result if requested. if env.getbool('COMPRESS'): driver_tools.RunDriver('compress', [f_output]) return 0
def test_bc_objects(self): s = self.getFakeSourceFile() with self.getTemp(suffix='.o') as obj: # Test that clang with "normal" args results in a portable bitcode object driver_tools.RunDriver('clang', [s.name, '-c', '-o', obj.name]) self.assertTrue(filetype.IsLLVMBitcode(obj.name)) self.assertEqual(self.getBitcodeArch(obj.name), 'le32') # Test that the --target flag produces biased bitcode objects driver_tools.RunDriver( 'clang', [s.name, '--target=x86_64-unknown-nacl', '-c', '-o', obj.name]) self.assertTrue(filetype.IsLLVMBitcode(obj.name)) self.assertEqual(self.getBitcodeArch(obj.name), 'X8664') driver_tools.RunDriver( 'clang', [s.name, '--target=i686-unknown-nacl', '-c', '-o', obj.name]) self.assertTrue(filetype.IsLLVMBitcode(obj.name)) self.assertEqual(self.getBitcodeArch(obj.name), 'X8632') driver_tools.RunDriver('clang', [ s.name, '--target=armv7a-unknown-nacl-gnueabi', '-mfloat-abi=hard', '-c', '-o', obj.name ]) self.assertTrue(filetype.IsLLVMBitcode(obj.name)) self.assertEqual(self.getBitcodeArch(obj.name), 'ARM')
def test_multiple_compresses(self): pexe = self.getFakePexe() init_size = pathtools.getsize(pexe.name) driver_tools.RunDriver('pnacl-compress', [pexe.name]) shrunk_size = pathtools.getsize(pexe.name) self.assertTrue(init_size >= shrunk_size) driver_tools.RunDriver('pnacl-compress', [pexe.name]) self.assertTrue(pathtools.getsize(pexe.name) == shrunk_size)
def stripFileAndCheck(self, f): f_stripped = self.getTemp() driver_tools.RunDriver('strip', ['--strip-all', f.name, '-o', f_stripped.name]) self.assertTrue(self.getFileSize(f_stripped.name) < self.getFileSize(f.name)) driver_tools.RunDriver('strip', ['--strip-debug', f.name, '-o', f_stripped.name]) self.assertTrue(self.getFileSize(f_stripped.name) < self.getFileSize(f.name))
def BuildDynamicExecutable(): inputs = Env.get('INPUTS') if len(inputs) != 1: Log.Fatal('You must specify exactly on input for a dynamic executable.') pexe_command = ProcessBuildCommand(BUILD_COMMAND_PEXE_FROM_BC) DumpCommand("@bc->pexe", pexe_command) driver_tools.RunDriver('clang', pexe_command, suppress_arch=True) nexe_command = ProcessBuildCommand(BUILD_COMMAND_NEXE_FROM_PEXE) DumpCommand("@pexe->nexe", nexe_command) driver_tools.RunDriver('translate', nexe_command)
def getFakePexe(self): with self.getTemp(suffix='.ll', close=False) as t: with self.getTemp(suffix='.pexe') as p: t.write(''' define i32 @foo() { %1 = add i32 1, 1 %2 = add i32 %1, %1 %3 = add i32 %2, %2 %4 = add i32 %3, %3 %5 = add i32 %4, %4 %6 = add i32 %5, %5 %7 = add i32 %6, %6 %8 = add i32 %7, %7 %9 = add i32 %8, %8 %10 = add i32 %9, %9 %11 = add i32 %10, %10 %12 = add i32 %11, %11 %13 = add i32 %12, %12 %14 = add i32 %13, %13 %15 = add i32 %14, %14 %16 = add i32 %15, %15 ret i32 %16 } define i32 @main() { %1 = add i32 1, 1 %2 = add i32 %1, %1 %3 = add i32 %2, %2 %4 = add i32 %3, %3 %5 = add i32 %4, %4 %6 = add i32 %5, %5 %7 = add i32 %6, %6 %8 = add i32 %7, %7 %9 = add i32 %8, %8 %10 = add i32 %9, %9 %11 = add i32 %10, %10 %12 = add i32 %11, %11 %13 = add i32 %12, %12 %14 = add i32 %13, %13 %15 = add i32 %14, %14 %16 = add i32 %15, %15 %17 = call i32 @foo() %18 = add i32 %16, %17 ret i32 %18 } ''') t.close() driver_tools.RunDriver('pnacl-as', [t.name, '-o', p.name]) driver_tools.RunDriver('pnacl-finalize', [p.name]) return p
def getFakePexe(self): # Even --dry-run requires a file to exist, so make a fake pexe. # It even cares that the file is really bitcode. with self.getTemp(suffix='.ll', close=False) as t: with self.getTemp(suffix='.pexe') as p: t.write(''' define i32 @main() { ret i32 0 } ''') t.close() driver_tools.RunDriver('as', [t.name, '-o', p.name]) driver_tools.RunDriver('finalize', [p.name]) return p
def test_relocatable_header(self): """Tests that the driver accepts --relocatable-header.""" h = self.getFirstTestHeader(suffix='.h') h2 = self.getSecondTestHeader(h.name, suffix='.h') driver_tools.RunDriver('pnacl-clang', [ '-x', 'c-header', '--relocatable-pch', '-isysroot', self.temp_dir, h2.name ])
def generateArchive(self, objs): a = self.getTemp(suffix='.a') # Archive file must be a valid archive (non-empty), or non-existent, # so remove it before running. os.remove(a.name) obj_names = [obj.name for obj in objs] args = ['rcs', a.name] + obj_names driver_tools.RunDriver('pnacl-ar', args) return a
def getFakePexe(self, finalized=True): # Even --dry-run requires a file to exist, so make a fake pexe. # It even cares that the file is really bitcode. with self.getTemp(suffix='.ll', close=False) as t: with self.getTemp(suffix='.pexe') as p: t.write(''' define i32 @_start() { ret i32 0 } ''') t.close() driver_tools.RunDriver('as', [t.name, '-o', p.name]) if finalized: driver_tools.RunDriver('finalize', [p.name]) self.assertTrue(filetype.IsPNaClBitcode(p.name)) else: self.assertTrue(filetype.IsLLVMBitcode(p.name)) return p
def test_ExpandedPathTooLong(self): '''Test that the expanded path is checked with a short relative path''' if not driver_test_utils.CanRunHost() or driver_tools.IsWindowsPython( ): return os.chdir(self.LongTempDir) shortname = 'a' * 10 longname = 'a' * 32 # Now we are in a state where the file can be referred to by a relative # path or a normalized absolute path. For 'shortname', both are short # enough assert len(os.path.join(self.LongTempDir, shortname)) + 2 < 255 assert len(os.path.join(self.LongTempDir, longname)) + 2 > 255 self.WriteCFile(shortname + '.c') # Test that using a relative almost-too-long path works driver_tools.RunDriver( 'pnacl-clang', [shortname + '.c', '-c', '-o', shortname + '.o']) driver_tools.RunDriver('pnacl-ld', [shortname + '.o']) # This name has a short-enough relative path and a short-enough normalized # final path, but the intermediate concatenation of pwd + rel path is too # long name_with_traversals = os.path.join('..', os.path.basename(self.LongTempDir), shortname) output = self.AssertRaisesAndReturnOutput( driver_test_utils.DriverExitException, driver_tools.RunDriver, 'pnacl-clang', [name_with_traversals + '.c', '-c', '-o', shortname + '.o']) self.assertIn('expanded', output) # The previous test only gives a long input name. Also test that the output # name is checked. output = self.AssertRaisesAndReturnOutput( driver_test_utils.DriverExitException, driver_tools.RunDriver, 'pnacl-clang', [shortname + '.c', '-c', '-o', name_with_traversals + '.o']) self.assertIn('expanded', output)
def test_finalize(self): """ Test that pnacl-ld will finalize the pexe when requested""" if not driver_test_utils.CanRunHost(): return bitcode = self.getBitcode() with self.getTemp(suffix='.pexe') as temp_output: driver_tools.RunDriver( 'pnacl-ld', ['--finalize', bitcode.name, '-o', temp_output.name]) self.assertFalse(filetype.IsLLVMBitcode(temp_output.name)) self.assertTrue(filetype.IsPNaClBitcode(temp_output.name))
def generateObjWithDebug(self, src, is_native): s = '.bc' if is_native: s = '.o' obj = self.getTemp(suffix=s) args = ['-c', '-g', src.name, '-o', obj.name] if is_native: args += ['-arch', 'x86-32', '--pnacl-allow-translate'] driver_tools.RunDriver('pnacl-clang', args) return obj
def test_PathWithSpaces(self): '''Test that the driver correctly handles paths containing spaces''' if not driver_test_utils.CanRunHost(): return name = os.path.join(self.ShorterTempDir, 'a file') self.WriteCFile(name + '.c') driver_tools.RunDriver('pnacl-clang', [name + '.c', '-c', '-o', name + '.o']) self.assertEqual('po', filetype.FileType(name + '.o'))
def getBitcodeArch(self, filename): with self.getTemp(suffix='.ll') as ll: driver_tools.RunDriver('dis', [filename, '-o', ll.name]) with open(ll.name) as f: disassembly = f.read() match = re.search(r'target triple = "(.+)"', disassembly) if not match: return None triple = match.group(1) return driver_tools.ParseTriple(triple)
def test_inplace_finalize(self): if not driver_test_utils.CanRunHost(): return ll, bc = self.getFakeLLAndBitcodeFile() self.assertTrue(filetype.FileType(bc.name) == 'po') self.assertTrue(filetype.IsLLVMBitcode(bc.name)) self.assertFalse(filetype.IsPNaClBitcode(bc.name)) driver_tools.RunDriver('finalize', [bc.name]) self.assertFalse(filetype.IsLLVMBitcode(bc.name)) self.assertTrue(filetype.IsPNaClBitcode(bc.name)) self.assertTrue(filetype.FileType(bc.name) == 'pexe')
def BuildSharedLib(): # Shared libs must be built PIC Env.set('GENERATE_PIC', '1') inputs = Env.get('INPUTS') if len(inputs) == 0: Log.Fatal('No input specified.') if not Env.getbool('GENERATE_PIC'): Log.Fatal('Shared libs must be build in pic mode. Use -fPIC') if Env.getone('SONAME_FLAG') == '': Log.Fatal('Shared libs must be given a soname.') pso_command = ProcessBuildCommand(BUILD_COMMAND_PSO_FROM_BC) DumpCommand("@bc->pso", pso_command) # suppress_arch is needed to prevent clang to inherit the # -arch argument driver_tools.RunDriver('clang', pso_command, suppress_arch=True) so_command = ProcessBuildCommand(BUILD_COMMAND_SO_FROM_PSO) DumpCommand("@pso->so", so_command) driver_tools.RunDriver('translate', so_command)
def getFakeLLAndBitcodeFile(self): with self.getTemp(suffix='.ll', close=False) as t: t.write(''' define i32 @main() { ret i32 0 } ''') t.close() with self.getTemp(suffix='.bc') as b: driver_tools.RunDriver('as', [t.name, '-o', b.name]) return t, b
def RunLD(infile, outfile): inputs = env.get('INPUTS') if infile: inputs = ListReplace(inputs, '__BITCODE__', '--llc-translated-file=' + infile) ToggleDefaultCommandlineLD(inputs, infile) env.set('ld_inputs', *inputs) args = env.get('LD_ARGS') + ['-o', outfile] if not env.getbool('SHARED') and env.getbool('STDLIB'): args += env.get('LD_ARGS_ENTRY') args += env.get('LD_FLAGS') driver_tools.RunDriver('nativeld', args)
def checkXFlagOutput(self, flags, expected): ''' Given |flags| for pnacl-clang, check that clang outputs the |expected|. ''' if not driver_test_utils.CanRunHost(): return temp_out = pathtools.normalize(tempfile.NamedTemporaryFile().name) driver_temps.TempFiles.add(temp_out) driver_tools.RunDriver('pnacl-clang', flags + ['-o', temp_out]) output = open(temp_out, 'r').read() for e in expected: self.assertTrue(re.search(e, output), msg='Searching for regex %s in %s' % (e, output))
def test_finalize_keep_syms(self): """Test that finalize is still able to create a pexe w/ -no-strip-syms.""" if not driver_test_utils.CanRunHost(): return bc = self.getBCWithDebug() self.assertTrue(filetype.FileType(bc.name) == 'po') self.assertTrue(filetype.IsLLVMBitcode(bc.name)) self.assertFalse(filetype.IsPNaClBitcode(bc.name)) driver_tools.RunDriver('pnacl-finalize', [bc.name, '--no-strip-syms']) self.assertFalse(filetype.IsLLVMBitcode(bc.name)) self.assertTrue(filetype.IsPNaClBitcode(bc.name)) self.assertTrue(filetype.FileType(bc.name) == 'pexe') # Use pnacl-dis instead of llvm-nm, since llvm-nm won't know how to # handle finalized bitcode for now: # https://code.google.com/p/nativeclient/issues/detail?id=3993 with self.getTemp(suffix='.ll') as temp_ll: driver_tools.RunDriver('pnacl-dis', [bc.name, '-o', temp_ll.name]) with open(temp_ll.name, 'r') as dis_file: file_contents = dis_file.read() self.assertTrue(re.search(r'define .*@baz', file_contents)) self.assertTrue(re.search(r'define .*@foo', file_contents))
def getBitcode(self, finalized=True): # Even --dry-run requires a file to exist, so make a fake bitcode file. # It even cares that the file is really bitcode. with self.getTemp(suffix='.ll', close=False) as t: with self.getTemp(suffix='.o') as o: t.write(''' define i32 @_start() { ret i32 0 } ''') t.close() driver_tools.RunDriver('pnacl-as', [t.name, '-o', o.name]) return o
def test_InputPathTooLong(self): '''Test that clang and ld reject input paths that are too long Test that compiling and linking paths shorter than 255 succeeds and paths longer than 255 fails. Operations in python (e.g. rename) on long paths don't work on Windows, so just run the tests on Linux/Mac (the checks are enabled in unittest mode) ''' if not driver_test_utils.CanRunHost() or driver_tools.IsWindowsPython( ): return shortname = os.path.join(self.LongTempDir, 'a' * 10) longname = os.path.join(self.LongTempDir, 'a' * 32) assert len(shortname) + 2 < 255 assert len(longname) + 2 > 255 self.WriteCFile(shortname + '.c') driver_tools.RunDriver( 'pnacl-clang', [shortname + '.c', '-c', '-o', shortname + '.o']) driver_tools.RunDriver('pnacl-ld', [shortname + '.o']) os.rename(shortname + '.c', longname + '.c') os.rename(shortname + '.o', longname + '.o') output = self.AssertRaisesAndReturnOutput( driver_test_utils.DriverExitException, driver_tools.RunDriver, 'pnacl-clang', [longname + '.c', '-c', '-o', longname + '.o']) self.assertIn('too long', output) output = self.AssertRaisesAndReturnOutput( driver_test_utils.DriverExitException, driver_tools.RunDriver, 'pnacl-ld', [longname + '.o']) self.assertIn('too long', output)
def test_bc_objects(self): s = self.getFakeSourceFile() with self.getTemp(suffix='.o') as obj: # Test that clang with "normal" args results in a portable bitcode object driver_tools.RunDriver('clang', [s.name, '-c', '-o', obj.name]) self.assertTrue(filetype.IsLLVMBitcode(obj.name)) self.assertEqual(self.getBitcodeArch(obj.name), 'le32') # Test that the --target flag produces biased bitcode objects test_args = [ ('armv7', 'ARM', '-gnueabihf', ['-mfloat-abi=hard']), ('i686', 'X8632', '', []), ('x86_64', 'X8664', '', []), ('mips', 'MIPS32', '', []), ] for (target, arch, target_extra, cmd_extra) in test_args: target_arg = '--target=%s-unknown-nacl%s' % (target, target_extra) driver_tools.RunDriver( 'clang', [s.name, target_arg, '-c', '-o', obj.name] + cmd_extra) self.assertTrue(filetype.IsLLVMBitcode(obj.name)) self.assertEqual(self.getBitcodeArch(obj.name), arch)
def RunLD(infile, outfile): inputs = env.get('INPUTS') if infile: # Put llc-translated-file at the beginning of the inputs so that it will # pull in all needed symbols from any native archives that may also be # in the input list. This is in case there are any mixed groups of bitcode # and native archives in the link (as is the case with irt_browser_lib) inputs.remove('__BITCODE__') inputs = ['--llc-translated-file=' + infile] + inputs env.set('ld_inputs', *inputs) args = env.get('LD_ARGS') + ['-o', outfile] if env.getbool('USE_STDLIB'): args += env.get('LD_ARGS_ENTRY') args += env.get('LD_FLAGS') driver_tools.RunDriver('nativeld', args)
def check_flags(self, flags, pnacl_flag): """ Check that pnacl_flag doesn't get passed to clang. It should only be in the 'Driver invocation:' part that we print out. """ capture_out = cStringIO.StringIO() driver_log.Log.CaptureToStream(capture_out) driver_tools.RunDriver('clang', flags + [pnacl_flag]) driver_log.Log.ResetStreams() out = capture_out.getvalue() lines = out.splitlines() self.assertTrue('Driver invocation:' in lines[0]) self.assertTrue(pnacl_flag in lines[0]) for line in lines[1:]: self.assertTrue(pnacl_flag not in line) for flag in flags: self.assertTrue(exists(flag, lines[1:]))
def getBCWithDebug(self): with self.getTemp(suffix='.c', close=False) as t: t.write(''' int __attribute__((noinline)) baz(int x, int y) { return x + y; } int foo(int a, int b) { return baz(a, b); } ''') t.close() with self.getTemp(suffix='.bc') as b: # Compile w/ optimization to avoid allocas from local # variables/parameters, since this isn't running the ABI # simplification passes. driver_tools.RunDriver( 'pnacl-clang', [t.name, '-o', b.name, '-c', '-g', '-O1']) return b
def checkLDOptNumRuns(self, bitcode, flags, num_runs): """ Given a |bitcode| file the |arch| and additional pnacl-ld |flags|, check that opt will only be run |num_runs| times. """ # TODO(jvoung): Get rid of INHERITED_DRIVER_ARGS, which leaks across runs. env.set('INHERITED_DRIVER_ARGS', '') temp_output = self.getTemp() capture_out = cStringIO.StringIO() driver_log.Log.CaptureToStream(capture_out) driver_tools.RunDriver('pnacl-ld', ['--pnacl-driver-verbose', '--dry-run', bitcode.name, '-o', temp_output.name] + flags) driver_log.Log.ResetStreams() out = capture_out.getvalue() split_out = out.splitlines() count = 0 for line in split_out: if re.search('Running: .*opt( |\.exe)', line): count += 1 self.assertEqual(num_runs, count)