diff --git a/tslang/lib/TypeScript/LowerToAffineLoops.cpp b/tslang/lib/TypeScript/LowerToAffineLoops.cpp index e8a7fffa..1b2454f1 100644 --- a/tslang/lib/TypeScript/LowerToAffineLoops.cpp +++ b/tslang/lib/TypeScript/LowerToAffineLoops.cpp @@ -2002,13 +2002,17 @@ class SwitchStateOpLowering : public TsPattern SmallVector caseDestinations; - SmallPtrSet stateLabels; + // Collect state labels in program (walk) order: dispatch below is positional + // (case N -> caseDestinations[N-1]), so an order-scrambling container here + // (e.g. SmallPtrSet, which only preserves insertion order below its inline + // capacity) would silently corrupt generator resume dispatch. + SmallVector stateLabels; // select all states auto visitorAllStateLabels = [&](Operation *op) { if (auto stateLabelOp = dyn_cast_or_null(op)) { - stateLabels.insert(op); + stateLabels.push_back(op); } }; diff --git a/tslang/lib/TypeScript/LowerToLLVM.cpp b/tslang/lib/TypeScript/LowerToLLVM.cpp index 4c230a37..50d976cd 100644 --- a/tslang/lib/TypeScript/LowerToLLVM.cpp +++ b/tslang/lib/TypeScript/LowerToLLVM.cpp @@ -584,7 +584,7 @@ class StringConcatOpLowering : public TsLlvmPattern auto allocInStack = op.getAllocInStack().has_value() && op.getAllocInStack().value() && !isInsidePresplitCoroutine(op); - mlir::Value newStringValue = allocInStack ? ch.Alloca(i8PtrTy, size, true) + mlir::Value newStringValue = allocInStack ? ch.Alloca(th.getI8Type(), size, true) : ch.MemoryAlloc(size); // copy @@ -2682,27 +2682,33 @@ struct ArraySpliceOpLowering : public TsLlvmPattern auto incSizeAsLLVMType = clh.createIndexConstantOf(llvmIndexType, transformed.getItems().size()); - mlir::Value newCountAsIndexType = rewriter.create(loc, indexType, ValueRange{countAsIndexType, decSizeAsIndexType}); - newCountAsIndexType = rewriter.create(loc, indexType, ValueRange{newCountAsIndexType, incSizeAsLLVMType}); + // Keep all arithmetic in the already-LLVM-converted domain (llvmIndexType), matching + // every sibling array-mutation lowering (ArrayPushOp/ArrayUnshiftOp/ArrayShiftOp) -- + // mlir::index::*Op ops require genuinely `index`-typed operands, but countAsIndexType + // (despite its name) is loaded as llvmIndexType, and incSizeAsLLVMType is already + // LLVM-typed, so mixing them into index:: ops here was a dialect-operand mismatch. + mlir::Value newCountAsLLVMType = rewriter.create(loc, llvmIndexType, ValueRange{countAsIndexType, decSizeAsLLVMType}); + newCountAsLLVMType = rewriter.create(loc, llvmIndexType, ValueRange{newCountAsLLVMType, incSizeAsLLVMType}); - auto sizeOfTypeValue = rewriter.create(loc, indexType, elementType); + auto sizeOfTypeValueMLIR = rewriter.create(loc, indexType, elementType); + auto sizeOfTypeValue = rewriter.create(loc, llvmIndexType, sizeOfTypeValueMLIR); auto multSizeOfTypeValue = - rewriter.create(loc, indexType, ValueRange{sizeOfTypeValue, newCountAsIndexType}); + rewriter.create(loc, llvmIndexType, ValueRange{sizeOfTypeValue, newCountAsLLVMType}); auto increaseArrayFunc = [&](OpBuilder &builder, Location location) -> mlir::Value { auto allocated = ch.MemoryRealloc(currentPtr, multSizeOfTypeValue); - auto moveCountAsIndexType = - rewriter.create(loc, indexType, ValueRange{countAsIndexType, startIndexAsIndexType}); - moveCountAsIndexType = - rewriter.create(loc, indexType, ValueRange{moveCountAsIndexType, decSizeAsIndexType}); + auto moveCountAsLLVMType = + rewriter.create(loc, llvmIndexType, ValueRange{countAsIndexType, startIndexAsLLVMType}); + moveCountAsLLVMType = + rewriter.create(loc, llvmIndexType, ValueRange{moveCountAsLLVMType, decSizeAsLLVMType}); // realloc auto offsetStart = rewriter.create(loc, ptrType, llvmElementType, allocated, ValueRange{startIndexAsLLVMType}); auto offsetFrom = rewriter.create(loc, ptrType, llvmElementType, offsetStart, ValueRange{decSizeAsLLVMType}); auto offsetTo = rewriter.create(loc, ptrType, llvmElementType, offsetStart, ValueRange{incSizeAsLLVMType}); - auto moveCountAsIndexTypeAdapt = rewriter.create(loc, indexType, moveCountAsIndexType); + auto moveCountAsIndexTypeAdapt = rewriter.create(loc, indexType, moveCountAsLLVMType); rewriter.create(loc, offsetTo, offsetFrom, moveCountAsIndexTypeAdapt); return allocated; @@ -2710,26 +2716,27 @@ struct ArraySpliceOpLowering : public TsLlvmPattern auto decreaseArrayFunc = [&](OpBuilder &builder, Location location) -> mlir::Value { - auto moveCountAsIndexType = - rewriter.create(loc, indexType, ValueRange{countAsIndexType, startIndexAsIndexType}); - moveCountAsIndexType = - rewriter.create(loc, indexType, ValueRange{moveCountAsIndexType, decSizeAsIndexType}); + auto moveCountAsLLVMType = + rewriter.create(loc, llvmIndexType, ValueRange{countAsIndexType, startIndexAsLLVMType}); + moveCountAsLLVMType = + rewriter.create(loc, llvmIndexType, ValueRange{moveCountAsLLVMType, decSizeAsLLVMType}); // realloc auto offsetStart = rewriter.create(loc, ptrType, llvmElementType, currentPtr, ValueRange{startIndexAsLLVMType}); auto offsetFrom = rewriter.create(loc, ptrType, llvmElementType, offsetStart, ValueRange{decSizeAsLLVMType}); auto offsetTo = rewriter.create(loc, ptrType, llvmElementType, offsetStart, ValueRange{incSizeAsLLVMType}); - rewriter.create(loc, offsetTo, offsetFrom, moveCountAsIndexType); + auto moveCountAsIndexTypeAdapt = rewriter.create(loc, indexType, moveCountAsLLVMType); + rewriter.create(loc, offsetTo, offsetFrom, moveCountAsIndexTypeAdapt); auto allocated = ch.MemoryRealloc(currentPtr, multSizeOfTypeValue); return allocated; }; - auto cond = rewriter.create(loc, th.getLLVMBoolType(), arith::CmpIPredicateAttr::get(rewriter.getContext(), arith::CmpIPredicate::ugt), incSizeAsLLVMType, decSizeAsIndexType); + auto cond = rewriter.create(loc, LLVM::ICmpPredicate::ugt, incSizeAsLLVMType, decSizeAsLLVMType); auto allocated = clh.conditionalExpressionLowering(loc, ptrType, cond, increaseArrayFunc, decreaseArrayFunc); - mlir::Value index = startIndexAsIndexType; + mlir::Value indexAsLLVMType = startIndexAsLLVMType; auto next = false; mlir::Value value1; for (auto itemPair : llvm::zip(transformed.getItems(), spliceOp.getItems())) @@ -2744,11 +2751,10 @@ struct ArraySpliceOpLowering : public TsLlvmPattern value1 = clh.createIndexConstantOf(llvmIndexType, 1); } - index = rewriter.create(loc, indexType, ValueRange{index, value1}); + indexAsLLVMType = rewriter.create(loc, llvmIndexType, ValueRange{indexAsLLVMType, value1}); } // save new element - auto indexAsLLVMType = rewriter.create(loc, llvmIndexType, index); auto offset = rewriter.create(loc, ptrType, llvmElementType, allocated, ValueRange{indexAsLLVMType}); auto effectiveItem = item; @@ -2766,7 +2772,6 @@ struct ArraySpliceOpLowering : public TsLlvmPattern } rewriter.create(loc, allocated, currentPtrPtr); - auto newCountAsLLVMType = rewriter.create(loc, llvmIndexType, newCountAsIndexType); rewriter.create(loc, newCountAsLLVMType, countAsIndexTypePtr); rewriter.replaceOp(spliceOp, ValueRange{newCountAsLLVMType}); @@ -3495,8 +3500,12 @@ struct GlobalOpLowering : public TsLlvmPattern isa(op) || isa(op) || isa(op) || isa(op) || isa(op) || isa(op) || isa(op) || isa(op) || - isa(op) || isa(op) || - isa(op) || isa(op)) + isa(op) || isa(op) || + isa(op) || isa(op) || + isa(op) || isa(op) || isa(op) || + isa(op) || isa(op) || isa(op) || + isa(op) || isa(op) || + isa(op) || isa(op)) { createAsGlobalConstructor = true; } diff --git a/tslang/lib/TypeScriptExceptionPass/LandingPadFixPass.cpp b/tslang/lib/TypeScriptExceptionPass/LandingPadFixPass.cpp index ac892c59..417d37cb 100644 --- a/tslang/lib/TypeScriptExceptionPass/LandingPadFixPass.cpp +++ b/tslang/lib/TypeScriptExceptionPass/LandingPadFixPass.cpp @@ -51,9 +51,9 @@ struct LandingPadFixPassCode newLandingPad->setCleanup(true); LPI->replaceAllUsesWith(newLandingPad); LPI->eraseFromParent(); - } - MadeChange = true; + MadeChange = true; + } } LLVM_DEBUG(llvm::dbgs() << "\n!! LANDFIX Change: " << MadeChange;); diff --git a/tslang/lib/TypeScriptExceptionPass/Win32ExceptionPass.cpp b/tslang/lib/TypeScriptExceptionPass/Win32ExceptionPass.cpp index 2a3de757..4a3155c1 100644 --- a/tslang/lib/TypeScriptExceptionPass/Win32ExceptionPass.cpp +++ b/tslang/lib/TypeScriptExceptionPass/Win32ExceptionPass.cpp @@ -541,22 +541,18 @@ struct Win32ExceptionPassCode // remove for (auto CI : toRemoveWorkSet) { - // TODO: we need to fix issue wit PHI node after inline works - if (CI->getNumUses() > 0) + // Erase every PHI-node user first (there can be more than one, e.g. after + // inlining merges control flow through several PHIs referencing the same + // to-be-removed value); eraseFromParent() below requires no uses remain. + while (!CI->use_empty()) { - for (auto &U : CI->uses()) + auto UI = llvm::find_if(CI->users(), [](llvm::User *U) { return isa(U); }); + if (UI == CI->user_end()) { - if (U.getUser() && isa(U.getUser())) - { - // Instruction *UserI = cast(U.getUser()); - PHINode *UserPHI = cast(U.getUser()); - if (UserPHI) - { - UserPHI->eraseFromParent(); - break; - } - } + break; } + + cast(*UI)->eraseFromParent(); } CI->eraseFromParent(); @@ -631,7 +627,7 @@ struct Win32ExceptionPassCode // which describes the exception. llvm::Type *Args[] = {PointerType::get(Ctx, 0), PointerType::get(Ctx, 0)}; auto *FTy = llvm::FunctionType::get(Type::getVoidTy(Ctx), Args, /*isVarArg=*/false); - auto Throw = Function::Create(FTy, llvm::GlobalValue::LinkageTypes::InternalLinkage, "_CxxThrowException"); + auto Throw = Function::Create(FTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "_CxxThrowException", module); /* // _CxxThrowException is stdcall on 32-bit x86 platforms. if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index 8bdf8b21..7ceb86d3 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -164,6 +164,7 @@ add_test(NAME test-compile-00-arrays2 COMMAND test-runner "${PROJECT_SOURCE_DIR} add_test(NAME test-compile-00-arrays3 COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array3.ts") add_test(NAME test-compile-00-arrays4-push-pop COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array4_push_pop.ts") add_test(NAME test-compile-00-array-shift COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array_shift.ts") +add_test(NAME test-compile-00-array-splice COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array_splice.ts") add_test(NAME test-compile-00-arrays5-deconstruct COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array5_deconst.ts") add_test(NAME test-compile-00-arrays6 COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array6.ts") add_test(NAME test-compile-00-arrays7 COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array7.ts") @@ -502,6 +503,7 @@ add_test(NAME test-jit-00-arrays2 COMMAND test-runner -jit "${PROJECT_SOURCE_DIR add_test(NAME test-jit-00-arrays3 COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array3.ts") add_test(NAME test-jit-00-arrays4-push-pop COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array4_push_pop.ts") add_test(NAME test-jit-00-array-shift COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array_shift.ts") +add_test(NAME test-jit-00-array-splice COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array_splice.ts") add_test(NAME test-jit-00-arrays5-deconstruct COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array5_deconst.ts") add_test(NAME test-jit-00-arrays6 COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array6.ts") add_test(NAME test-jit-00-arrays7 COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array7.ts") diff --git a/tslang/test/tester/tests/00array_splice.ts b/tslang/test/tester/tests/00array_splice.ts new file mode 100644 index 00000000..a8580a18 --- /dev/null +++ b/tslang/test/tester/tests/00array_splice.ts @@ -0,0 +1,29 @@ +function main() { + // shrink: delete more than inserted + let a: number[] = [1, 2, 3, 4, 5]; + a.splice(1, 2); + assert(a.length == 3, "shrink len"); + assert(a[0] == 1, "shrink 0"); + assert(a[1] == 4, "shrink 1"); + assert(a[2] == 5, "shrink 2"); + + // grow: insert more than deleted + let b: number[] = [1, 2, 3]; + b.splice(1, 1, 10, 20, 30); + assert(b.length == 5, "grow len"); + assert(b[0] == 1, "grow 0"); + assert(b[1] == 10, "grow 1"); + assert(b[2] == 20, "grow 2"); + assert(b[3] == 30, "grow 3"); + assert(b[4] == 3, "grow 4"); + + // equal: same count deleted as inserted + let c: number[] = [1, 2, 3, 4]; + c.splice(1, 2, 99); + assert(c.length == 3, "equal len"); + assert(c[0] == 1, "equal 0"); + assert(c[1] == 99, "equal 1"); + assert(c[2] == 4, "equal 2"); + + print("done."); +}