Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ bash scripts/build-vendor.sh

## What It Is

TypeScript-to-native compiler using LLVM IR. Compiles .ts/.js files to native binaries via: Parser → AST → Semantic Analysis → LLVM IR Codegen → llc (assembler) → clang (linker) → native binary.
TypeScript-to-native compiler using LLVM IR. Compiles .ts/.js files to native binaries via: Parser → AST → Semantic Analysis → LLVM IR Codegen → clang (compile + link) → native binary.

## Key Directories

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"coverage:report": "c8 report",
"format": "prettier --write .",
"format:check": "prettier --check .",
"prepare": "git config core.hooksPath .git/hooks && cp scripts/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit"
"prepare": "HOOKS=$(git rev-parse --git-common-dir)/hooks && git config core.hooksPath \"$HOOKS\" && cp scripts/pre-commit \"$HOOKS/pre-commit\" && chmod +x \"$HOOKS/pre-commit\""
},
"keywords": [
"compiler",
Expand Down
31 changes: 9 additions & 22 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,6 @@ export function compile(
logger.info(`InstalledDir: ${process.cwd()}`);

// Check for required build tools
const llcPath = findLLVMTool("llc");
const optPath = findLLVMTool("opt");
let linkerPath: string;
let useClang = true;

Expand Down Expand Up @@ -327,27 +325,23 @@ export function compile(
return;
}

// Compile IR to object file
// Compile IR to object file via clang (single pass: optimize + assemble)
const objFile = outputFile + ".o";
const sanitizeFlags = sanitize ? ` -fsanitize=${sanitize}` : "";
const llcStdio = logger.getLevel() >= LogLevel_Verbose ? "inherit" : "pipe";
const cpuFlag = crossCompiling ? `-mcpu=${target.cpu}` : `-mcpu=${targetCpu}`;
const tripleFlag = crossCompiling ? ` -mtriple=${target.triple}` : "";
const compileStdio = logger.getLevel() >= LogLevel_Verbose ? "inherit" : "pipe";
const cpuFlag = crossCompiling ? "" : `-march=${targetCpu}`;
const tripleFlag = crossCompiling ? ` --target=${target.triple}` : "";
const clangPath = useClang ? linkerPath : findLLVMTool("clang");
let compileCmd: string;
let optFile: string | null = null;
if (sanitize) {
compileCmd = `${linkerPath} -c${sanitizeFlags} ${irFile} -o ${objFile}`;
compileCmd = `${clangPath} -c -Wno-override-module${sanitizeFlags} ${irFile} -o ${objFile}`;
} else if (debugInfo) {
compileCmd = `${llcPath} -O0${tripleFlag} -filetype=obj ${irFile} -o ${objFile}`;
compileCmd = `${clangPath} -c -Wno-override-module -O0${tripleFlag} ${irFile} -o ${objFile}`;
} else {
optFile = irFile.replace(".ll", ".opt.bc");
const optCmd = `${optPath} -O2 ${cpuFlag}${tripleFlag} ${irFile} -o ${optFile}`;
logger.info(` ${optCmd}`);
execSync(optCmd, { stdio: llcStdio });
compileCmd = `${llcPath} -O2 ${cpuFlag}${tripleFlag} -filetype=obj ${optFile} -o ${objFile}`;
compileCmd = `${clangPath} -c -Wno-override-module -O2 ${cpuFlag}${tripleFlag} ${irFile} -o ${objFile}`;
}
logger.info(` ${compileCmd}`);
execSync(compileCmd, { stdio: llcStdio });
execSync(compileCmd, { stdio: compileStdio });

// Link to executable - only link libraries that the program actually uses.
// When cross-compiling, we use pre-built libraries from the target SDK
Expand Down Expand Up @@ -536,13 +530,6 @@ export function compile(
// File may already be deleted, ignore
}
}
if (optFile) {
try {
fs.unlinkSync(optFile);
} catch (e) {
// File may already be deleted, ignore
}
}
}

if (diagnosticsJson) {
Expand Down
31 changes: 14 additions & 17 deletions src/native-compiler-lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,28 +390,26 @@ export function compileNative(inputFile: string, outputFile: string): void {
}

const objFile = outputFile + ".o";
const optFile = irFile.replace(".ll", ".opt.bc");
const optTool = findLLVMTool("opt");
const llcTool = findLLVMTool("llc");
const clangTool = findLLVMTool("clang");

// Cross-compilation: add triple flags to opt/llc
const cpuFlag = crossCompiling ? "-mcpu=generic" : "-mcpu=" + targetCpu;
const tripleFlag = crossCompiling ? " -mtriple=" + targetTriple : "";
const cpuFlag = crossCompiling ? "" : "-march=" + targetCpu;
const tripleFlag = crossCompiling ? " --target=" + targetTriple : "";

const optCmd = optTool + " -O2 " + cpuFlag + tripleFlag + " " + irFile + " -o " + optFile;
if (verbose) {
console.log("Running: " + optCmd);
}
child_process.execSync(optCmd);
const llcCmd =
llcTool + " -O2 " + cpuFlag + tripleFlag + " -filetype=obj " + optFile + " -o " + objFile;
const compileCmd =
clangTool +
" -c -Wno-override-module -O2 " +
cpuFlag +
tripleFlag +
" " +
irFile +
" -o " +
objFile;
if (verbose) {
console.log("Running: " + llcCmd);
console.log("Running: " + compileCmd);
}
child_process.execSync(llcCmd);
child_process.execSync(compileCmd);
if (!fs.existsSync(objFile)) {
console.log("Error: llc failed to produce " + objFile);
console.log("Error: clang failed to produce " + objFile);
process.exit(1);
}

Expand Down Expand Up @@ -630,7 +628,6 @@ export function compileNative(inputFile: string, outputFile: string): void {
}

fs.unlinkSync(objFile);
fs.unlinkSync(optFile);
if (verbose) {
console.log("Compiled: " + outputFile);
}
Expand Down
Loading