@@ -567,27 +567,70 @@ static bool getBit(const char *rawData, size_t bitPos) {
567
567
return (rawData[bitPos / CHAR_BIT] & (1 << (bitPos % CHAR_BIT))) != 0 ;
568
568
}
569
569
570
- // / Get start position of actual data in `value`. Actual data is
571
- // / stored in last `bitWidth`/CHAR_BIT bytes in big endian.
572
- static char *getAPIntDataPos (APInt &value, size_t bitWidth) {
573
- char *dataPos =
574
- const_cast <char *>(reinterpret_cast <const char *>(value.getRawData ()));
575
- if (llvm::support::endian::system_endianness () ==
576
- llvm::support::endianness::big)
577
- dataPos = dataPos + 8 - llvm::divideCeil (bitWidth, CHAR_BIT);
578
- return dataPos;
579
- }
580
-
581
- // / Read APInt `value` from appropriate position.
582
- static void readAPInt (APInt &value, size_t bitWidth, char *outData) {
583
- char *dataPos = getAPIntDataPos (value, bitWidth);
584
- std::copy_n (dataPos, llvm::divideCeil (bitWidth, CHAR_BIT), outData);
585
- }
586
-
587
- // / Write `inData` to appropriate position of APInt `value`.
588
- static void writeAPInt (const char *inData, size_t bitWidth, APInt &value) {
589
- char *dataPos = getAPIntDataPos (value, bitWidth);
590
- std::copy_n (inData, llvm::divideCeil (bitWidth, CHAR_BIT), dataPos);
570
+ // / Copy actual `numBytes` data from `value` (APInt) to char array(`result`) for
571
+ // / BE format.
572
+ static void copyAPIntToArrayForBEmachine (APInt value, size_t numBytes,
573
+ char *result) {
574
+ assert (llvm::support::endian::system_endianness () == // NOLINT
575
+ llvm::support::endianness::big); // NOLINT
576
+ assert (value.getNumWords () * APInt::APINT_WORD_SIZE >= numBytes);
577
+
578
+ // Copy the words filled with data.
579
+ // For example, when `value` has 2 words, the first word is filled with data.
580
+ // `value` (10 bytes, BE):|abcdefgh|------ij| ==> `result` (BE):|abcdefgh|--|
581
+ size_t numFilledWords = (value.getNumWords () - 1 ) * APInt::APINT_WORD_SIZE;
582
+ std::copy_n (reinterpret_cast <const char *>(value.getRawData ()),
583
+ numFilledWords, result);
584
+ // Convert last word of APInt to LE format and store it in char
585
+ // array(`valueLE`).
586
+ // ex. last word of `value` (BE): |------ij| ==> `valueLE` (LE): |ji------|
587
+ size_t lastWordPos = numFilledWords;
588
+ SmallVector<char , 8 > valueLE (APInt::APINT_WORD_SIZE);
589
+ DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine (
590
+ reinterpret_cast <const char *>(value.getRawData ()) + lastWordPos,
591
+ valueLE.begin (), APInt::APINT_BITS_PER_WORD, 1 );
592
+ // Extract actual APInt data from `valueLE`, convert endianness to BE format,
593
+ // and store it in `result`.
594
+ // ex. `valueLE` (LE): |ji------| ==> `result` (BE): |abcdefgh|ij|
595
+ DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine (
596
+ valueLE.begin (), result + lastWordPos,
597
+ (numBytes - lastWordPos) * CHAR_BIT, 1 );
598
+ }
599
+
600
+ // / Copy `numBytes` data from `inArray`(char array) to `result`(APINT) for BE
601
+ // / format.
602
+ static void copyArrayToAPIntForBEmachine (const char *inArray, size_t numBytes,
603
+ APInt &result) {
604
+ assert (llvm::support::endian::system_endianness () == // NOLINT
605
+ llvm::support::endianness::big); // NOLINT
606
+ assert (result.getNumWords () * APInt::APINT_WORD_SIZE >= numBytes);
607
+
608
+ // Copy the data that fills the word of `result` from `inArray`.
609
+ // For example, when `result` has 2 words, the first word will be filled with
610
+ // data. So, the first 8 bytes are copied from `inArray` here.
611
+ // `inArray` (10 bytes, BE): |abcdefgh|ij|
612
+ // ==> `result` (2 words, BE): |abcdefgh|--------|
613
+ size_t numFilledWords = (result.getNumWords () - 1 ) * APInt::APINT_WORD_SIZE;
614
+ std::copy_n (
615
+ inArray, numFilledWords,
616
+ const_cast <char *>(reinterpret_cast <const char *>(result.getRawData ())));
617
+
618
+ // Convert array data which will be last word of `result` to LE format, and
619
+ // store it in char array(`inArrayLE`).
620
+ // ex. `inArray` (last two bytes, BE): |ij| ==> `inArrayLE` (LE): |ji------|
621
+ size_t lastWordPos = numFilledWords;
622
+ SmallVector<char , 8 > inArrayLE (APInt::APINT_WORD_SIZE);
623
+ DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine (
624
+ inArray + lastWordPos, inArrayLE.begin (),
625
+ (numBytes - lastWordPos) * CHAR_BIT, 1 );
626
+
627
+ // Convert `inArrayLE` to BE format, and store it in last word of `result`.
628
+ // ex. `inArrayLE` (LE): |ji------| ==> `result` (BE): |abcdefgh|------ij|
629
+ DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine (
630
+ inArrayLE.begin (),
631
+ const_cast <char *>(reinterpret_cast <const char *>(result.getRawData ())) +
632
+ lastWordPos,
633
+ APInt::APINT_BITS_PER_WORD, 1 );
591
634
}
592
635
593
636
// / Writes value to the bit position `bitPos` in array `rawData`.
@@ -600,7 +643,20 @@ static void writeBits(char *rawData, size_t bitPos, APInt value) {
600
643
601
644
// Otherwise, the bit position is guaranteed to be byte aligned.
602
645
assert ((bitPos % CHAR_BIT) == 0 && " expected bitPos to be 8-bit aligned" );
603
- readAPInt (value, bitWidth, rawData + (bitPos / CHAR_BIT));
646
+ if (llvm::support::endian::system_endianness () ==
647
+ llvm::support::endianness::big) {
648
+ // Copy from `value` to `rawData + (bitPos / CHAR_BIT)`.
649
+ // Copying the first `llvm::divideCeil(bitWidth, CHAR_BIT)` bytes doesn't
650
+ // work correctly in BE format.
651
+ // ex. `value` (2 words including 10 bytes)
652
+ // ==> BE: |abcdefgh|------ij|, LE: |hgfedcba|ji------|
653
+ copyAPIntToArrayForBEmachine (value, llvm::divideCeil (bitWidth, CHAR_BIT),
654
+ rawData + (bitPos / CHAR_BIT));
655
+ } else {
656
+ std::copy_n (reinterpret_cast <const char *>(value.getRawData ()),
657
+ llvm::divideCeil (bitWidth, CHAR_BIT),
658
+ rawData + (bitPos / CHAR_BIT));
659
+ }
604
660
}
605
661
606
662
// / Reads the next `bitWidth` bits from the bit position `bitPos` in array
@@ -613,7 +669,21 @@ static APInt readBits(const char *rawData, size_t bitPos, size_t bitWidth) {
613
669
// Otherwise, the bit position must be 8-bit aligned.
614
670
assert ((bitPos % CHAR_BIT) == 0 && " expected bitPos to be 8-bit aligned" );
615
671
APInt result (bitWidth, 0 );
616
- writeAPInt (rawData + (bitPos / CHAR_BIT), bitWidth, result);
672
+ if (llvm::support::endian::system_endianness () ==
673
+ llvm::support::endianness::big) {
674
+ // Copy from `rawData + (bitPos / CHAR_BIT)` to `result`.
675
+ // Copying the first `llvm::divideCeil(bitWidth, CHAR_BIT)` bytes doesn't
676
+ // work correctly in BE format.
677
+ // ex. `result` (2 words including 10 bytes)
678
+ // ==> BE: |abcdefgh|------ij|, LE: |hgfedcba|ji------| This function
679
+ copyArrayToAPIntForBEmachine (rawData + (bitPos / CHAR_BIT),
680
+ llvm::divideCeil (bitWidth, CHAR_BIT), result);
681
+ } else {
682
+ std::copy_n (rawData + (bitPos / CHAR_BIT),
683
+ llvm::divideCeil (bitWidth, CHAR_BIT),
684
+ const_cast <char *>(
685
+ reinterpret_cast <const char *>(result.getRawData ())));
686
+ }
617
687
return result;
618
688
}
619
689
@@ -1175,7 +1245,7 @@ void DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine(
1175
1245
default : {
1176
1246
size_t nBytes = elementBitWidth / CHAR_BIT;
1177
1247
for (size_t i = 0 ; i < nBytes; i++)
1178
- std::copy_n (inRawData + (nBytes - 1 - i), numElements , outRawData + i);
1248
+ std::copy_n (inRawData + (nBytes - 1 - i), 1 , outRawData + i);
1179
1249
break ;
1180
1250
}
1181
1251
}
0 commit comments