From 193c2358507b151ffbca2f0bb6fbfba55b60bdbd Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 2 Jun 2008 21:30:49 +0000 Subject: [PATCH] Implement CBE support for first-class structs and array values, and insertvalue and extractvalue instructions. First-class array values are not trivial because C doesn't support them. The approach I took here is to wrap all arrays in structs. Feedback is welcome. The 2007-01-15-NamedArrayType.ll test needed to be modified because it has a "not grep" for a string that now exists, because array types now have associated struct types, and those struct types have names. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51881 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/CBackend/CBackend.cpp | 95 +++++++++++++++---- .../CBackend/2007-01-15-NamedArrayType.ll | 2 +- 2 files changed, 78 insertions(+), 19 deletions(-) diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 440ce1cb4a4..16abb05169f 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -171,7 +171,7 @@ namespace { void printModule(Module *M); void printModuleTypes(const TypeSymbolTable &ST); - void printContainedStructs(const Type *Ty, std::set &); + void printContainedStructs(const Type *Ty, std::set &); void printFloatingPointConstants(Function &F); void printFunctionSignature(const Function *F, bool Prototype); @@ -210,7 +210,8 @@ namespace { // emit it inline where it would go. if (I.getType() == Type::VoidTy || !I.hasOneUse() || isa(I) || isa(I) || isa(I) || - isa(I) || isa(I) || isa(I)) + isa(I) || isa(I) || isa(I) || + isa(I)) // Don't inline a load across a store or other bad things! return false; @@ -286,6 +287,9 @@ namespace { void visitShuffleVectorInst(ShuffleVectorInst &SVI); void visitGetResultInst(GetResultInst &GRI); + void visitInsertValueInst(InsertValueInst &I); + void visitExtractValueInst(ExtractValueInst &I); + void visitInstruction(Instruction &I) { cerr << "C Writer does not know about " << I; abort(); @@ -325,9 +329,10 @@ bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) { TI != TE; ) { TypeSymbolTable::iterator I = TI++; - // If this isn't a struct type, remove it from our set of types to name. - // This simplifies emission later. - if (!isa(I->second) && !isa(I->second)) { + // If this isn't a struct or array type, remove it from our set of types + // to name. This simplifies emission later. + if (!isa(I->second) && !isa(I->second) && + !isa(I->second)) { TST.remove(I); } else { // If this is not used, remove it from the symbol table. @@ -346,8 +351,8 @@ bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) { unsigned RenameCounter = 0; for (std::set::const_iterator I = UT.begin(), E = UT.end(); I != E; ++I) - if (const StructType *ST = dyn_cast(*I)) { - while (M.addTypeName("unnamed"+utostr(RenameCounter), ST)) + if (isa(*I) || isa(*I)) { + while (M.addTypeName("unnamed"+utostr(RenameCounter), *I)) ++RenameCounter; Changed = true; } @@ -557,8 +562,12 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty, const ArrayType *ATy = cast(Ty); unsigned NumElements = ATy->getNumElements(); if (NumElements == 0) NumElements = 1; - return printType(Out, ATy->getElementType(), false, - NameSoFar + "[" + utostr(NumElements) + "]"); + // Arrays are wrapped in structs to allow them to have normal + // value semantics (avoiding the array "decay"). + Out << NameSoFar << " { "; + printType(Out, ATy->getElementType(), false, + "array[" + utostr(NumElements) + "]"); + return Out << "; }"; } case Type::OpaqueTyID: { @@ -1013,6 +1022,7 @@ void CWriter::printConstant(Constant *CPV) { } case Type::ArrayTyID: + Out << "{ "; // Arrays are wrapped in struct types. if (ConstantArray *CA = dyn_cast(CPV)) { printConstantArray(CA); } else { @@ -1030,6 +1040,7 @@ void CWriter::printConstant(Constant *CPV) { } Out << " }"; } + Out << " }"; // Arrays are wrapped in struct types. break; case Type::VectorTyID: @@ -1760,9 +1771,12 @@ bool CWriter::doInitialization(Module &M) { // the compiler figure out the rest of the zeros. Out << " = " ; if (isa(I->getInitializer()->getType()) || - isa(I->getInitializer()->getType()) || isa(I->getInitializer()->getType())) { Out << "{ 0 }"; + } else if (isa(I->getInitializer()->getType())) { + // As with structs and vectors, but with an extra set of braces + // because arrays are wrapped in structs. + Out << "{ { 0 } }"; } else { // Just print it out normally. writeOperand(I->getInitializer()); @@ -1904,16 +1918,16 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) { Out << '\n'; // Keep track of which structures have been printed so far... - std::set StructPrinted; + std::set StructPrinted; // Loop over all structures then push them into the stack so they are // printed in the correct order. // Out << "/* Structure contents */\n"; for (I = TST.begin(); I != End; ++I) - if (const StructType *STy = dyn_cast(I->second)) + if (isa(I->second) || isa(I->second)) // Only print out used types! - printContainedStructs(STy, StructPrinted); + printContainedStructs(I->second, StructPrinted); } // Push the struct onto the stack and recursively push all structs @@ -1922,7 +1936,7 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) { // TODO: Make this work properly with vector types // void CWriter::printContainedStructs(const Type *Ty, - std::set &StructPrinted){ + std::set &StructPrinted) { // Don't walk through pointers. if (isa(Ty) || Ty->isPrimitiveType() || Ty->isInteger()) return; @@ -1931,12 +1945,12 @@ void CWriter::printContainedStructs(const Type *Ty, E = Ty->subtype_end(); I != E; ++I) printContainedStructs(*I, StructPrinted); - if (const StructType *STy = dyn_cast(Ty)) { + if (isa(Ty) || isa(Ty)) { // Check to see if we have already printed this struct. - if (StructPrinted.insert(STy).second) { + if (StructPrinted.insert(Ty).second) { // Print structure type out. - std::string Name = TypeNames[STy]; - printType(Out, STy, false, Name, true); + std::string Name = TypeNames[Ty]; + printType(Out, Ty, false, Name, true); Out << ";\n\n"; } } @@ -3097,6 +3111,10 @@ void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I, for (; I != E; ++I) { if (isa(*I)) { Out << ".field" << cast(I.getOperand())->getZExtValue(); + } else if (isa(*I)) { + Out << ".array["; + writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); + Out << ']'; } else if (!isa(*I)) { Out << '['; writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); @@ -3255,6 +3273,47 @@ void CWriter::visitGetResultInst(GetResultInst &GRI) { Out << ")"; } +void CWriter::visitInsertValueInst(InsertValueInst &IVI) { + // Start by copying the entire aggregate value into the result variable. + writeOperand(IVI.getOperand(0)); + Out << ";\n "; + + // Then do the insert to update the field. + Out << GetValueName(&IVI); + for (const unsigned *b = IVI.idx_begin(), *i = b, *e = IVI.idx_end(); + i != e; ++i) { + const Type *IndexedTy = + ExtractValueInst::getIndexedType(IVI.getOperand(0)->getType(), b, i+1); + if (isa(IndexedTy)) + Out << ".array[" << *i << "]"; + else + Out << ".field" << *i; + } + Out << " = "; + writeOperand(IVI.getOperand(1)); +} + +void CWriter::visitExtractValueInst(ExtractValueInst &EVI) { + Out << "("; + if (isa(EVI.getOperand(0))) { + Out << "("; + printType(Out, EVI.getType()); + Out << ") 0/*UNDEF*/"; + } else { + Out << GetValueName(EVI.getOperand(0)); + for (const unsigned *b = EVI.idx_begin(), *i = b, *e = EVI.idx_end(); + i != e; ++i) { + const Type *IndexedTy = + ExtractValueInst::getIndexedType(EVI.getOperand(0)->getType(), b, i+1); + if (isa(IndexedTy)) + Out << ".array[" << *i << "]"; + else + Out << ".field" << *i; + } + } + Out << ")"; +} + //===----------------------------------------------------------------------===// // External Interface declaration //===----------------------------------------------------------------------===// diff --git a/test/CodeGen/CBackend/2007-01-15-NamedArrayType.ll b/test/CodeGen/CBackend/2007-01-15-NamedArrayType.ll index a9eeff3bffd..42fa0d897f6 100644 --- a/test/CodeGen/CBackend/2007-01-15-NamedArrayType.ll +++ b/test/CodeGen/CBackend/2007-01-15-NamedArrayType.ll @@ -1,5 +1,5 @@ ; PR918 -; RUN: llvm-as < %s | llc -march=c | not grep fixarray_array3 +; RUN: llvm-as < %s | llc -march=c | not grep {l_structtype_s l_fixarray_array3} %structtype_s = type { i32 } %fixarray_array3 = type [3 x %structtype_s] -- 2.34.1