From f3f12e2d48196dc93a9da577bb1d3cb7680154ed Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 14 Dec 2024 16:55:35 +0000 Subject: [PATCH] Allow passing target to codegen --- editors/README.md | 5 +- editors/code/src/bytecode.ts | 77 +++++++++++++++++++++++------ src/LanguageServer.cpp | 2 +- src/include/Protocol/Extensions.hpp | 22 ++++++++- src/operations/Bytecode.cpp | 25 ++++++++-- 5 files changed, 111 insertions(+), 20 deletions(-) diff --git a/editors/README.md b/editors/README.md index 46c7f2fa..a91af13b 100644 --- a/editors/README.md +++ b/editors/README.md @@ -164,6 +164,9 @@ A custom LSP request message is implemented: - `luau-lsp/bytecode`: `{ textDocument: TextDocumentIdentifier, optimizationLevel: number }`, returns `string` - textual bytecode output - `luau-lsp/compilerRemarks`: `{ textDocument: TextDocumentIdentifier, optimizationLevel: number }`, returns `string` - source code with inline remarks as comments -- `luau-lsp/codeGen`: `{ textDocument: TextDocumentIdentifier, optimizationLevel: number }`, returns `string` - annotated codegen instructions +- `luau-lsp/codeGen`: `{ textDocument: TextDocumentIdentifier, optimizationLevel: number, codeGenTarget: string }`, + returns `string` - annotated codegen instructions + +`codeGenTarget` can be one of: `"host" | "a64" | "a64_nofeatures" | "x64_windows" | "x64_systemv"` You can implement this request via a custom command to surface this information in your editor diff --git a/editors/code/src/bytecode.ts b/editors/code/src/bytecode.ts index 6d763abe..5b15744d 100644 --- a/editors/code/src/bytecode.ts +++ b/editors/code/src/bytecode.ts @@ -22,7 +22,7 @@ export type BytecodeParams = { }; export const BytecodeRequest = new RequestType( - "luau-lsp/bytecode", + "luau-lsp/bytecode" ); export type CompilerRemarksParams = { @@ -36,9 +36,17 @@ export const ComputeCompilerRemarksRequest = new RequestType< void >("luau-lsp/compilerRemarks"); +export type CodeGenTarget = + | "host" + | "a64" + | "a64_nofeatures" + | "x64_windows" + | "x64_systemv"; + export type CodeGenParams = { textDocument: TextDocumentIdentifier; optimizationLevel: OptimizationLevel; + codeGenTarget: CodeGenTarget; }; export const ComputeCodeGenRequest = new RequestType< @@ -70,7 +78,7 @@ export const getOptimizationLevel = async (): Promise => { { title: "Select Optimization Level", placeHolder: "Select optimization level", - }, + } ); return optimizationLevel?.label === "None" @@ -82,7 +90,43 @@ export const getOptimizationLevel = async (): Promise => { : OptimizationLevel.O1; }; +export const getCodeGenTarget = async (): Promise => { + const optimizationLevel = await vscode.window.showQuickPick( + [ + { + label: "host", + detail: "Host target", + picked: true, + }, + + { + label: "a64", + detail: "Arm64", + }, + { + label: "a64_nofeatures", + detail: "Arm64 (No Features)", + }, + { + label: "x64_windows", + detail: "x64 Windows", + }, + { + label: "x64_systemv", + detail: "x64 SystemV", + }, + ], + { + title: "Select CodeGen target", + placeHolder: "Select CodeGen target", + } + ); + + return (optimizationLevel?.label as CodeGenTarget) ?? "host"; +}; + let optimizationLevel = OptimizationLevel.O2; +let codeGenTarget: CodeGenTarget = "host"; // Based off https://github.com/rust-lang/rust-analyzer/blob/a24ede2066778f66b5b5e5aa7aa57a6d1be2063a/editors/code/src/commands.ts // Licensed under MIT @@ -110,10 +154,10 @@ const getBytecodeInfo = ( scheme: string, fileName: string, requestType: RequestType< - CompilerRemarksParams | BytecodeParams, + CompilerRemarksParams | BytecodeParams | CodeGenParams, string, void - >, + > ) => { const tdcp = new (class implements vscode.TextDocumentContentProvider { readonly uri = vscode.Uri.parse(`${scheme}://bytecode/${fileName}.luau`); @@ -123,12 +167,12 @@ const getBytecodeInfo = ( vscode.workspace.onDidChangeTextDocument( this.onDidChangeTextDocument, this, - context.subscriptions, + context.subscriptions ); vscode.window.onDidChangeActiveTextEditor( this.onDidChangeActiveTextEditor, this, - context.subscriptions, + context.subscriptions ); } @@ -153,9 +197,10 @@ const getBytecodeInfo = ( const params = { textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier( - editor.document, + editor.document ), optimizationLevel, + codeGenTarget, }; return client.sendRequest(requestType, params); @@ -174,6 +219,10 @@ const getBytecodeInfo = ( if (isLuauEditor(textEditor)) { optimizationLevel = await getOptimizationLevel(); + if (command === "luau-lsp.computeCodeGen") { + codeGenTarget = await getCodeGenTarget(); + } + const doc = await vscode.workspace.openTextDocument(tdcp.uri); tdcp.eventEmitter.fire(tdcp.uri); await vscode.window.showTextDocument(doc, { @@ -181,14 +230,14 @@ const getBytecodeInfo = ( preserveFocus: true, }); } - }, + } ), ]; }; export const registerComputeBytecode = ( context: vscode.ExtensionContext, - client: LanguageClient, + client: LanguageClient ): vscode.Disposable[] => { return getBytecodeInfo( context, @@ -196,13 +245,13 @@ export const registerComputeBytecode = ( "luau-lsp.computeBytecode", BYTECODE_SCHEME, "bytecode", - BytecodeRequest, + BytecodeRequest ); }; export const registerComputeCompilerRemarks = ( context: vscode.ExtensionContext, - client: LanguageClient, + client: LanguageClient ): vscode.Disposable[] => { return getBytecodeInfo( context, @@ -210,13 +259,13 @@ export const registerComputeCompilerRemarks = ( "luau-lsp.computeCompilerRemarks", COMPILER_REMARKS_SCHEME, "compiler-remarks", - ComputeCompilerRemarksRequest, + ComputeCompilerRemarksRequest ); }; export const registerComputeCodeGen = ( context: vscode.ExtensionContext, - client: LanguageClient, + client: LanguageClient ): vscode.Disposable[] => { return getBytecodeInfo( context, @@ -224,6 +273,6 @@ export const registerComputeCodeGen = ( "luau-lsp.computeCodeGen", CODEGEN_SCHEME, "codeGen", - ComputeCodeGenRequest, + ComputeCodeGenRequest ); }; diff --git a/src/LanguageServer.cpp b/src/LanguageServer.cpp index db7eb5ad..0c6c0eec 100644 --- a/src/LanguageServer.cpp +++ b/src/LanguageServer.cpp @@ -265,7 +265,7 @@ void LanguageServer::onRequest(const id_type& id, const std::string& method, std auto workspace = findWorkspace(params.textDocument.uri); response = workspace->compilerRemarks(params); } - else if (method == "luau-lsp/codegen") + else if (method == "luau-lsp/codeGen") { ASSERT_PARAMS(baseParams, "luau-lsp/codeGen") auto params = baseParams->get(); diff --git a/src/include/Protocol/Extensions.hpp b/src/include/Protocol/Extensions.hpp index 344d5f68..0f02d3ae 100644 --- a/src/include/Protocol/Extensions.hpp +++ b/src/include/Protocol/Extensions.hpp @@ -29,12 +29,32 @@ NLOHMANN_DEFINE_OPTIONAL(CompilerRemarksParams, textDocument, optimizationLevel) using CompilerRemarksResult = std::string; +// Based off Luau::CodeGen::AssemblyOptions::Target +enum struct CodeGenTarget +{ + Host, + A64, + A64_NoFeatures, + X64_Windows, + X64_SystemV +}; + +NLOHMANN_JSON_SERIALIZE_ENUM(CodeGenTarget, { + {CodeGenTarget::Host, "host"}, + {CodeGenTarget::A64, "a64"}, + {CodeGenTarget::A64_NoFeatures, "a64_nofeatures"}, + {CodeGenTarget::X64_Windows, "x64_windows"}, + {CodeGenTarget::X64_SystemV, "x64_systemv"}, + }) + + struct CodegenParams { TextDocumentIdentifier textDocument; CompilerRemarksOptimizationLevel optimizationLevel = CompilerRemarksOptimizationLevel::O1; + CodeGenTarget codeGenTarget = CodeGenTarget::Host; }; -NLOHMANN_DEFINE_OPTIONAL(CodegenParams, textDocument, optimizationLevel) +NLOHMANN_DEFINE_OPTIONAL(CodegenParams, textDocument, optimizationLevel, codeGenTarget) using CodegenResult = std::string; } // namespace lsp diff --git a/src/operations/Bytecode.cpp b/src/operations/Bytecode.cpp index e02aebe9..7607c2de 100644 --- a/src/operations/Bytecode.cpp +++ b/src/operations/Bytecode.cpp @@ -57,7 +57,25 @@ static uint32_t flagsForType(BytecodeOutputType type) return 0; } -static std::string computeBytecodeOutput(const Luau::ModuleName& moduleName, const std::string& source, const ClientConfiguration& config, int optimizationLevel, BytecodeOutputType type) +static Luau::CodeGen::AssemblyOptions::Target getCodeGenTarget(const lsp::CodeGenTarget& codeGenTarget) +{ + switch (codeGenTarget) + { + case lsp::CodeGenTarget::Host: + return Luau::CodeGen::AssemblyOptions::Target::Host; + case lsp::CodeGenTarget::A64: + return Luau::CodeGen::AssemblyOptions::Target::A64; + case lsp::CodeGenTarget::A64_NoFeatures: + return Luau::CodeGen::AssemblyOptions::Target::A64_NoFeatures; + case lsp::CodeGenTarget::X64_Windows: + return Luau::CodeGen::AssemblyOptions::Target::X64_Windows; + case lsp::CodeGenTarget::X64_SystemV: + return Luau::CodeGen::AssemblyOptions::Target::X64_SystemV; + } +} + +static std::string computeBytecodeOutput(const Luau::ModuleName& moduleName, const std::string& source, const ClientConfiguration& config, + int optimizationLevel, BytecodeOutputType type, lsp::CodeGenTarget codeGenTarget = lsp::CodeGenTarget::Host) { try { @@ -85,7 +103,7 @@ static std::string computeBytecodeOutput(const Luau::ModuleName& moduleName, con if (type == BytecodeOutputType::CodeGen) { Luau::CodeGen::AssemblyOptions assemblyOptions; - // TODO: assemblyOptions target + assemblyOptions.target = getCodeGenTarget(codeGenTarget); assemblyOptions.outputBinary = false; assemblyOptions.includeAssembly = true; assemblyOptions.includeIr = true; @@ -143,5 +161,6 @@ lsp::CompilerRemarksResult WorkspaceFolder::codeGen(const lsp::CodegenParams& pa throw JsonRpcException(lsp::ErrorCode::RequestFailed, "No managed text document for " + params.textDocument.uri.toString()); auto config = client->getConfiguration(rootUri); - return computeBytecodeOutput(moduleName, textDocument->getText(), config, params.optimizationLevel, BytecodeOutputType::CodeGen); + return computeBytecodeOutput( + moduleName, textDocument->getText(), config, params.optimizationLevel, BytecodeOutputType::CodeGen, params.codeGenTarget); }