From fee76265ff7d8360c629eb6289e2166576272208 Mon Sep 17 00:00:00 2001 From: "Vikram S. Adve" Date: Sun, 13 Oct 2002 00:32:18 +0000 Subject: [PATCH] Several major fixes, particularly in emitting constant aggregates: (1) Padding bytes between structure fields (for alignment) were never being emitted into the constant pool so the layout did not match! (2) In printing constants, structures containing structures or arrays were never handled. (3) Support new model for external/uninitialized/initialized globals. Uninitialized globals are no longer emitted since they are external. Initialized globals may go either in .bss or in .data. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4134 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SparcV9/SparcV9AsmPrinter.cpp | 165 ++++++++++++++--------- 1 file changed, 105 insertions(+), 60 deletions(-) diff --git a/lib/Target/SparcV9/SparcV9AsmPrinter.cpp b/lib/Target/SparcV9/SparcV9AsmPrinter.cpp index 9822ae80b95..7342baba973 100644 --- a/lib/Target/SparcV9/SparcV9AsmPrinter.cpp +++ b/lib/Target/SparcV9/SparcV9AsmPrinter.cpp @@ -60,7 +60,7 @@ public: Text, ReadOnlyData, InitRWData, - UninitRWData, + ZeroInitRWData, } CurSection; AsmPrinter(std::ostream &os, const TargetMachine &T) @@ -105,7 +105,7 @@ public: case Text: toAsm << "\".text\""; break; case ReadOnlyData: toAsm << "\".rodata\",#alloc"; break; case InitRWData: toAsm << "\".data\",#alloc,#write"; break; - case UninitRWData: toAsm << "\".bss\",#alloc,#write"; break; + case ZeroInitRWData: toAsm << "\".bss\",#alloc,#write"; break; } toAsm << "\n"; } @@ -541,28 +541,29 @@ public: } private: - void emitGlobalsAndConstants(const Module &M); + void emitGlobalsAndConstants (const Module &M); - void printGlobalVariable(const GlobalVariable *GV); - void printSingleConstant( const Constant* CV); - void printConstantValueOnly(const Constant* CV); - void printConstant( const Constant* CV, std::string valID = ""); + void printGlobalVariable (const GlobalVariable *GV); + void PrintZeroBytesToPad (int numBytes); + void printSingleConstantValue (const Constant* CV); + void printConstantValueOnly (const Constant* CV, int numPadBytes = 0); + void printConstant (const Constant* CV, std::string valID = ""); - static void FoldConstants(const Module &M, - hash_set &moduleConstants); + static void FoldConstants (const Module &M, + hash_set &moduleConstants); }; // Can we treat the specified array as a string? Only if it is an array of // ubytes or non-negative sbytes. // -static bool isStringCompatible(const ConstantArray *CPA) { - const Type *ETy = cast(CPA->getType())->getElementType(); +static bool isStringCompatible(const ConstantArray *CVA) { + const Type *ETy = cast(CVA->getType())->getElementType(); if (ETy == Type::UByteTy) return true; if (ETy != Type::SByteTy) return false; - for (unsigned i = 0; i < CPA->getNumOperands(); ++i) - if (cast(CPA->getOperand(i))->getValue() < 0) + for (unsigned i = 0; i < CVA->getNumOperands(); ++i) + if (cast(CVA->getOperand(i))->getValue() < 0) return false; return true; @@ -576,16 +577,16 @@ static inline char toOctal(int X) { // getAsCString - Return the specified array as a C compatible string, only if // the predicate isStringCompatible is true. // -static string getAsCString(const ConstantArray *CPA) { - assert(isStringCompatible(CPA) && "Array is not string compatible!"); +static string getAsCString(const ConstantArray *CVA) { + assert(isStringCompatible(CVA) && "Array is not string compatible!"); string Result; - const Type *ETy = cast(CPA->getType())->getElementType(); + const Type *ETy = cast(CVA->getType())->getElementType(); Result = "\""; - for (unsigned i = 0; i < CPA->getNumOperands(); ++i) { + for (unsigned i = 0; i < CVA->getNumOperands(); ++i) { unsigned char C = (ETy == Type::SByteTy) ? - (unsigned char)cast(CPA->getOperand(i))->getValue() : - (unsigned char)cast(CPA->getOperand(i))->getValue(); + (unsigned char)cast(CVA->getOperand(i))->getValue() : + (unsigned char)cast(CVA->getOperand(i))->getValue(); if (C == '"') { Result += "\\\""; @@ -649,24 +650,30 @@ TypeToDataDirective(const Type* type) } } +// Get the size of the type +// +inline unsigned int +TypeToSize(const Type* type, const TargetMachine& target) +{ + return target.findOptimalStorageSize(type); +} + // Get the size of the constant for the given target. // If this is an unsized array, return 0. // inline unsigned int ConstantToSize(const Constant* CV, const TargetMachine& target) { - if (const ConstantArray* CPA = dyn_cast(CV)) + if (const ConstantArray* CVA = dyn_cast(CV)) { - const ArrayType *aty = cast(CPA->getType()); + const ArrayType *aty = cast(CVA->getType()); if (ArrayTypeIsString(aty)) - return 1 + CPA->getNumOperands(); + return 1 + CVA->getNumOperands(); } - return target.findOptimalStorageSize(CV->getType()); + return TypeToSize(CV->getType(), target); } - - // Align data larger than one L1 cache line on L1 cache line boundaries. // Align all smaller data on the next higher 2^x boundary (4, 8, ...). // @@ -687,7 +694,7 @@ SizeToAlignment(unsigned int size, const TargetMachine& target) inline unsigned int TypeToAlignment(const Type* type, const TargetMachine& target) { - return SizeToAlignment(target.findOptimalStorageSize(type), target); + return SizeToAlignment(TypeToSize(type, target), target); } // Get the size of the constant and then use SizeToAlignment. @@ -695,9 +702,9 @@ TypeToAlignment(const Type* type, const TargetMachine& target) inline unsigned int ConstantToAlignment(const Constant* CV, const TargetMachine& target) { - if (const ConstantArray* CPA = dyn_cast(CV)) - if (ArrayTypeIsString(cast(CPA->getType()))) - return SizeToAlignment(1 + CPA->getNumOperands(), target); + if (const ConstantArray* CVA = dyn_cast(CV)) + if (ArrayTypeIsString(cast(CVA->getType()))) + return SizeToAlignment(1 + CVA->getNumOperands(), target); return TypeToAlignment(CV->getType(), target); } @@ -705,7 +712,7 @@ ConstantToAlignment(const Constant* CV, const TargetMachine& target) // Print a single constant value. void -SparcModuleAsmPrinter::printSingleConstant(const Constant* CV) +SparcModuleAsmPrinter::printSingleConstantValue(const Constant* CV) { assert(CV->getType() != Type::VoidTy && CV->getType() != Type::TypeTy && @@ -759,31 +766,68 @@ SparcModuleAsmPrinter::printSingleConstant(const Constant* CV) } } -// Print a constant value or values (it may be an aggregate). -// Uses printSingleConstant() to print each individual value. void -SparcModuleAsmPrinter::printConstantValueOnly(const Constant* CV) +SparcModuleAsmPrinter::PrintZeroBytesToPad(int numBytes) { - const ConstantArray *CPA = dyn_cast(CV); - - if (CPA && isStringCompatible(CPA)) + for ( ; numBytes >= 8; numBytes -= 8) + printSingleConstantValue(Constant::getNullValue(Type::ULongTy)); + + if (numBytes >= 4) + { + printSingleConstantValue(Constant::getNullValue(Type::UIntTy)); + numBytes -= 4; + } + + while (numBytes--) + printSingleConstantValue(Constant::getNullValue(Type::UByteTy)); +} + +// Print a constant value or values (it may be an aggregate). +// Uses printSingleConstantValue() to print each individual value. +void +SparcModuleAsmPrinter::printConstantValueOnly(const Constant* CV, + int numPadBytes /* = 0*/) +{ + const ConstantArray *CVA = dyn_cast(CV); + + if (numPadBytes) + PrintZeroBytesToPad(numPadBytes); + + if (CVA && isStringCompatible(CVA)) { // print the string alone and return - toAsm << "\t" << ".ascii" << "\t" << getAsCString(CPA) << "\n"; + toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; } - else if (CPA) + else if (CVA) { // Not a string. Print the values in successive locations - const std::vector &constValues = CPA->getValues(); + const std::vector &constValues = CVA->getValues(); for (unsigned i=0; i < constValues.size(); i++) printConstantValueOnly(cast(constValues[i].get())); } - else if (const ConstantStruct *CPS = dyn_cast(CV)) - { // Print the fields in successive locations - const std::vector& constValues = CPS->getValues(); - for (unsigned i=0; i < constValues.size(); i++) - printConstantValueOnly(cast(constValues[i].get())); + else if (const ConstantStruct *CVS = dyn_cast(CV)) + { // Print the fields in successive locations. Pad to align if needed! + const StructLayout *cvsLayout = + Target.DataLayout.getStructLayout(CVS->getType()); + const std::vector& constValues = CVS->getValues(); + unsigned sizeSoFar = 0; + for (unsigned i=0, N = constValues.size(); i < N; i++) + { + const Constant* field = cast(constValues[i].get()); + + // Check if padding is needed and insert one or more 0s. + unsigned fieldSize = Target.DataLayout.getTypeSize(field->getType()); + int padSize = ((i == N-1? cvsLayout->StructSize + : cvsLayout->MemberOffsets[i+1]) + - cvsLayout->MemberOffsets[i]) - fieldSize; + sizeSoFar += (fieldSize + padSize); + + // Now print the actual field value + printConstantValueOnly(field, padSize); + } + assert(sizeSoFar == cvsLayout->StructSize && + "Layout of constant struct may be incorrect!"); } else - printSingleConstant(CV); + printSingleConstantValue(CV); } // Print a constant (which may be an aggregate) prefixed by all the @@ -798,11 +842,11 @@ SparcModuleAsmPrinter::printConstant(const Constant* CV, string valID) toAsm << "\t.align\t" << ConstantToAlignment(CV, Target) << "\n"; // Print .size and .type only if it is not a string. - const ConstantArray *CPA = dyn_cast(CV); - if (CPA && isStringCompatible(CPA)) + const ConstantArray *CVA = dyn_cast(CV); + if (CVA && isStringCompatible(CVA)) { // print it as a string and return toAsm << valID << ":\n"; - toAsm << "\t" << ".ascii" << "\t" << getAsCString(CPA) << "\n"; + toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; return; } @@ -833,14 +877,14 @@ void SparcModuleAsmPrinter::printGlobalVariable(const GlobalVariable* GV) if (GV->hasExternalLinkage()) toAsm << "\t.global\t" << getID(GV) << "\n"; - if (GV->hasInitializer()) + if (GV->hasInitializer() && ! GV->getInitializer()->isNullValue()) printConstant(GV->getInitializer(), getID(GV)); else { toAsm << "\t.align\t" << TypeToAlignment(GV->getType()->getElementType(), Target) << "\n"; toAsm << "\t.type\t" << getID(GV) << ",#object\n"; toAsm << "\t.reserve\t" << getID(GV) << "," - << Target.findOptimalStorageSize(GV->getType()->getElementType()) + << TypeToSize(GV->getType()->getElementType(), Target) << "\n"; } } @@ -863,17 +907,18 @@ void SparcModuleAsmPrinter::emitGlobalsAndConstants(const Module &M) { printConstant(*I); // Output global variables... - for (Module::const_giterator GI = M.gbegin(), GE = M.gend(); GI != GE; ++GI) { - if (GI->hasInitializer() && GI->isConstant()) { - enterSection(AsmPrinter::ReadOnlyData); // read-only, initialized data - } else if (GI->hasInitializer() && !GI->isConstant()) { // read-write data - enterSection(AsmPrinter::InitRWData); - } else { - assert (!GI->hasInitializer() && "Unexpected global variable type found"); - enterSection(AsmPrinter::UninitRWData); // Uninitialized data + for (Module::const_giterator GI = M.gbegin(), GE = M.gend(); GI != GE; ++GI) + if (! GI->isExternal()) { + assert(GI->hasInitializer()); + if (GI->isConstant()) + enterSection(AsmPrinter::ReadOnlyData); // read-only, initialized data + else if (GI->getInitializer()->isNullValue()) + enterSection(AsmPrinter::ZeroInitRWData); // read-write zero data + else + enterSection(AsmPrinter::InitRWData); // read-write non-zero data + + printGlobalVariable(GI); } - printGlobalVariable(GI); - } toAsm << "\n"; }