diff --git a/integration_tests/test_list_pop.py b/integration_tests/test_list_pop.py index 51c9f02f45..262470af67 100644 --- a/integration_tests/test_list_pop.py +++ b/integration_tests/test_list_pop.py @@ -4,6 +4,7 @@ def test_list_pop(): l1: list[i32] l2: list[tuple[i32, f64]] l3: list[list[str]] + l4: list[i32] i: i32 j: i32 total: i32 @@ -45,6 +46,10 @@ def test_list_pop(): assert l1.pop(len(l1) - 1) == 4 assert l1 == [1, 2] + l4 = [1, 2, 3, 4, 5] + assert l4.pop(-5) == 1 + assert l4.pop(-1) == 5 + total = 10 l1 = [] for i in range(total): diff --git a/src/libasr/codegen/llvm_utils.cpp b/src/libasr/codegen/llvm_utils.cpp index e19f309b1f..665af13abc 100644 --- a/src/libasr/codegen/llvm_utils.cpp +++ b/src/libasr/codegen/llvm_utils.cpp @@ -4659,10 +4659,26 @@ namespace LCompilers { llvm::Value* end_point_ptr = get_pointer_to_current_end_point(list); llvm::Value* end_point = LLVM::CreateLoad(*builder, end_point_ptr); + llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), + llvm::APInt(32, 0)); + llvm::Value* adjusted_pos = pos; + llvm::Value* is_negative = builder->CreateICmpSLT(pos, zero); + llvm::Value* abs_pos = builder->CreateSelect(is_negative, + builder->CreateNeg(pos), + pos + ); + llvm::Value* is_negative_and_in_bounds = builder->CreateAnd(is_negative, + builder->CreateICmpULE(abs_pos, end_point) + ); + // If the index is negative, convert it to the corresponding positive index + adjusted_pos = builder->CreateSelect(is_negative_and_in_bounds, + builder->CreateAdd(end_point, pos), + adjusted_pos + ); llvm::AllocaInst *pos_ptr = builder0.CreateAlloca( llvm::Type::getInt32Ty(context), nullptr); - LLVM::CreateStore(*builder, pos, pos_ptr); + LLVM::CreateStore(*builder, adjusted_pos, pos_ptr); llvm::Value* tmp = nullptr; // Get element to return