@@ -70,6 +70,75 @@ static std::string PrintType(const Type *type, bool truncate = false) {
70
70
return s;
71
71
}
72
72
73
+ static bool
74
+ isNonTrivialBitcast (const Instruction &inst,
75
+ lldb_private::ExecutionContext &exe_ctx) {
76
+ auto *result_type = dyn_cast<VectorType>(inst.getType ());
77
+ auto *operand = inst.getOperand (0 );
78
+ auto *operand_type = dyn_cast<VectorType>(operand->getType ());
79
+
80
+ // If neither type is a vector then the bitcast is trivial
81
+ if (!result_type && !operand_type)
82
+ return false ;
83
+
84
+ // Get endianness and element order from the architecture
85
+ lldb::ByteOrder byte_order = lldb::eByteOrderLittle;
86
+ lldb::ByteOrder element_order = lldb::eByteOrderLittle;
87
+
88
+ lldb::TargetSP target_sp = exe_ctx.GetTargetSP ();
89
+ if (target_sp) {
90
+ const auto *arch_plugin = target_sp->GetArchitecturePlugin ();
91
+ if (arch_plugin) {
92
+ byte_order = target_sp->GetArchitecture ().GetByteOrder ();
93
+ element_order = arch_plugin->GetVectorElementOrder ();
94
+ }
95
+ }
96
+
97
+ // Bitcast is trivial if endianness matches element order
98
+ if (byte_order == element_order)
99
+ return false ;
100
+
101
+ // If the element order and value byte order disagree then vector bitcasts
102
+ // aren't no-ops when the element sizes change. For example given:
103
+ // <2 x i32> <i32 0x00112233, i32 0x44556677>
104
+ // then bitcast's LangRef definition of
105
+ // store <2 x i32>, ptr @loc
106
+ // load <4 x i16>, ptr @loc
107
+ // gives:
108
+ // Order | Mem after Store | <4 x i16> after Load | Bitcast
109
+ // LF | 3322110077665544 | 0x3322 0x0011 0x6677 0x4455 | no-op
110
+ // BN | 0011223344556677 | 0x0011 0x2233 0x4455 0x6677 | shuffle
111
+ // LF | 7766554433221100 | 0x6677 0x4455 0x3322 0x1100 | shuffle
112
+ // BN | 4455667700112233 | 0x4455 0x6677 0x0011 0x2233 | no-op
113
+ // Order abbreviations:
114
+ // L = Little Endian
115
+ // B = Big Endian
116
+ // F = Lane 0 is first
117
+ // N = Lane N-1 is first
118
+
119
+ // If only one type is a vector, then we'll assume it's non-trivial on the
120
+ // basis that this changes the number of elements from N to 1 or the other
121
+ // way around.
122
+ if (!result_type || !operand_type)
123
+ return false ;
124
+
125
+ // I'm not sure how scalable vectors behave in this situation.
126
+ // Reject them to be safe.
127
+ if (!result_type->getElementCount ().isFixed () ||
128
+ !operand_type->getElementCount ().isFixed ())
129
+ return true ;
130
+
131
+ // We can handle the cases that are no-op by virtue of the element
132
+ // sizes/counts not changing but the shuffle cases aren't
133
+ // implemented in IRInterpreter::Interpret so decline to interpret
134
+ // them.
135
+ if (result_type->getElementCount () != operand_type->getElementCount () ||
136
+ result_type->getScalarSizeInBits () != operand_type->getScalarSizeInBits ())
137
+ return true ;
138
+
139
+ return false ;
140
+ }
141
+
73
142
static bool CanIgnoreCall (const CallInst *call) {
74
143
const llvm::Function *called_function = call->getCalledFunction ();
75
144
@@ -367,7 +436,62 @@ class InterpreterStackFrame {
367
436
return true ;
368
437
}
369
438
439
+ bool ResolveVectorConstant (lldb::addr_t process_address,
440
+ const Constant *constant) {
441
+ auto *vector_type = dyn_cast<FixedVectorType>(constant->getType ());
442
+ if (!vector_type)
443
+ return false ;
444
+
445
+ Type *element_type = vector_type->getElementType ();
446
+ unsigned num_elements = vector_type->getNumElements ();
447
+ size_t element_size = m_target_data.getTypeStoreSize (element_type);
448
+ size_t total_size = element_size * num_elements;
449
+
450
+ lldb_private::DataBufferHeap buf (total_size, 0 );
451
+ uint8_t *data_ptr = buf.GetBytes ();
452
+
453
+ if (isa<ConstantAggregateZero>(constant)) {
454
+ // Zero initializer - buffer is already zeroed, just write it
455
+ lldb_private::Status write_error;
456
+ m_execution_unit.WriteMemory (process_address, buf.GetBytes (),
457
+ buf.GetByteSize (), write_error);
458
+ return write_error.Success ();
459
+ }
460
+
461
+ if (const ConstantDataVector *cdv =
462
+ dyn_cast<ConstantDataVector>(constant)) {
463
+ for (unsigned i = 0 ; i < num_elements; ++i) {
464
+ const Constant *element = cdv->getElementAsConstant (i);
465
+ APInt element_value;
466
+ if (!ResolveConstantValue (element_value, element))
467
+ return false ;
468
+
469
+ size_t offset = i * element_size;
470
+
471
+ lldb_private::Scalar element_scalar (
472
+ element_value.zextOrTrunc (element_size * 8 ));
473
+ lldb_private::Status get_data_error;
474
+ if (!element_scalar.GetAsMemoryData (data_ptr + offset, element_size,
475
+ m_byte_order, get_data_error))
476
+ return false ;
477
+ }
478
+ lldb_private::Status write_error;
479
+ m_execution_unit.WriteMemory (process_address, buf.GetBytes (),
480
+ buf.GetByteSize (), write_error);
481
+
482
+ return write_error.Success ();
483
+ }
484
+
485
+ return false ;
486
+ }
487
+
370
488
bool ResolveConstant (lldb::addr_t process_address, const Constant *constant) {
489
+ // Handle vector constants specially since they can't be represented as a
490
+ // single APInt
491
+ if (constant->getType ()->isVectorTy ()) {
492
+ return ResolveVectorConstant (process_address, constant);
493
+ }
494
+
371
495
APInt resolved_value;
372
496
373
497
if (!ResolveConstantValue (resolved_value, constant))
@@ -484,8 +608,12 @@ static bool CanResolveConstant(llvm::Constant *constant) {
484
608
return false ;
485
609
case Value::ConstantIntVal:
486
610
case Value::ConstantFPVal:
611
+ return true ;
487
612
case Value::FunctionVal:
488
613
return true ;
614
+ case Value::ConstantDataVectorVal:
615
+ case Value::ConstantAggregateZeroVal:
616
+ return constant->getType ()->getTypeID () == Type::FixedVectorTyID;
489
617
case Value::ConstantExprVal:
490
618
if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
491
619
switch (constant_expr->getOpcode ()) {
@@ -522,7 +650,8 @@ static bool CanResolveConstant(llvm::Constant *constant) {
522
650
523
651
bool IRInterpreter::CanInterpret (llvm::Module &module , llvm::Function &function,
524
652
lldb_private::Status &error,
525
- const bool support_function_calls) {
653
+ const bool support_function_calls,
654
+ lldb_private::ExecutionContext &exe_ctx) {
526
655
lldb_private::Log *log (GetLog (LLDBLog::Expressions));
527
656
528
657
bool saw_function_with_body = false ;
@@ -548,9 +677,13 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
548
677
}
549
678
case Instruction::Add:
550
679
case Instruction::Alloca:
551
- case Instruction::BitCast:
552
680
case Instruction::Br:
553
681
case Instruction::PHI:
682
+ case Instruction::ExtractElement:
683
+ break ;
684
+ case Instruction::BitCast:
685
+ if (isNonTrivialBitcast (ii, exe_ctx))
686
+ return false ;
554
687
break ;
555
688
case Instruction::Call: {
556
689
CallInst *call_inst = dyn_cast<CallInst>(&ii);
@@ -645,6 +778,7 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
645
778
default :
646
779
break ;
647
780
case Type::FixedVectorTyID:
781
+ break ;
648
782
case Type::ScalableVectorTyID: {
649
783
LLDB_LOGF (log, " Unsupported operand type: %s" ,
650
784
PrintType (operand_type).c_str ());
@@ -657,8 +791,9 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
657
791
// The IR interpreter currently doesn't know about
658
792
// 128-bit integers. As they're not that frequent,
659
793
// we can just fall back to the JIT rather than
660
- // choking.
661
- if (operand_type->getPrimitiveSizeInBits () > 64 ) {
794
+ // choking. However, allow vectors since we handle them above.
795
+ if (operand_type->getPrimitiveSizeInBits () > 64 &&
796
+ !operand_type->isVectorTy ()) {
662
797
LLDB_LOGF (log, " Unsupported operand type: %s" ,
663
798
PrintType (operand_type).c_str ());
664
799
error =
@@ -1543,9 +1678,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
1543
1678
// Void return type
1544
1679
if (returnType->isVoidTy ()) {
1545
1680
// Cant assign to void types, so we leave the frame untouched
1546
- } else
1547
- // Integer or pointer return type
1548
- if (returnType->isIntegerTy () || returnType->isPointerTy ()) {
1681
+ } else if (returnType->isIntegerTy () || returnType->isPointerTy ()) {
1549
1682
// Get the encapsulated return value
1550
1683
lldb::ValueObjectSP retVal = call_plan_sp.get ()->GetReturnValueObject ();
1551
1684
@@ -1567,10 +1700,113 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
1567
1700
frame.AssignValue (inst, returnVal, module );
1568
1701
}
1569
1702
} break ;
1703
+ case Instruction::ExtractElement: {
1704
+ if (!InterpretExtractElement (inst, frame, data_layout, module ,
1705
+ execution_unit, error, log))
1706
+ return false ;
1707
+ } break ;
1570
1708
}
1571
1709
1572
1710
++frame.m_ii ;
1573
1711
}
1574
1712
1575
1713
return false ;
1576
1714
}
1715
+
1716
+ bool IRInterpreter::InterpretExtractElement (
1717
+ const llvm::Instruction *inst, InterpreterStackFrame &frame,
1718
+ const llvm::DataLayout &data_layout, llvm::Module &module ,
1719
+ lldb_private::IRExecutionUnit &execution_unit, lldb_private::Status &error,
1720
+ lldb_private::Log *log) {
1721
+ const ExtractElementInst *extract_inst = cast<ExtractElementInst>(inst);
1722
+
1723
+ // Get the vector and index operands
1724
+ const Value *vector_operand = extract_inst->getVectorOperand ();
1725
+ const Value *index_operand = extract_inst->getIndexOperand ();
1726
+
1727
+ // Get the vector address
1728
+ lldb::addr_t vector_addr =
1729
+ frame.ResolveValue (vector_operand, module );
1730
+
1731
+ if (vector_addr == LLDB_INVALID_ADDRESS) {
1732
+ LLDB_LOGF (log, " ExtractElement's vector doesn't resolve to anything" );
1733
+ error = lldb_private::Status::FromErrorString (bad_value_error);
1734
+ return false ;
1735
+ }
1736
+
1737
+ // Evaluate the index
1738
+ lldb_private::Scalar index_scalar;
1739
+ if (!frame.EvaluateValue (index_scalar, index_operand, module )) {
1740
+ LLDB_LOGF (log, " Couldn't evaluate index %s" ,
1741
+ PrintValue (index_operand).c_str ());
1742
+ error = lldb_private::Status::FromErrorString (bad_value_error);
1743
+ return false ;
1744
+ }
1745
+
1746
+ uint64_t index = index_scalar.ULongLong ();
1747
+
1748
+ // Get the vector type information
1749
+ auto *vector_type = dyn_cast<FixedVectorType>(vector_operand->getType ());
1750
+ if (!vector_type) {
1751
+ LLDB_LOGF (log, " ExtractElement instruction doesn't have a fixed vector "
1752
+ " operand type" );
1753
+ error = lldb_private::Status::FromErrorString (interpreter_internal_error);
1754
+ return false ;
1755
+ }
1756
+
1757
+ unsigned num_elements = vector_type->getNumElements ();
1758
+ if (index >= num_elements) {
1759
+ LLDB_LOG (log,
1760
+ " ExtractElement index {0} is out of bounds for vector with "
1761
+ " {1} elements" ,
1762
+ index, num_elements);
1763
+ error = lldb_private::Status::FromErrorString (bad_value_error);
1764
+ return false ;
1765
+ }
1766
+
1767
+ Type *element_type = vector_type->getElementType ();
1768
+ size_t element_size = data_layout.getTypeStoreSize (element_type);
1769
+
1770
+ size_t element_offset = index * element_size;
1771
+
1772
+ // Allocate space for the result element
1773
+ lldb::addr_t result_addr = frame.ResolveValue (extract_inst, module );
1774
+ if (result_addr == LLDB_INVALID_ADDRESS) {
1775
+ LLDB_LOG (log, " ExtractElement's result doesn't resolve to anything" );
1776
+ error = lldb_private::Status::FromErrorString (bad_value_error);
1777
+ return false ;
1778
+ }
1779
+
1780
+ // Read the element from the vector
1781
+ lldb_private::DataBufferHeap element_buffer (element_size, 0 );
1782
+ lldb_private::Status read_error;
1783
+ execution_unit.ReadMemory (element_buffer.GetBytes (),
1784
+ vector_addr + element_offset, element_size,
1785
+ read_error);
1786
+ if (!read_error.Success ()) {
1787
+ LLDB_LOG (log, " Couldn't read element data for ExtractElement" );
1788
+ error = lldb_private::Status::FromErrorString (memory_read_error);
1789
+ return false ;
1790
+ }
1791
+
1792
+ // Write the element to the result location
1793
+ lldb_private::Status write_error;
1794
+ execution_unit.WriteMemory (result_addr, element_buffer.GetBytes (),
1795
+ element_size, write_error);
1796
+ if (!write_error.Success ()) {
1797
+ LLDB_LOG (log, " Couldn't write result for ExtractElement" );
1798
+ error = lldb_private::Status::FromErrorString (memory_write_error);
1799
+ return false ;
1800
+ }
1801
+
1802
+ if (log) {
1803
+ LLDB_LOG (log,
1804
+ " Interpreted an ExtractElement\n "
1805
+ " Vector: {0}\n "
1806
+ " Index: {1}\n "
1807
+ " Element offset: {2}\n "
1808
+ " Result: {3}\n " ,
1809
+ vector_addr, index, element_offset, result_addr);
1810
+ }
1811
+ return true ;
1812
+ }
0 commit comments