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
79 changes: 79 additions & 0 deletions docs/how/debug/debug-shared.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
@echo off
rem ============================================================================
rem Repro + lldb launcher for the shared-component (test-compile-shared-component)
rem loader crash. Builds shared.dll + use_shared.exe with the STATIC-CRT link
rem line (matching the CRT fix) and KEEPS them, then opens lldb stopped ready to
rem hit the access violation.
rem
rem Usage: debug-shared.bat (builds, then launches lldb)
rem debug-shared.bat build (build only, no debugger)
rem debug-shared.bat run (just run use_shared.exe, show exit code)
rem ============================================================================
setlocal

rem --- Python 3.10 so lldb can load (needs python310.dll + a clean stdlib path) ---
set "PY310=C:\Users\duzha\AppData\Local\Python\pythoncore-3.10-64"
set "PATH=%PY310%;%PATH%"
set "PYTHONHOME=%PY310%"
set "PYTHONPATH="

rem --- toolchain / lib paths (from the test harness compiled.bat) ---
set "WORK=%~dp0"
set "TESTS=I:\TypeScriptCompiler\tslang\test\tester\tests"
set "tslangEXEPATH=I:\TypeScriptCompiler\__build\tslang\msbuild\x64\debug\bin"
set "tslang_LIB_PATH=I:\TypeScriptCompiler\__build\tslang\msbuild\x64\debug\lib"
set "LLVMEXEPATH=I:\TypeScriptCompiler\3rdParty\llvm\x64\debug\bin"
set "LLVM_LIB_PATH=I:\TypeScriptCompiler\3rdParty\llvm\x64\debug\lib"
set "GC_LIB_PATH=I:\TypeScriptCompiler\3rdParty\gc\x64\debug"
set "LIBPATH=C:\Program Files\Microsoft Visual Studio\18\Professional\VC\Tools\MSVC\14.51.36231\lib\x64"
set "SDKPATH=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\um\x64"
set "UCRTPATH=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\ucrt\x64"

rem --- STATIC CRT link line (matches the test-runner.cpp fix) ---
set "LIBS=libcmtd.lib libvcruntimed.lib libucrtd.lib ntdll.lib TypeScriptAsyncRuntime.lib gc.lib LLVMSupport.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib"
set "LIBPATHS=/libpath:"%GC_LIB_PATH%" /libpath:"%LLVM_LIB_PATH%" /libpath:"%tslang_LIB_PATH%" /libpath:"%LIBPATH%" /libpath:"%SDKPATH%" /libpath:"%UCRTPATH%""

cd /d "%WORK%"

if /i "%~1"=="run" goto run

