3434#include " mlir/Pass/Pass.h"
3535#include " mlir/Transforms/DialectConversion.h"
3636#include " llvm/Support/Debug.h"
37+ #include " llvm/Support/FormatVariadic.h"
3738
3839#define DEBUG_TYPE " lower-arc-to-llvm"
3940
@@ -534,25 +535,53 @@ struct SimEmitValueOpLowering
534535 if (!moduleOp)
535536 return failure ();
536537
537- // Cast the value to a size_t.
538- // FIXME: like the rest of MLIR, this assumes sizeof(intptr_t) ==
539- // sizeof(size_t) on the target architecture.
540- Value toPrint = adaptor.getValue ();
541- DataLayout layout = DataLayout::closest (op);
542- llvm::TypeSize sizeOfSizeT =
543- layout.getTypeSizeInBits (rewriter.getIndexType ());
544- assert (!sizeOfSizeT.isScalable () &&
545- sizeOfSizeT.getFixedValue () <= std::numeric_limits<unsigned >::max ());
546- bool truncated = false ;
547- if (valueType.getWidth () > sizeOfSizeT) {
548- toPrint = LLVM::TruncOp::create (
549- rewriter, loc,
550- IntegerType::get (getContext (), sizeOfSizeT.getFixedValue ()), toPrint);
551- truncated = true ;
552- } else if (valueType.getWidth () < sizeOfSizeT)
553- toPrint = LLVM::ZExtOp::create (
554- rewriter, loc,
555- IntegerType::get (getContext (), sizeOfSizeT.getFixedValue ()), toPrint);
538+ SmallVector<Value> printfVariadicArgs;
539+ SmallString<16 > printfFormatStr;
540+ int remainingBits = valueType.getWidth ();
541+ Value value = adaptor.getValue ();
542+
543+ // Assumes the target platform uses 64bit for long long ints (%llx
544+ // formatter).
545+ constexpr llvm::StringRef intFormatter = " llx" ;
546+ auto intType = IntegerType::get (getContext (), 64 );
547+ Value shiftValue = LLVM::ConstantOp::create (
548+ rewriter, loc, rewriter.getIntegerAttr (valueType, intType.getWidth ()));
549+
550+ if (valueType.getWidth () < intType.getWidth ()) {
551+ int width = llvm::divideCeil (valueType.getWidth (), 4 );
552+ printfFormatStr = llvm::formatv (" %0{0}{1}" , width, intFormatter);
553+ printfVariadicArgs.push_back (
554+ LLVM::ZExtOp::create (rewriter, loc, intType, value));
555+ } else {
556+ // Process the value in 64 bit chunks, starting from the least significant
557+ // bits. Since we append chunks in low-to-high order, we reverse the
558+ // vector to print them in the correct high-to-low order.
559+ int otherChunkWidth = intType.getWidth () / 4 ;
560+ int firstChunkWidth =
561+ llvm::divideCeil (valueType.getWidth () % intType.getWidth (), 4 );
562+ if (firstChunkWidth == 0 ) { // print the full 64-bit hex or a subset.
563+ firstChunkWidth = otherChunkWidth;
564+ }
565+
566+ std::string firstChunkFormat =
567+ llvm::formatv (" %0{0}{1}" , firstChunkWidth, intFormatter);
568+ std::string otherChunkFormat =
569+ llvm::formatv (" %0{0}{1}" , otherChunkWidth, intFormatter);
570+
571+ for (int i = 0 ; remainingBits > 0 ; ++i) {
572+ // Append 64-bit chunks to the printf arguments, in low-to-high
573+ // order. The integer is printed in hex format with zero padding.
574+ printfVariadicArgs.push_back (
575+ LLVM::TruncOp::create (rewriter, loc, intType, value));
576+
577+ // Zero-padded format specifier for fixed width, e.g. %01llx for 4 bits.
578+ printfFormatStr.append (i == 0 ? firstChunkFormat : otherChunkFormat);
579+
580+ value =
581+ LLVM::LShrOp::create (rewriter, loc, value, shiftValue).getResult ();
582+ remainingBits -= intType.getWidth ();
583+ }
584+ }
556585
557586 // Lookup of create printf function symbol.
558587 auto printfFunc = LLVM::lookupOrCreateFn (
@@ -563,7 +592,6 @@ struct SimEmitValueOpLowering
563592
564593 // Insert the format string if not already available.
565594 SmallString<16 > formatStrName{" _arc_sim_emit_" };
566- formatStrName.append (truncated ? " trunc_" : " full_" );
567595 formatStrName.append (adaptor.getValueName ());
568596 LLVM::GlobalOp formatStrGlobal;
569597 if (!(formatStrGlobal =
@@ -572,9 +600,8 @@ struct SimEmitValueOpLowering
572600
573601 SmallString<16 > formatStr = adaptor.getValueName ();
574602 formatStr.append (" = " );
575- if (truncated)
576- formatStr.append (" (truncated) " );
577- formatStr.append (" %zx\n " );
603+ formatStr.append (printfFormatStr);
604+ formatStr.append (" \n " );
578605 SmallVector<char > formatStrVec{formatStr.begin (), formatStr.end ()};
579606 formatStrVec.push_back (0 );
580607
@@ -590,8 +617,14 @@ struct SimEmitValueOpLowering
590617
591618 Value formatStrGlobalPtr =
592619 LLVM::AddressOfOp::create (rewriter, loc, formatStrGlobal);
593- rewriter.replaceOpWithNewOp <LLVM::CallOp>(
594- op, printfFunc.value (), ValueRange{formatStrGlobalPtr, toPrint});
620+
621+ // Add the format string to the end, and reverse the vector to print them in
622+ // the correct high-to-low order with the format string at the beginning.
623+ printfVariadicArgs.push_back (formatStrGlobalPtr);
624+ std::reverse (printfVariadicArgs.begin (), printfVariadicArgs.end ());
625+
626+ rewriter.replaceOpWithNewOp <LLVM::CallOp>(op, printfFunc.value (),
627+ printfVariadicArgs);
595628
596629 return success ();
597630 }
0 commit comments