diff --git a/tslang/lib/TypeScript/MLIRGenStatements.cpp b/tslang/lib/TypeScript/MLIRGenStatements.cpp index 982ad9a61..f483c8add 100644 --- a/tslang/lib/TypeScript/MLIRGenStatements.cpp +++ b/tslang/lib/TypeScript/MLIRGenStatements.cpp @@ -1083,6 +1083,21 @@ namespace mlirgen GenContext thunkGenContext{}; thunkGenContext.funcOp = funcOp; + // A function of its own to the debugger as well. `location` is the throw or catch + // statement's, and carries that statement's debug scope - a lexical block of the + // function around it when the statement sits in a braced block. Left on the thunk and + // its body, LLVM rejected the module: the thunk got a subprogram of its own while its + // instructions still pointed into the other function's block. Same steps as + // mlirGenFunctionLikeDeclaration: a subprogram for the thunk, the body scoped under it. + DITableScopeT debugFuncScope(debugScope); + if (compileOptions.generateDebugInfo) + { + MLIRDebugInfoHelper mdi(builder, debugScope); + auto plainLocation = stripMetadata(location); + funcOp->setLoc(mdi.getSubprogram(plainLocation, name, name, plainLocation)); + location = locFuseWithScope(plainLocation); + } + auto &entryBlock = *funcOp.addEntryBlock(); builder.setInsertionPointToStart(&entryBlock); diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index 48f5d4d52..64f51d5db 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -392,6 +392,7 @@ tslang_add_test(NAME test-compile-00-throw-inlined COMMAND test-runner "${PROJEC tslang_add_test(NAME test-compile-00-try-catch-sequence-and-nesting COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00try_catch_sequence_and_nesting.ts") tslang_add_test(NAME test-compile-00-try-in-catch-with-finally COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00try_in_catch_with_finally.ts") tslang_add_test(NAME test-compile-00-throw-number-untyped-catch COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00throw_number_untyped_catch.ts") +tslang_add_test(NAME test-compile-00-throw-in-block-debug-info COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00throw_in_block_debug_info.ts") tslang_add_test(NAME test-compile-00-catch-untyped-value COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00catch_untyped_value.ts") tslang_add_test(NAME test-compile-00-throw-bool-bigint COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00throw_bool_bigint.ts") tslang_add_test(NAME test-compile-00-throw-f32 COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00throw_f32.ts") @@ -825,6 +826,7 @@ tslang_add_test(NAME test-jit-00-throw-inlined COMMAND test-runner -jit "${PROJE tslang_add_test(NAME test-jit-00-try-catch-sequence-and-nesting COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00try_catch_sequence_and_nesting.ts") tslang_add_test(NAME test-jit-00-try-in-catch-with-finally COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00try_in_catch_with_finally.ts") tslang_add_test(NAME test-jit-00-throw-number-untyped-catch COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00throw_number_untyped_catch.ts") +tslang_add_test(NAME test-jit-00-throw-in-block-debug-info COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00throw_in_block_debug_info.ts") tslang_add_test(NAME test-jit-00-catch-untyped-value COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00catch_untyped_value.ts") tslang_add_test(NAME test-jit-00-throw-bool-bigint COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00throw_bool_bigint.ts") tslang_add_test(NAME test-jit-00-throw-f32 COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00throw_f32.ts") @@ -1737,6 +1739,7 @@ set(TSLANG_CORPUS 00throw_bool_bigint.ts 00throw_f32.ts 00throw_u32.ts + 00throw_in_block_debug_info.ts 00throw_inlined.ts 00throw_number_untyped_catch.ts 00to_primitive_ops.ts diff --git a/tslang/test/tester/tests/00throw_in_block_debug_info.ts b/tslang/test/tester/tests/00throw_in_block_debug_info.ts new file mode 100644 index 000000000..8404094f2 --- /dev/null +++ b/tslang/test/tester/tests/00throw_in_block_debug_info.ts @@ -0,0 +1,33 @@ +// A class thrown from inside a braced block, with debug info on (the suite runs every test with +// --di). The block opens a lexical debug scope, and the catch copy thunk built for the throw +// used to inherit that scope: LLVM then rejected the module ("!dbg attachment points at wrong +// subprogram for function"). The thunk has to be a function of its own to the debugger too. +class Err { + constructor(public m: string) {} +} + +function f(n: number) { + if (n < 0) { + throw new Err("negative"); + } + + return n; +} + +function g(n: number) { + let caught = ""; + try { + f(n); + } catch (e: Err) { + caught = e.m; + } + + return caught; +} + +function main() { + assert(f(1) == 1, "f(1)"); + assert(g(-1) == "negative", "g(-1)"); + assert(g(2) == "", "g(2)"); + print("done."); +}