rem NOTE: WinDbg/cdb need CodeView, NOT DWARF -- do NOT pass --lldb here (that
rem emits DWARF and cdb can't read it). /DEBUG on the link produces the .pdb.
echo === [1/4] compile shared.ts -^> shared.obj ===
"%tslangEXEPATH%\tslang.exe" --emit=obj --di --opt_level=0 "%TESTS%\shared.ts" -o=shared.obj || goto err

echo === [2/4] link shared.dll ===
"%LLVMEXEPATH%\lld.exe" -flavor link /out:shared.dll /DLL /DEBUG shared.obj %LIBS% %LIBPATHS% || goto err

echo === [3/4] compile use_shared.ts -^> use_shared.obj ===
"%tslangEXEPATH%\tslang.exe" --emit=obj --di --opt_level=0 "%TESTS%\use_shared.ts" -o=use_shared.obj || goto err

echo === [4/4] link use_shared.exe ===
"%LLVMEXEPATH%\lld.exe" -flavor link /out:use_shared.exe /DEBUG use_shared.obj %LIBS% %LIBPATHS% || goto err

echo.
echo Built: %WORK%use_shared.exe (+ shared.dll)
echo.

if /i "%~1"=="build" goto done

:debug
echo === launching cdb (Microsoft symbols; stops on the access violation) ===
echo it will auto: continue, show regs, stack, then drop to interactive prompt
echo.
set "_NT_SYMBOL_PATH=srv*C:\symbols*https://msdl.microsoft.com/download/symbols"
"C:\Users\duzha\AppData\Local\Microsoft\WindowsApps\cdbX64.exe" -c "g; .echo ===FAULT===; r; .echo ===STACK===; kn 40" "%WORK%use_shared.exe"
goto done

:run
echo === running use_shared.exe ===
"%WORK%use_shared.exe"
echo EXITCODE=%ERRORLEVEL%
goto done

:err
echo *** BUILD FAILED (errorlevel %ERRORLEVEL%) ***
exit /b 1

:done
endlocal
25 changes: 21 additions & 4 deletions tslang/lib/TypeScript/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2912,10 +2912,27 @@ struct ArithmeticBinaryOpLowering : public TsLlvmPattern<mlir_ts::ArithmeticBina
{
using TsLlvmPattern<mlir_ts::ArithmeticBinaryOp>::TsLlvmPattern;

// JS shift operators (<<, >>, >>>) use only the low 5 bits of the shift amount
// (i.e. count & 31 for 32-bit operands). LLVM's shl/ashr/lshr are undefined
// behavior when the shift amount >= the operand's bit width, so without this
// mask, optimized (-O) builds can produce garbage for e.g. `10 << 100`.
static mlir::Value maskShiftAmount(mlir::Location loc, mlir::Value shiftAmount, ConversionPatternRewriter &rewriter)
{
auto intType = dyn_cast<mlir::IntegerType>(shiftAmount.getType());
if (!intType)
{
return shiftAmount;
}

auto mask = rewriter.create<arith::ConstantOp>(
loc, intType, rewriter.getIntegerAttr(intType, intType.getWidth() - 1));
return rewriter.create<arith::AndIOp>(loc, shiftAmount, mask);
}

LogicalResult matchAndRewrite(mlir_ts::ArithmeticBinaryOp arithmeticBinaryOp, Adaptor transformed,
ConversionPatternRewriter &rewriter) const final
{


auto opCode = (SyntaxKind)arithmeticBinaryOp.getOpCode();
switch (opCode)
Expand Down Expand Up @@ -2946,15 +2963,15 @@ struct ArithmeticBinaryOpLowering : public TsLlvmPattern<mlir_ts::ArithmeticBina

case SyntaxKind::GreaterThanGreaterThanToken:
return BinOp<mlir_ts::ArithmeticBinaryOp, arith::ShRSIOp, arith::ShRSIOp, arith::ShRUIOp>(
arithmeticBinaryOp, transformed.getOperand1(), transformed.getOperand2(), rewriter);
arithmeticBinaryOp, transformed.getOperand1(), maskShiftAmount(arithmeticBinaryOp->getLoc(), transformed.getOperand2(), rewriter), rewriter);

case SyntaxKind::GreaterThanGreaterThanGreaterThanToken:
return BinOp<mlir_ts::ArithmeticBinaryOp, arith::ShRUIOp, arith::ShRUIOp>(
arithmeticBinaryOp, transformed.getOperand1(), transformed.getOperand2(), rewriter);
arithmeticBinaryOp, transformed.getOperand1(), maskShiftAmount(arithmeticBinaryOp->getLoc(), transformed.getOperand2(), rewriter), rewriter);

case SyntaxKind::LessThanLessThanToken:
return BinOp<mlir_ts::ArithmeticBinaryOp, arith::ShLIOp, arith::ShLIOp>(arithmeticBinaryOp, transformed.getOperand1(),
transformed.getOperand2(), rewriter);
maskShiftAmount(arithmeticBinaryOp->getLoc(), transformed.getOperand2(), rewriter), rewriter);

