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
37 changes: 34 additions & 3 deletions packages/cxx-frontend/src/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ interface ParserParams {
export class Parser {
#unit: Unit | undefined;
#ast: AST | undefined;
#pendingAST: Promise<AST> | undefined;

static async init({
wasm,
Expand Down Expand Up @@ -97,24 +98,54 @@ export class Parser {
this.#unit = cxx.createUnit(source, path, { resolve, readFile });
}

async parse() {
async parse(): Promise<AST> {
return await this.getASTAsync();
}

async emitIR(): Promise<string> {
const _ = await this.getASTAsync();
return this.#unit?.emitIR() ?? "";
}

async #parseHelper(): Promise<AST> {
if (this.#pendingAST) {
return await this.#pendingAST;
}

if (!this.#unit) {
return;
throw new Error("Parser has been disposed");
}

await this.#unit.parse();
this.#ast = AST.from(this.#unit.getHandle(), this);

const ast = AST.from(this.#unit.getHandle(), this);

if (!ast) {
throw new Error("Failed to create AST");
}

this.#ast = ast;

return ast;
}

dispose() {
this.#unit?.delete();
this.#unit = undefined;
this.#ast = undefined;
this.#pendingAST = undefined;
}

getUnitHandle(): number {
return this.#unit?.getUnitHandle() ?? 0;
}

async getASTAsync(): Promise<AST> {
this.#pendingAST ??= this.#parseHelper();
return await this.#pendingAST;
}

// internal
getAST(): AST | undefined {
return this.#ast;
}
Expand Down
1 change: 1 addition & 0 deletions packages/cxx-frontend/src/Unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ export interface Unit {
getHandle(): number;
getUnitHandle(): number;
getDiagnostics(): Diagnostic[];
emitIR(): string;
}
1 change: 1 addition & 0 deletions packages/cxx-frontend/src/cxx-js.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export type CXX = {
TranslationUnit: TranslationUnit;

createUnit(source: string, path: string, api: Api): Unit;
emitIR(handle: number): string;
getASTKind(handle: number): number;
getASTSlot(handle: number, slot: number): number;
getASTSlotKind(handle: number, slot: number): ASTSlotKind;
Expand Down
1 change: 0 additions & 1 deletion src/frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ add_executable(cxx
target_link_libraries(cxx PRIVATE cxx-lsp)

if (CXX_ENABLE_MLIR)
target_compile_definitions(cxx PRIVATE CXX_WITH_MLIR)
target_link_libraries(cxx PRIVATE cxx-mlir)
endif()

Expand Down
4 changes: 4 additions & 0 deletions src/js/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ add_executable(cxx-js ${SOURCES})

target_link_libraries(cxx-js cxx-parser embind)

if (CXX_ENABLE_MLIR)
target_link_libraries(cxx-js cxx-mlir)
endif()

target_link_options(cxx-js PUBLIC
"SHELL:-s ENVIRONMENT=web"
"SHELL:-s MINIMAL_RUNTIME"
Expand Down
35 changes: 34 additions & 1 deletion src/js/cxx/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@
#include <optional>
#include <sstream>

#ifdef CXX_WITH_MLIR
#include <cxx/mlir/codegen.h>
#include <cxx/mlir/cxx_dialect.h>
#include <llvm/Support/raw_os_ostream.h>
#include <mlir/IR/MLIRContext.h>
#endif

using namespace emscripten;

namespace {
Expand Down Expand Up @@ -179,6 +186,31 @@ struct WrappedUnit {

co_return val{true};
}

auto emitIR() -> std::string {
#ifdef CXX_WITH_MLIR
mlir::MLIRContext context;
context.loadDialect<mlir::cxx::CxxDialect>();

cxx::Codegen codegen(context, unit.get());

auto ir = codegen(unit->ast());

mlir::OpPrintingFlags flags;
flags.enableDebugInfo(true, true);

std::ostringstream out;
llvm::raw_os_ostream os(out);
ir.module->print(os, flags);
os.flush();

auto code = out.str();

return code;
#else
return {};
#endif
}
};

auto getTokenText(std::intptr_t handle, std::intptr_t unitHandle)
Expand Down Expand Up @@ -381,7 +413,8 @@ EMSCRIPTEN_BINDINGS(cxx) {
.function("parse", &WrappedUnit::parse)
.function("getHandle", &WrappedUnit::getHandle)
.function("getUnitHandle", &WrappedUnit::getUnitHandle)
.function("getDiagnostics", &WrappedUnit::getDiagnostics);
.function("getDiagnostics", &WrappedUnit::getDiagnostics)
.function("emitIR", &WrappedUnit::emitIR);

function("createUnit", &createUnit, allow_raw_pointers());
function("getASTKind", &getASTKind);
Expand Down
3 changes: 3 additions & 0 deletions src/mlir/cxx/mlir/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ target_link_libraries(cxx-mlir PUBLIC
MLIRControlFlowDialect
MLIRSCFDialect
)

target_compile_definitions(cxx-mlir PUBLIC CXX_WITH_MLIR)

add_dependencies(cxx-mlir MLIRCxxOpsIncGen)

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
Expand Down
4 changes: 1 addition & 3 deletions templates/cxx-browser-esm-vite/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,10 @@ async function main() {
source,
});

parser.parse();
const ast = await parser.parse();

const rows: string[] = [];

const ast = parser.getAST();

for (const { node, depth } of ast?.walk().preVisit() ?? []) {
if (!(node instanceof AST)) {
continue;
Expand Down
6 changes: 2 additions & 4 deletions templates/cxx-parse-esm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,16 @@ async function main() {

const parser = new Parser({ source, path: "source.cc" });

await parser.parse();
const ast = await parser.parse();

const diagnostics = parser.getDiagnostics();

if (diagnostics.length > 0) {
console.log("diagnostics", diagnostics);
}

const ast = parser.getAST();

for (const { node, slot, depth } of ast?.walk().preVisit() ?? []) {
if (!node instanceof AST) continue;
if (!(node instanceof AST)) continue;
const ind = " ".repeat(depth * 2);
const kind = ASTKind[node.getKind()];
const member = slot !== undefined ? `${ASTSlot[slot]}: ` : "";
Expand Down
2 changes: 1 addition & 1 deletion templates/cxx-parse/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async function main() {
const ast = parser.getAST();

for (const { node, slot, depth } of ast?.walk().preVisit() ?? []) {
if (!node instanceof AST) continue;
if (!(node instanceof AST)) continue;
const ind = " ".repeat(depth * 2);
const kind = ASTKind[node.getKind()];
const member = slot !== undefined ? `${ASTSlot[slot]}: ` : "";
Expand Down