From 1b7e2356ace23af872cc7d66cf45c56b10e77c4d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 17 Aug 2004 06:36:49 +0000 Subject: [PATCH] Implement emitGlobalConstant git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15868 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/AsmPrinter.cpp | 161 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/lib/CodeGen/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter.cpp index a84cc7127f1..7773274eed4 100644 --- a/lib/CodeGen/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter.cpp @@ -108,3 +108,164 @@ void AsmPrinter::emitConstantValueOnly(const Constant *CV) { assert(0 && "Unknown constant value!"); } } + +/// toOctal - Convert the low order bits of X into an octal digit. +/// +static inline char toOctal(int X) { + return (X&7)+'0'; +} + +/// getAsCString - Return the specified array as a C compatible string, only if +/// the predicate isString is true. +/// +static void printAsCString(std::ostream &O, const ConstantArray *CVA) { + assert(CVA->isString() && "Array is not string compatible!"); + + O << "\""; + for (unsigned i = 0; i != CVA->getNumOperands(); ++i) { + unsigned char C = cast(CVA->getOperand(i))->getRawValue(); + + if (C == '"') { + O << "\\\""; + } else if (C == '\\') { + O << "\\\\"; + } else if (isprint(C)) { + O << C; + } else { + switch(C) { + case '\b': O << "\\b"; break; + case '\f': O << "\\f"; break; + case '\n': O << "\\n"; break; + case '\r': O << "\\r"; break; + case '\t': O << "\\t"; break; + default: + O << '\\'; + O << toOctal(C >> 6); + O << toOctal(C >> 3); + O << toOctal(C >> 0); + break; + } + } + } + O << "\""; +} + +/// emitGlobalConstant - Print a general LLVM constant to the .s file. +/// +void AsmPrinter::emitGlobalConstant(const Constant *CV) { + const TargetData &TD = TM.getTargetData(); + + if (CV->isNullValue()) { + O << ZeroDirective << TD.getTypeSize(CV->getType()) << "\n"; + return; + } else if (const ConstantArray *CVA = dyn_cast(CV)) { + if (CVA->isString()) { + O << AsciiDirective; + printAsCString(O, CVA); + O << "\n"; + } else { // Not a string. Print the values in successive locations + for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) + emitGlobalConstant(CVA->getOperand(i)); + } + return; + } else if (const ConstantStruct *CVS = dyn_cast(CV)) { + // Print the fields in successive locations. Pad to align if needed! + const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType()); + unsigned sizeSoFar = 0; + for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) { + const Constant* field = CVS->getOperand(i); + + // Check if padding is needed and insert one or more 0s. + unsigned fieldSize = TD.getTypeSize(field->getType()); + unsigned padSize = ((i == e-1? cvsLayout->StructSize + : cvsLayout->MemberOffsets[i+1]) + - cvsLayout->MemberOffsets[i]) - fieldSize; + sizeSoFar += fieldSize + padSize; + + // Now print the actual field value + emitGlobalConstant(field); + + // Insert the field padding unless it's zero bytes... + if (padSize) + O << ZeroDirective << padSize << "\n"; + } + assert(sizeSoFar == cvsLayout->StructSize && + "Layout of constant struct may be incorrect!"); + return; + } else if (const ConstantFP *CFP = dyn_cast(CV)) { + // FP Constants are printed as integer constants to avoid losing + // precision... + double Val = CFP->getValue(); + if (CFP->getType() == Type::DoubleTy) { + union DU { // Abide by C TBAA rules + double FVal; + uint64_t UVal; + } U; + U.FVal = Val; + + if (TD.isBigEndian()) { + O << Data32bitsDirective << unsigned(U.UVal >> 32) + << "\t; double most significant word " << Val << "\n"; + O << Data32bitsDirective << unsigned(U.UVal) + << "\t; double least significant word " << Val << "\n"; + } else { + O << Data32bitsDirective << unsigned(U.UVal) + << "\t; double least significant word " << Val << "\n"; + O << Data32bitsDirective << unsigned(U.UVal >> 32) + << "\t; double most significant word " << Val << "\n"; + } + return; + } else { + union FU { // Abide by C TBAA rules + float FVal; + int32_t UVal; + } U; + U.FVal = Val; + + O << Data32bitsDirective << U.UVal << "\t; float " << Val << "\n"; + return; + } + } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) { + if (const ConstantInt *CI = dyn_cast(CV)) { + uint64_t Val = CI->getRawValue(); + + if (TD.isBigEndian()) { + O << Data32bitsDirective << unsigned(Val >> 32) + << "\t; Double-word most significant word " << Val << "\n"; + O << Data32bitsDirective << unsigned(Val) + << "\t; Double-word least significant word " << Val << "\n"; + } else { + O << Data32bitsDirective << unsigned(Val) + << "\t; Double-word least significant word " << Val << "\n"; + O << Data32bitsDirective << unsigned(Val >> 32) + << "\t; Double-word most significant word " << Val << "\n"; + } + return; + } + } + + const Type *type = CV->getType(); + O << "\t"; + switch (type->getTypeID()) { + case Type::UByteTyID: case Type::SByteTyID: + O << Data8bitsDirective; + break; + case Type::UShortTyID: case Type::ShortTyID: + O << Data16bitsDirective; + break; + case Type::BoolTyID: + case Type::PointerTyID: + case Type::UIntTyID: case Type::IntTyID: + O << Data32bitsDirective; + break; + case Type::ULongTyID: case Type::LongTyID: + assert (0 && "Should have already output double-word constant."); + case Type::FloatTyID: case Type::DoubleTyID: + assert (0 && "Should have already output floating point constant."); + default: + assert (0 && "Can't handle printing this type of thing"); + break; + } + emitConstantValueOnly(CV); + O << "\n"; +} -- 2.11.0