case SyntaxKind::AmpersandToken:
return BinOp<mlir_ts::ArithmeticBinaryOp, arith::AndIOp, arith::AndIOp>(arithmeticBinaryOp, transformed.getOperand1(),
Expand Down
15 changes: 9 additions & 6 deletions tslang/lib/TypeScript/MLIRGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9749,13 +9749,13 @@ class MLIRGenImpl
result = leftInt * rightInt;
break;
case SyntaxKind::LessThanLessThanToken:
result = leftInt << rightInt;
result = leftInt << rightInt.urem(leftInt.getBitWidth());
break;
case SyntaxKind::GreaterThanGreaterThanToken:
result = leftInt.ashr(rightInt);
result = leftInt.ashr(rightInt.urem(leftInt.getBitWidth()));
break;
case SyntaxKind::GreaterThanGreaterThanGreaterThanToken:
result = leftInt.lshr(rightInt);
result = leftInt.lshr(rightInt.urem(leftInt.getBitWidth()));
break;
case SyntaxKind::AmpersandToken:
result = leftInt & rightInt;
Expand Down Expand Up @@ -9813,14 +9813,17 @@ class MLIRGenImpl
case SyntaxKind::AsteriskToken:
result = leftFloat * rightFloat;
break;
// JS bitwise/shift operators coerce both operands to Int32, so the shift
// amount is masked mod 32 here regardless of the 64-bit APSInt width used
// above to stage the float->int conversion.
case SyntaxKind::LessThanLessThanToken:
resultAPInt = leftAPInt.shl(rightAPInt);
resultAPInt = leftAPInt.shl(rightAPInt.urem(32));
break;
case SyntaxKind::GreaterThanGreaterThanToken:
resultAPInt = leftAPInt.ashr(rightAPInt);
resultAPInt = leftAPInt.ashr(rightAPInt.urem(32));
break;
case SyntaxKind::GreaterThanGreaterThanGreaterThanToken:
resultAPInt = leftAPInt.lshr(rightAPInt);
resultAPInt = leftAPInt.lshr(rightAPInt.urem(32));
break;
case SyntaxKind::AmpersandToken:
resultAPInt = leftAPInt & rightAPInt;
Expand Down
43 changes: 43 additions & 0 deletions tslang/tslang/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,49 @@
}
}
},
{
"name": "(Windows) tslang.exe - EXE(DI)",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/../../__build/tslang/windows-msbuild-2026-debug/bin/tslang.exe",
"args": [
"-emit=exe",
"--di",
"-mtriple=x86_64-pc-windows-msvc",
"--nowarn",
"I:/TypeScriptCompilerDefaultLib/tests/array_copyWithin.ts",
],
"stopAtEntry": false,
"cwd": "I:/Playground",
"environment": [
{
"name": "GC_LIB_PATH",
"value": "${workspaceFolder}/../../__build/gc/msbuild/x64/debug/Debug"
},
{
"name": "LLVM_LIB_PATH",
"value": "${workspaceFolder}/../../__build/llvm/msbuild/x64/debug/Debug/lib"
},
{
"name": "TSLANG_LIB_PATH",
"value": "${workspaceFolder}/../../__build/tslang/windows-msbuild-2026-debug/lib"
},
],
"console": "externalTerminal",
"visualizerFile": "${workspaceFolder}/../tslang.natvis",
"symbolOptions": {
"searchPaths": [
"C:/symbols",
"${workspaceFolder}/../../__build/tslang/windows-msbuild-2026-debug/bin"
],
"searchMicrosoftSymbolServer": true,
"cachePath": "C:/symbols",
"moduleFilter": {
"mode": "loadAllButExcluded",
"excludedModules": [ "DoNotLookForThisOne*.dll" ]
}
}
},
{
"name": "(Windows) tslang.exe - EXE(OPT) - NO DEFAULT",
"type": "cppvsdbg",
Expand Down
13 changes: 2 additions & 11 deletions tslang/tslang/exe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,11 +356,6 @@ int buildExe(int argc, char **argv, std::string objFileName, std::string additio
args.push_back(additionalObjFileName.c_str());
}

if (win && shared)
{
//args.push_back("-Wl,-nodefaultlib:libcmt");
}

if (outputFilename.empty())
{
outputFilename = getDefaultOutputFileName(emitAction);
Expand Down Expand Up @@ -450,12 +445,14 @@ int buildExe(int argc, char **argv, std::string objFileName, std::string additio
args.push_back("-llibucrt");
args.push_back("-llibcmt");
args.push_back("-llibvcruntime");
args.push_back("-Wl,-nodefaultlib:libcmtd");
}
else
{
args.push_back("-llibucrtd");
args.push_back("-llibcmtd");
args.push_back("-llibvcruntimed");
args.push_back("-Wl,-nodefaultlib:libcmt");
}

args.push_back("-lntdll");
Expand Down Expand Up @@ -552,12 +549,6 @@ int buildExe(int argc, char **argv, std::string objFileName, std::string additio
theDriver.setTargetAndMode(targetAndMode);
std::unique_ptr<clang::driver::Compilation> c(theDriver.BuildCompilation(args));

if (win && (shared || !disableGC))
{
args.push_back("-Wl,-nodefaultlib:libcmt");
removeCommandArgs(c.get(), {"defaultlib:libcmt"});
}

if (wasm)
{
if (emscripten)
Expand Down
Loading