Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: codegen instructions #865

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]

### Added

- Added command `Luau: Compute CodeGen instructions for file` to emit annotated codegen instructions, similar to the bytecode command. External editors can implement this by using the `luau-lsp/codeGen` request. ([#617](https://github.com/JohnnyMorganz/luau-lsp/issues/617))

## [1.37.0] - 2024-12-14

### Added
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ set(EXTERN_INCLUDES extern/json/include extern/glob/single_include extern/argpar
target_compile_features(Luau.LanguageServer PUBLIC cxx_std_17)
target_compile_options(Luau.LanguageServer PRIVATE ${LUAU_LSP_OPTIONS})
target_include_directories(Luau.LanguageServer PUBLIC src/include ${EXTERN_INCLUDES})
target_link_libraries(Luau.LanguageServer PRIVATE Luau.Ast Luau.Analysis Luau.Compiler)
target_link_libraries(Luau.LanguageServer PRIVATE Luau.Ast Luau.Analysis Luau.Compiler Luau.VM Luau.CodeGen)

set_target_properties(Luau.LanguageServer.CLI PROPERTIES OUTPUT_NAME luau-lsp)
target_compile_features(Luau.LanguageServer.CLI PUBLIC cxx_std_17)
Expand Down
6 changes: 5 additions & 1 deletion editors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,15 @@ Further Reference:

## Optional: Bytecode generation

The Language server implements support for computing file-level textual bytecode and source code remarks, for lower level debugging features.
The Language server implements support for computing file-level textual bytecode, source code remarks, and codegen instructions for lower level debugging features.

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, 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
5 changes: 5 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@
"title": "Luau: Compute Compiler Remarks for file",
"enablement": "resourceLangId == luau"
},
{
"command": "luau-lsp.computeCodeGen",
"title": "Luau: Compute CodeGen instructions for file",
"enablement": "resourceLangId == luau"
},
{
"command": "luau-lsp.flushTimeTrace",
"title": "Luau: Flush Time Trace Events to tracing.json"
Expand Down
99 changes: 87 additions & 12 deletions editors/code/src/bytecode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {

export const BYTECODE_SCHEME = "luau-bytecode";
export const COMPILER_REMARKS_SCHEME = "luau-remarks";
export const CODEGEN_SCHEME = "luau-codegen";

enum OptimizationLevel {
None = 0,
Expand All @@ -21,7 +22,7 @@ export type BytecodeParams = {
};

export const BytecodeRequest = new RequestType<BytecodeParams, string, void>(
"luau-lsp/bytecode",
"luau-lsp/bytecode"
);

export type CompilerRemarksParams = {
Expand All @@ -35,6 +36,25 @@ 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<
CodeGenParams,
string,
void
>("luau-lsp/codeGen");

export const getOptimizationLevel = async (): Promise<OptimizationLevel> => {
const optimizationLevel = await vscode.window.showQuickPick(
[
Expand All @@ -58,7 +78,7 @@ export const getOptimizationLevel = async (): Promise<OptimizationLevel> => {
{
title: "Select Optimization Level",
placeHolder: "Select optimization level",
},
}
);

return optimizationLevel?.label === "None"
Expand All @@ -70,7 +90,43 @@ export const getOptimizationLevel = async (): Promise<OptimizationLevel> => {
: OptimizationLevel.O1;
};

export const getCodeGenTarget = async (): Promise<CodeGenTarget> => {
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
Expand Down Expand Up @@ -98,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`);
Expand All @@ -111,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
);
}

Expand All @@ -141,9 +197,10 @@ const getBytecodeInfo = (

const params = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(
editor.document,
editor.document
),
optimizationLevel,
codeGenTarget,
};

return client.sendRequest(requestType, params);
Expand All @@ -162,42 +219,60 @@ 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, {
viewColumn: vscode.ViewColumn.Two,
preserveFocus: true,
});
}
},
}
),
];
};

export const registerComputeBytecode = (
context: vscode.ExtensionContext,
client: LanguageClient,
client: LanguageClient
): vscode.Disposable[] => {
return getBytecodeInfo(
context,
client,
"luau-lsp.computeBytecode",
BYTECODE_SCHEME,
"bytecode",
BytecodeRequest,
BytecodeRequest
);
};

export const registerComputeCompilerRemarks = (
context: vscode.ExtensionContext,
client: LanguageClient,
client: LanguageClient
): vscode.Disposable[] => {
return getBytecodeInfo(
context,
client,
"luau-lsp.computeCompilerRemarks",
COMPILER_REMARKS_SCHEME,
"compiler-remarks",
ComputeCompilerRemarksRequest,
ComputeCompilerRemarksRequest
);
};

export const registerComputeCodeGen = (
context: vscode.ExtensionContext,
client: LanguageClient
): vscode.Disposable[] => {
return getBytecodeInfo(
context,
client,
"luau-lsp.computeCodeGen",
CODEGEN_SCHEME,
"codeGen",
ComputeCodeGenRequest
);
};
2 changes: 2 additions & 0 deletions editors/code/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {

import {
registerComputeBytecode,
registerComputeCodeGen,
registerComputeCompilerRemarks,
} from "./bytecode";

Expand Down Expand Up @@ -239,6 +240,7 @@ const startLanguageServer = async (context: vscode.ExtensionContext) => {

clientDisposables.push(...registerComputeBytecode(context, client));
clientDisposables.push(...registerComputeCompilerRemarks(context, client));
clientDisposables.push(...registerComputeCodeGen(context, client));

console.log("LSP Setup");
await client.start();
Expand Down
8 changes: 7 additions & 1 deletion src/LanguageServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,14 +258,20 @@ void LanguageServer::onRequest(const id_type& id, const std::string& method, std
auto workspace = findWorkspace(params.textDocument.uri);
response = workspace->bytecode(params);
}

else if (method == "luau-lsp/compilerRemarks")
{
ASSERT_PARAMS(baseParams, "luau-lsp/compilerRemarks")
auto params = baseParams->get<lsp::CompilerRemarksParams>();
auto workspace = findWorkspace(params.textDocument.uri);
response = workspace->compilerRemarks(params);
}
else if (method == "luau-lsp/codeGen")
{
ASSERT_PARAMS(baseParams, "luau-lsp/codeGen")
auto params = baseParams->get<lsp::CodegenParams>();
auto workspace = findWorkspace(params.textDocument.uri);
response = workspace->codeGen(params);
}
else
{
throw JsonRpcException(lsp::ErrorCode::MethodNotFound, "method not found / supported: " + method);
Expand Down
1 change: 1 addition & 0 deletions src/include/LSP/Workspace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class WorkspaceFolder

lsp::BytecodeResult bytecode(const lsp::BytecodeParams& params);
lsp::CompilerRemarksResult compilerRemarks(const lsp::CompilerRemarksParams& params);
lsp::CodegenResult codeGen(const lsp::CodegenParams& params);

bool isNullWorkspace() const
{
Expand Down
29 changes: 29 additions & 0 deletions src/include/Protocol/Extensions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,33 @@ struct CompilerRemarksParams
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, codeGenTarget)

using CodegenResult = std::string;
} // namespace lsp
Loading
Loading