def CompileLlvmBytecode(src: str, suffix: str, cflags: typing.List[str], timeout_seconds: int = 60) -> str: """Compile input code into textual LLVM byte code. Args: src: The source code to compile. suffix: The suffix to append to the source code temporary file. E.g. '.c' for a C program. cflags: A list of flags to be passed to clang. timeout_seconds: The number of seconds to allow before killing clang. Returns: The textual LLVM byte code. Raises: ClangException: In case of an error. ClangTimeout: If clang does not complete before timeout_seconds. """ builtin_cflags = ['-S', '-emit-llvm', '-o', '-'] with tempfile.NamedTemporaryFile('w', prefix='clgen_clang_', suffix=suffix) as f: f.write(src) f.flush() cmd = ['timeout', '-s9', str(timeout_seconds), str(CLANG), f.name] + builtin_cflags + cflags logging.debug('$ %s', ' '.join(cmd)) process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) stdout, stderr = process.communicate() if process.returncode == 9: raise errors.ClangTimeout(f'Clang timed out after {timeout_seconds}s') elif process.returncode != 0: raise errors.ClangException(stderr) return stdout
def Preprocess(src: str, cflags: typing.List[str], timeout_seconds: int = 60, strip_preprocessor_lines: bool = True): """Run input code through the compiler frontend to inline macros. This uses the repository clang binary. Args: src: The source code to preprocess. cflags: A list of flags to be passed to clang. timeout_seconds: The number of seconds to allow before killing clang. strip_preprocessor_lines: Whether to strip the extra lines introduced by the preprocessor. Returns: The preprocessed code. Raises: ClangException: In case of an error. ClangTimeout: If clang does not complete before timeout_seconds. """ cmd = ['timeout', '-s9', str(timeout_seconds), str(CLANG), '-E', '-c', '-', '-o', '-'] + cflags logging.debug('$ %s', ' '.join(cmd)) process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) stdout, stderr = process.communicate(src) if process.returncode == 9: raise errors.ClangTimeout( f'Clang preprocessor timed out after {timeout_seconds}s') elif process.returncode != 0: raise errors.ClangException(stderr) if strip_preprocessor_lines: return StripPreprocessorLines(stdout) else: return stdout
def CompileLlvmBytecode(src: str, suffix: str, cflags: typing.List[str], timeout_seconds: int = 60) -> str: """Compile input code into textual LLVM byte code. Args: src: The source code to compile. suffix: The suffix to append to the source code temporary file. E.g. '.c' for a C program. cflags: A list of flags to be passed to clang. timeout_seconds: The number of seconds to allow before killing clang. Returns: The textual LLVM byte code. Raises: ClangException: In case of an error. ClangTimeout: If clang does not complete before timeout_seconds. """ builtin_cflags = ["-S", "-emit-llvm", "-o", "-"] with tempfile.NamedTemporaryFile( "w", prefix="phd_deeplearning_clgen_preprocessors_clang_", suffix=suffix) as f: f.write(src) f.flush() cmd = ( ["timeout", "-s9", str(timeout_seconds), str(clang.CLANG), f.name] + builtin_cflags + cflags) app.Log(2, "$ %s", " ".join(cmd)) process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) stdout, stderr = process.communicate() if process.returncode == 9: raise errors.ClangTimeout(f"Clang timed out after {timeout_seconds}s") elif process.returncode != 0: raise errors.ClangException(stderr) return stdout
def ClangPreprocess(text: str) -> str: try: return clang.StripPreprocessorLines( clanglib.Preprocess(text, CLANG_ARGS)) except llvm.LlvmError as e: raise errors.ClangException(str(e.stderr[:1024]))