Files
work-ts/compiler.ts

116 lines
2.8 KiB
TypeScript

import child_process from "child_process"
import { PlatformPath } from "path"
import path from "path"
// FIXME: these imports basically looks ugly.
import { LLVM_EXTRACT, PREFIX, SYSROOT_PREFIX, FLANG } from "./environment";
/**
* 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
}
/**
* 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 = [
FLANG,
...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) })
}