import child_process from "child_process" import { PlatformPath } from "path" import path from "path" const PREFIX = "/home/lyc/workspace/sw-autovec/swllvm-13.0.0-vect0919/local/installed/85e4fed0c9e4cd4ab8bce89f307127ccbad31294" const PREFIXBIN = path.join(PREFIX, "bin") const LLVM_EXTRACT = path.join(PREFIXBIN, "llvm-extract") const SYSROOT_PREFIX = "/usr/sw/standard-830-6b-test" const CXX = path.join(PREFIXBIN, "clang++") const CC = path.join(PREFIXBIN, "clang") const FC = path.join(PREFIXBIN, "flang") const SYSROOT_COMMAND = [ "--sysroot", SYSROOT_PREFIX, ] /** * Helper function to generate output options for the linker. * @param exe Executable file name. * @returns Array of options to be passed to the linker. */ function driverOutput(exe: string): string[] { return ["-o", exe]; } export function functionList(module: string) { let result: string[] = []; // Split the LLVM module string by lines const lines = module.split('\n') lines.forEach(line => { if (line.startsWith('define')) { let begin = line.indexOf('@'); let end = line.indexOf('('); result.push(line.substring(begin + 1, end).trim()); } }); return result; } /** * CLI options used for llvm-extract executable. */ export interface ExtractOptions { /** * Functions to extract. */ func?: string[] /** * Basic block specifiers. */ bb?: string[] output?: string /** * Input file name. If unspecified, llvm-extract reads from stdin */ input?: string asm?: boolean } export function extractCommand(options: ExtractOptions): string[] { return [ ...(options.func ?? []).flatMap(name => ["--func", name]), ...(options.bb ?? []).flatMap(name => ["--bb", name]), ...(options.output ? ["-o", options.output] : []), ...(options.asm ? ["-S"] : []), ...(options.input ? [options.input] : []) ]; } /** * Extract one function using llvm-extract */ export async function extract(options: ExtractOptions) { let process = child_process.spawn( LLVM_EXTRACT, extractCommand(options), { stdio: "inherit" } ) const exitcode = await new Promise((resolve, reject) => { process.on('close', resolve) }) return exitcode } export interface GeneralOptions { output?: string; outputKind?: "exe" | "object" | "assembly" | "preprocessed" } export function generalCommand(options: GeneralOptions) { return [ ...(options.output ? ["-o", options.output] : []), ...(options.outputKind ? { exe: [], object: ["-c"], assembly: ["-S"], preprocessed: ["-E"] }[options.outputKind] : []) ] } export interface PreprocessorOptions { includeDirs?: string[]; } export function preprocessorCommand(options: PreprocessorOptions) { return [ ...((options.includeDirs ?? []).flatMap(name => ["-I", name])) ] } /** * Links objects into an executable using specified environment variables and paths. * @param objects Array of object files to link. * @param exe Executable file name. */ export async function link(objects: string[], exe: string) { // Set up environment variables const linkenv = { ...process.env }; linkenv.LD_LIBRARY_PATH = [ path.join(PREFIX, 'lib'), path.join(SYSROOT_PREFIX, 'lib'), path.join(SYSROOT_PREFIX, 'usr', 'lib') ].join(':'); // Construct link command const linkcmd = [ FC, ...objects, "-L", path.join(PREFIX, 'lib'), // TODO: Implement rpath logic here if needed ...driverOutput(exe) ]; // Execute the link command child_process.spawn(linkcmd[0], linkcmd.slice(1), { stdio: 'inherit', env: linkenv }); return new Promise((resolve, reject) => { process.on('close', resolve) }) }