@@ -70,6 +70,18 @@ static std::string PrintType(const Type *type, bool truncate = false) {
70
70
return s;
71
71
}
72
72
73
+ static bool
74
+ MemoryMatchesIRElementOrder (lldb_private::ExecutionContext &exe_ctx) {
75
+ lldb::TargetSP target_sp = exe_ctx.GetTargetSP ();
76
+ if (target_sp) {
77
+ const auto *arch_plugin = target_sp->GetArchitecturePlugin ();
78
+ if (arch_plugin) {
79
+ return arch_plugin->GetVectorElementOrder () == lldb::eByteOrderLittle;
80
+ }
81
+ }
82
+ return true ; // Default to little-endian (matches IR)
83
+ }
84
+
73
85
static bool CanIgnoreCall (const CallInst *call) {
74
86
const llvm::Function *called_function = call->getCalledFunction ();
75
87
@@ -124,6 +136,17 @@ class InterpreterStackFrame {
124
136
125
137
~InterpreterStackFrame () = default ;
126
138
139
+ bool MemoryMatchesIRElementOrder () {
140
+ lldb::TargetSP target_sp = m_execution_unit.GetTarget ();
141
+ if (target_sp) {
142
+ const auto *arch_plugin = target_sp->GetArchitecturePlugin ();
143
+ if (arch_plugin) {
144
+ return arch_plugin->GetVectorElementOrder () == lldb::eByteOrderLittle;
145
+ }
146
+ }
147
+ return true ;
148
+ }
149
+
127
150
void Jump (const BasicBlock *bb) {
128
151
m_prev_bb = m_bb;
129
152
m_bb = bb;
@@ -367,7 +390,65 @@ class InterpreterStackFrame {
367
390
return true ;
368
391
}
369
392
393
+ bool ResolveVectorConstant (lldb::addr_t process_address,
394
+ const Constant *constant) {
395
+ auto *vector_type = dyn_cast<FixedVectorType>(constant->getType ());
396
+ if (!vector_type)
397
+ return false ;
398
+
399
+ Type *element_type = vector_type->getElementType ();
400
+ unsigned num_elements = vector_type->getNumElements ();
401
+ size_t element_size = m_target_data.getTypeStoreSize (element_type);
402
+ size_t total_size = element_size * num_elements;
403
+ bool reverse_elements = !MemoryMatchesIRElementOrder ();
404
+
405
+ lldb_private::DataBufferHeap buf (total_size, 0 );
406
+ uint8_t *data_ptr = buf.GetBytes ();
407
+
408
+ if (isa<ConstantAggregateZero>(constant)) {
409
+ // Zero initializer - buffer is already zeroed, just write it
410
+ lldb_private::Status write_error;
411
+ m_execution_unit.WriteMemory (process_address, buf.GetBytes (),
412
+ buf.GetByteSize (), write_error);
413
+ return write_error.Success ();
414
+ }
415
+
416
+ if (const ConstantDataVector *cdv =
417
+ dyn_cast<ConstantDataVector>(constant)) {
418
+ for (unsigned i = 0 ; i < num_elements; ++i) {
419
+ const Constant *element = cdv->getElementAsConstant (i);
420
+ APInt element_value;
421
+ if (!ResolveConstantValue (element_value, element))
422
+ return false ;
423
+
424
+ // Calculate target offset based on element ordering
425
+ unsigned target_index = !reverse_elements ? i : (num_elements - 1 - i);
426
+ size_t offset = target_index * element_size;
427
+
428
+ lldb_private::Scalar element_scalar (
429
+ element_value.zextOrTrunc (element_size * 8 ));
430
+ lldb_private::Status get_data_error;
431
+ if (!element_scalar.GetAsMemoryData (data_ptr + offset, element_size,
432
+ m_byte_order, get_data_error))
433
+ return false ;
434
+ }
435
+ lldb_private::Status write_error;
436
+ m_execution_unit.WriteMemory (process_address, buf.GetBytes (),
437
+ buf.GetByteSize (), write_error);
438
+
439
+ return write_error.Success ();
440
+ }
441
+
442
+ return false ;
443
+ }
444
+
370
445
bool ResolveConstant (lldb::addr_t process_address, const Constant *constant) {
446
+ // Handle vector constants specially since they can't be represented as a
447
+ // single APInt
448
+ if (constant->getType ()->isVectorTy ()) {
449
+ return ResolveVectorConstant (process_address, constant);
450
+ }
451
+
371
452
APInt resolved_value;
372
453
373
454
if (!ResolveConstantValue (resolved_value, constant))
@@ -484,8 +565,13 @@ static bool CanResolveConstant(llvm::Constant *constant) {
484
565
return false ;
485
566
case Value::ConstantIntVal:
486
567
case Value::ConstantFPVal:
568
+ return true ;
569
+ case Value::ConstantDataVectorVal:
487
570
case Value::FunctionVal:
488
571
return true ;
572
+ case Value::ConstantAggregateZeroVal:
573
+ // Zero initializers can be resolved
574
+ return true ;
489
575
case Value::ConstantExprVal:
490
576
if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
491
577
switch (constant_expr->getOpcode ()) {
@@ -522,7 +608,8 @@ static bool CanResolveConstant(llvm::Constant *constant) {
522
608
523
609
bool IRInterpreter::CanInterpret (llvm::Module &module , llvm::Function &function,
524
610
lldb_private::Status &error,
525
- const bool support_function_calls) {
611
+ const bool support_function_calls,
612
+ lldb_private::ExecutionContext &exe_ctx) {
526
613
lldb_private::Log *log (GetLog (LLDBLog::Expressions));
527
614
528
615
bool saw_function_with_body = false ;
@@ -551,6 +638,7 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
551
638
case Instruction::BitCast:
552
639
case Instruction::Br:
553
640
case Instruction::PHI:
641
+ case Instruction::ExtractElement:
554
642
break ;
555
643
case Instruction::Call: {
556
644
CallInst *call_inst = dyn_cast<CallInst>(&ii);
@@ -644,7 +732,25 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
644
732
switch (operand_type->getTypeID ()) {
645
733
default :
646
734
break ;
647
- case Type::FixedVectorTyID:
735
+ case Type::FixedVectorTyID: {
736
+ // If the element order is big-endian (highest index first) then it
737
+ // doesn't match LLVM-IR and must be transformed to correctly transfer
738
+ // between LLVM-IR and memory. This might not be fully implemented so
739
+ // decline to interpret this case.
740
+ if (exe_ctx.GetTargetPtr ()) {
741
+ const auto *arch_plugin =
742
+ exe_ctx.GetTargetRef ().GetArchitecturePlugin ();
743
+ if (arch_plugin &&
744
+ arch_plugin->GetVectorElementOrder () == lldb::eByteOrderBig) {
745
+ LLDB_LOGF (log, " Unsupported big-endian vector element ordering" );
746
+ error = lldb_private::Status::FromErrorString (
747
+ " IR interpreter doesn't support big-endian vector element "
748
+ " ordering" );
749
+ return false ;
750
+ }
751
+ }
752
+ break ;
753
+ }
648
754
case Type::ScalableVectorTyID: {
649
755
LLDB_LOGF (log, " Unsupported operand type: %s" ,
650
756
PrintType (operand_type).c_str ());
@@ -657,8 +763,9 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
657
763
// The IR interpreter currently doesn't know about
658
764
// 128-bit integers. As they're not that frequent,
659
765
// we can just fall back to the JIT rather than
660
- // choking.
661
- if (operand_type->getPrimitiveSizeInBits () > 64 ) {
766
+ // choking. However, allow vectors since we handle them above.
767
+ if (operand_type->getPrimitiveSizeInBits () > 64 &&
768
+ !operand_type->isVectorTy ()) {
662
769
LLDB_LOGF (log, " Unsupported operand type: %s" ,
663
770
PrintType (operand_type).c_str ());
664
771
error =
@@ -1567,6 +1674,100 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
1567
1674
frame.AssignValue (inst, returnVal, module );
1568
1675
}
1569
1676
} break ;
1677
+ case Instruction::ExtractElement: {
1678
+ const ExtractElementInst *extract_inst = cast<ExtractElementInst>(inst);
1679
+
1680
+ // Get the vector and index operands
1681
+ const Value *vector_operand = extract_inst->getVectorOperand ();
1682
+ const Value *index_operand = extract_inst->getIndexOperand ();
1683
+
1684
+ // Get the vector address
1685
+ lldb::addr_t vector_addr = frame.ResolveValue (vector_operand, module );
1686
+
1687
+ if (vector_addr == LLDB_INVALID_ADDRESS) {
1688
+ LLDB_LOGF (log, " ExtractElement's vector doesn't resolve to anything" );
1689
+ error = lldb_private::Status::FromErrorString (bad_value_error);
1690
+ return false ;
1691
+ }
1692
+
1693
+ // Evaluate the index
1694
+ lldb_private::Scalar index_scalar;
1695
+ if (!frame.EvaluateValue (index_scalar, index_operand, module )) {
1696
+ LLDB_LOGF (log, " Couldn't evaluate index %s" ,
1697
+ PrintValue (index_operand).c_str ());
1698
+ error = lldb_private::Status::FromErrorString (bad_value_error);
1699
+ return false ;
1700
+ }
1701
+
1702
+ uint64_t index = index_scalar.ULongLong ();
1703
+
1704
+ // Get the vector type information
1705
+ auto *vector_type = dyn_cast<FixedVectorType>(vector_operand->getType ());
1706
+ if (!vector_type) {
1707
+ LLDB_LOGF (log, " ExtractElement instruction doesn't have a fixed vector "
1708
+ " operand type" );
1709
+ error =
1710
+ lldb_private::Status::FromErrorString (interpreter_internal_error);
1711
+ return false ;
1712
+ }
1713
+
1714
+ unsigned num_elements = vector_type->getNumElements ();
1715
+ if (index >= num_elements) {
1716
+ LLDB_LOGF (log,
1717
+ " ExtractElement index %llu is out of bounds for vector with "
1718
+ " %u elements" ,
1719
+ (unsigned long long )index, num_elements);
1720
+ error = lldb_private::Status::FromErrorString (bad_value_error);
1721
+ return false ;
1722
+ }
1723
+
1724
+ Type *element_type = vector_type->getElementType ();
1725
+ size_t element_size = data_layout.getTypeStoreSize (element_type);
1726
+
1727
+ // Handle target-specific vector element ordering
1728
+ bool reverse_elements = !MemoryMatchesIRElementOrder (exe_ctx);
1729
+ uint64_t target_index =
1730
+ reverse_elements ? (num_elements - 1 - index) : index;
1731
+ size_t element_offset = target_index * element_size;
1732
+
1733
+ // Allocate space for the result element
1734
+ lldb::addr_t result_addr = frame.ResolveValue (extract_inst, module );
1735
+ if (result_addr == LLDB_INVALID_ADDRESS) {
1736
+ LLDB_LOGF (log, " ExtractElement's result doesn't resolve to anything" );
1737
+ error = lldb_private::Status::FromErrorString (bad_value_error);
1738
+ return false ;
1739
+ }
1740
+
1741
+ // Read the element from the vector
1742
+ lldb_private::DataBufferHeap element_buffer (element_size, 0 );
1743
+ lldb_private::Status read_error;
1744
+ execution_unit.ReadMemory (element_buffer.GetBytes (),
1745
+ vector_addr + element_offset, element_size,
1746
+ read_error);
1747
+ if (!read_error.Success ()) {
1748
+ LLDB_LOGF (log, " Couldn't read element data for ExtractElement" );
1749
+ error = lldb_private::Status::FromErrorString (memory_read_error);
1750
+ return false ;
1751
+ }
1752
+
1753
+ // Write the element to the result location
1754
+ lldb_private::Status write_error;
1755
+ execution_unit.WriteMemory (result_addr, element_buffer.GetBytes (),
1756
+ element_size, write_error);
1757
+ if (!write_error.Success ()) {
1758
+ LLDB_LOGF (log, " Couldn't write result for ExtractElement" );
1759
+ error = lldb_private::Status::FromErrorString (memory_write_error);
1760
+ return false ;
1761
+ }
1762
+
1763
+ if (log) {
1764
+ LLDB_LOGF (log, " Interpreted an ExtractElement" );
1765
+ LLDB_LOGF (log, " Vector: 0x%" PRIx64, vector_addr);
1766
+ LLDB_LOGF (log, " Index: %llu" , (unsigned long long )index);
1767
+ LLDB_LOGF (log, " Element offset: %zu" , element_offset);
1768
+ LLDB_LOGF (log, " Result: 0x%" PRIx64, result_addr);
1769
+ }
1770
+ } break ;
1570
1771
}
1571
1772
1572
1773
++frame.m_ii ;
0 commit comments