static void SplitUpPHINode(PHINode *Phi) { StructType *STy = cast<StructType>(Phi->getType()); Value *NewStruct = UndefValue::get(STy); Instruction *NewStructInsertPt = Phi->getParent()->getFirstInsertionPt(); // Create a separate PHINode for each struct field. for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { SmallVector<unsigned, 1> EVIndexes; EVIndexes.push_back(Index); PHINode *NewPhi = PHINode::Create( STy->getElementType(Index), Phi->getNumIncomingValues(), Phi->getName() + ".index", Phi); CopyDebug(NewPhi, Phi); for (unsigned PhiIndex = 0; PhiIndex < Phi->getNumIncomingValues(); ++PhiIndex) { BasicBlock *IncomingBB = Phi->getIncomingBlock(PhiIndex); Value *EV = CopyDebug( ExtractValueInst::Create( Phi->getIncomingValue(PhiIndex), EVIndexes, Phi->getName() + ".extract", IncomingBB->getTerminator()), Phi); NewPhi->addIncoming(EV, IncomingBB); } // Reconstruct the original struct value. NewStruct = CopyDebug( InsertValueInst::Create(NewStruct, NewPhi, EVIndexes, Phi->getName() + ".insert", NewStructInsertPt), Phi); } Phi->replaceAllUsesWith(NewStruct); Phi->eraseFromParent(); }
/// \brief Checks if a type could have padding bytes. bool ArgPromotion::isDenselyPacked(Type *type) { // There is no size information, so be conservative. if (!type->isSized()) return false; // If the alloc size is not equal to the storage size, then there are padding // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128. if (!DL || DL->getTypeSizeInBits(type) != DL->getTypeAllocSizeInBits(type)) return false; if (!isa<CompositeType>(type)) return true; // For homogenous sequential types, check for padding within members. if (SequentialType *seqTy = dyn_cast<SequentialType>(type)) return isa<PointerType>(seqTy) || isDenselyPacked(seqTy->getElementType()); // Check for padding within and between elements of a struct. StructType *StructTy = cast<StructType>(type); const StructLayout *Layout = DL->getStructLayout(StructTy); uint64_t StartPos = 0; for (unsigned i = 0, E = StructTy->getNumElements(); i < E; ++i) { Type *ElTy = StructTy->getElementType(i); if (!isDenselyPacked(ElTy)) return false; if (StartPos != Layout->getElementOffsetInBits(i)) return false; StartPos += DL->getTypeAllocSizeInBits(ElTy); } return true; }
Value *AArch64TTIImpl::getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType) { switch (Inst->getIntrinsicID()) { default: return nullptr; case Intrinsic::aarch64_neon_st2: case Intrinsic::aarch64_neon_st3: case Intrinsic::aarch64_neon_st4: { // Create a struct type StructType *ST = dyn_cast<StructType>(ExpectedType); if (!ST) return nullptr; unsigned NumElts = Inst->getNumArgOperands() - 1; if (ST->getNumElements() != NumElts) return nullptr; for (unsigned i = 0, e = NumElts; i != e; ++i) { if (Inst->getArgOperand(i)->getType() != ST->getElementType(i)) return nullptr; } Value *Res = UndefValue::get(ExpectedType); IRBuilder<> Builder(Inst); for (unsigned i = 0, e = NumElts; i != e; ++i) { Value *L = Inst->getArgOperand(i); Res = Builder.CreateInsertValue(Res, L, i); } return Res; } case Intrinsic::aarch64_neon_ld2: case Intrinsic::aarch64_neon_ld3: case Intrinsic::aarch64_neon_ld4: if (Inst->getType() == ExpectedType) return Inst; return nullptr; } }
string llvm_type::getTypeName() { if (data->isStructTy()) { StructType* st = (StructType*) data; return st->getName().str(); } return ""; }
/// Returns the byte alignment of this type unsigned getTypeAlignment(const llvm::Type* type) { using namespace llvm; // Array types are aligned to their element type if (const ArrayType* psAT = dyn_cast<ArrayType>(type)) { return getTypeAlignment(psAT->getElementType()); } // Struct alignment is the size of its largest contained type if (const StructType* structT = dyn_cast<StructType>(type)) { if (structT->isPacked()) return 1; StructType* nonConstTy = const_cast<StructType*>(structT); unsigned uAlign = 0, uMaxAlign = 1; unsigned uCount = structT->getNumElements(); for (unsigned i = 0; i < uCount; i++) { const Type* psElemType = nonConstTy->getTypeAtIndex(i); uAlign = getTypeAlignment(psElemType); if (uAlign > uMaxAlign) uMaxAlign = uAlign; } return uMaxAlign; } return getTypeSize(type); }
static bool SplitUpStore(StoreInst *Store, const DataLayout *DL) { StructType *STy = cast<StructType>(Store->getValueOperand()->getType()); bool NeedsAnotherPass = false; // Create a separate store instruction for each struct field. for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { SmallVector<Value *, 2> Indexes; Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, 0))); Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, Index))); Value *GEP = CopyDebug(GetElementPtrInst::Create(STy, Store->getPointerOperand(), Indexes, Store->getPointerOperand()->getName() + ".index", Store), Store); NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(GEP->getType()->getContainedType(0)); SmallVector<unsigned, 1> EVIndexes; EVIndexes.push_back(Index); Value *Field = ExtractValueInst::Create(Store->getValueOperand(), EVIndexes, "", Store); StoreInst *NewStore = new StoreInst(Field, GEP, Store); ProcessLoadOrStoreAttrs(NewStore, Store, STy, Index, DL); } Store->eraseFromParent(); return NeedsAnotherPass; }
static void SplitUpLoad(LoadInst *Load) { StructType *STy = cast<StructType>(Load->getType()); Value *NewStruct = UndefValue::get(STy); // Create a separate load instruction for each struct field. for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { SmallVector<Value *, 2> Indexes; Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, 0))); Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, Index))); Value *GEP = CopyDebug( GetElementPtrInst::Create(Load->getPointerOperand(), Indexes, Load->getName() + ".index", Load), Load); LoadInst *NewLoad = new LoadInst(GEP, Load->getName() + ".field", Load); ProcessLoadOrStoreAttrs(NewLoad, Load); // Reconstruct the struct value. SmallVector<unsigned, 1> EVIndexes; EVIndexes.push_back(Index); NewStruct = CopyDebug( InsertValueInst::Create(NewStruct, NewLoad, EVIndexes, Load->getName() + ".insert", Load), Load); } Load->replaceAllUsesWith(NewStruct); Load->eraseFromParent(); }
void TypeDeduction::Visit(MemberExpression* node) { //TODO: Finish it. node->GetContainer()->Accept(this); StructType *structType = dynamic_cast<StructType *>(node->GetContainer()->GetTag<Type>("Type")); if (structType == NULL) { CompilationContext::GetInstance()->ReportError(node->SourceLocation, false, "Member expression requires struct type."); } std::vector<Declaration *> * fileds = structType->GetFieldList(); for (std::vector<Declaration *>::iterator it = fileds->begin(); it != fileds->end(); ++it) { Declaration *decl = *it; if (decl->GetName() == node->GetFieldName()) { Type *fieldType = decl->GetType(); node->SetTag<Type>("Type", fieldType); return; } } CompilationContext::GetInstance()->ReportError(node->SourceLocation, false, "%s is not a member of type %s", node->GetFieldName().c_str(), structType->ToString().c_str()); abort(); }
FunctionType* ArgumentRecovery::createFunctionType(TargetInfo& info, const CallInformation& callInfo, llvm::Module& module, StringRef returnTypeName, SmallVectorImpl<string>& parameterNames) { LLVMContext& ctx = module.getContext(); Type* integer = Type::getIntNTy(ctx, info.getPointerSize() * CHAR_BIT); SmallVector<Type*, 8> parameterTypes; for (const auto& param : callInfo.parameters()) { if (param.type == ValueInformation::IntegerRegister) { parameterTypes.push_back(integer); parameterNames.push_back(param.registerInfo->name); } else if (param.type == ValueInformation::Stack) { parameterTypes.push_back(integer); parameterNames.emplace_back(); raw_string_ostream(parameterNames.back()) << "sp" << param.frameBaseOffset; } else { llvm_unreachable("not implemented"); } } SmallVector<Type*, 2> returnTypes; for (const auto& ret : callInfo.returns()) { if (ret.type == ValueInformation::IntegerRegister) { returnTypes.push_back(integer); } else { llvm_unreachable("not implemented"); } } Type* returnType; if (returnTypes.size() == 0) { returnType = Type::getVoidTy(ctx); } else if (returnTypes.size() == 1) { returnType = returnTypes.front(); } else { StructType* structTy = StructType::create(ctx, returnTypeName); structTy->setBody(returnTypes); md::setRecoveredReturnFieldNames(module, *structTy, callInfo); returnType = structTy; } assert(!callInfo.isVararg() && "not implemented"); return FunctionType::get(returnType, parameterTypes, false); }
void GcInfo::getGcPointers(StructType *StructTy, const DataLayout &DataLayout, SmallVector<uint32_t, 4> &Pointers) { assert(StructTy->isSized()); const uint32_t PointerSize = DataLayout.getPointerSize(); const uint32_t TypeSize = DataLayout.getTypeStoreSize(StructTy); const StructLayout *MainStructLayout = DataLayout.getStructLayout(StructTy); // Walk through the type in pointer-sized jumps. for (uint32_t GcOffset = 0; GcOffset < TypeSize; GcOffset += PointerSize) { const uint32_t FieldIndex = MainStructLayout->getElementContainingOffset(GcOffset); Type *FieldTy = StructTy->getStructElementType(FieldIndex); // If the field is a value class we need to dive in // to its fields and so on, until we reach a primitive type. if (FieldTy->isStructTy()) { // Prepare to loop through the nesting. const StructLayout *OuterStructLayout = MainStructLayout; uint32_t OuterOffset = GcOffset; uint32_t OuterIndex = FieldIndex; while (FieldTy->isStructTy()) { // Offset of the Inner class within the outer class const uint32_t InnerBaseOffset = OuterStructLayout->getElementOffset(OuterIndex); // Inner class should start at or before the outer offset assert(InnerBaseOffset <= OuterOffset); // Determine target offset relative to this inner class. const uint32_t InnerOffset = OuterOffset - InnerBaseOffset; // Get the inner class layout StructType *InnerStructTy = cast<StructType>(FieldTy); const StructLayout *InnerStructLayout = DataLayout.getStructLayout(InnerStructTy); // Find the field at that target offset. const uint32_t InnerIndex = InnerStructLayout->getElementContainingOffset(InnerOffset); // Update for next iteration. FieldTy = InnerStructTy->getStructElementType(InnerIndex); OuterStructLayout = InnerStructLayout; OuterOffset = InnerOffset; OuterIndex = InnerIndex; } } if (GcInfo::isGcPointer(FieldTy)) { Pointers.push_back(GcOffset); } } }
void Library::AddStruct(const StructType &structType) { if (m_RegisteredStruct.find(structType.GetName()) != m_RegisteredStruct.end()) { return; } m_RegisteredStruct.insert(structType.GetName()); for (auto it : structType.GetArgs()) { std::shared_ptr<StructType> st = it->GetStructType(); if (st.get() != nullptr) { AddStruct(*st); } } structType.EmitForwardDeclaration(m_Stream); }
void ExportPass::ConstructModuleSymbols() { CProcedureType* originalType = dynamic_cast<CProcedureType*>(originalProcedure->get_procedure_symbol()->get_type()) ; assert(originalType != NULL) ; // The original type takes and returns a struct. We need to change this // to a list of arguments. VoidType* newReturnType = create_void_type(theEnv, IInteger(0), 0) ; constructedType = create_c_procedure_type(theEnv, newReturnType, false, // has varargs true, // arguments_known 0, // bit alignment LString("ConstructedType")) ; StructType* returnType = dynamic_cast<StructType*>(originalType->get_result_type()) ; assert(returnType != NULL) ; SymbolTable* structSymTab = returnType->get_group_symbol_table() ; assert(structSymTab != NULL) ; for (int i = 0 ; i < structSymTab->get_symbol_table_object_count() ; ++i) { VariableSymbol* nextVariable = dynamic_cast<VariableSymbol*>(structSymTab->get_symbol_table_object(i)); if (nextVariable != NULL) { // Check to see if this is an output or not QualifiedType* cloneType ; DataType* cloneBase = dynamic_cast<DataType*>(nextVariable->get_type()->get_base_type()->deep_clone()) ; assert(cloneBase != NULL) ; cloneType = create_qualified_type(theEnv, cloneBase) ; if (nextVariable->lookup_annote_by_name("Output") != NULL) { cloneType->append_annote(create_brick_annote(theEnv, "Output")) ; // Why doesn't this stick around? } constructedType->append_argument(cloneType) ; } } constructedSymbol = create_procedure_symbol(theEnv, constructedType, originalProcedure->get_procedure_symbol()->get_name()) ; constructedSymbol->set_definition(NULL) ; }
// Strip any named types of their names. static void StripTypeNames(Module &M, bool PreserveDbgInfo) { std::vector<StructType*> StructTypes; M.findUsedStructTypes(StructTypes); for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) { StructType *STy = StructTypes[i]; if (STy->isAnonymous() || STy->getName().empty()) continue; if (PreserveDbgInfo && STy->getName().startswith("llvm.dbg")) continue; STy->setName(""); } }
bool EfficiencySanitizer::instrumentGetElementPtr(Instruction *I, Module &M) { GetElementPtrInst *GepInst = dyn_cast<GetElementPtrInst>(I); bool Res = false; if (GepInst == nullptr || GepInst->getNumIndices() == 1) { ++NumIgnoredGEPs; return false; } Type *SourceTy = GepInst->getSourceElementType(); StructType *StructTy = nullptr; ConstantInt *Idx; // Check if GEP calculates address from a struct array. if (isa<StructType>(SourceTy)) { StructTy = cast<StructType>(SourceTy); Idx = dyn_cast<ConstantInt>(GepInst->getOperand(1)); if ((Idx == nullptr || Idx->getSExtValue() != 0) && !shouldIgnoreStructType(StructTy) && StructTyMap.count(StructTy) != 0) Res |= insertCounterUpdate(I, StructTy, getArrayCounterIdx(StructTy)); } // Iterate all (except the first and the last) idx within each GEP instruction // for possible nested struct field address calculation. for (unsigned i = 1; i < GepInst->getNumIndices(); ++i) { SmallVector<Value *, 8> IdxVec(GepInst->idx_begin(), GepInst->idx_begin() + i); Type *Ty = GetElementPtrInst::getIndexedType(SourceTy, IdxVec); unsigned CounterIdx = 0; if (isa<ArrayType>(Ty)) { ArrayType *ArrayTy = cast<ArrayType>(Ty); StructTy = dyn_cast<StructType>(ArrayTy->getElementType()); if (shouldIgnoreStructType(StructTy) || StructTyMap.count(StructTy) == 0) continue; // The last counter for struct array access. CounterIdx = getArrayCounterIdx(StructTy); } else if (isa<StructType>(Ty)) { StructTy = cast<StructType>(Ty); if (shouldIgnoreStructType(StructTy) || StructTyMap.count(StructTy) == 0) continue; // Get the StructTy's subfield index. Idx = cast<ConstantInt>(GepInst->getOperand(i+1)); assert(Idx->getSExtValue() >= 0 && Idx->getSExtValue() < StructTy->getNumElements()); CounterIdx = getFieldCounterIdx(StructTy) + Idx->getSExtValue(); } Res |= insertCounterUpdate(I, StructTy, CounterIdx); } if (Res) ++NumInstrumentedGEPs; else ++NumIgnoredGEPs; return Res; }
// Strip any named types of their names. static void StripTypeNames(Module &M, bool PreserveDbgInfo) { TypeFinder StructTypes; StructTypes.run(M, false); for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) { StructType *STy = StructTypes[i]; if (STy->isLiteral() || STy->getName().empty()) continue; if (PreserveDbgInfo && STy->getName().startswith("llvm.dbg")) continue; STy->setName(""); } }
/// Verify - Verify that the specified constraint string is reasonable for the /// specified function type, and otherwise validate the constraint string. bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) { if (Ty->isVarArg()) return false; ConstraintInfoVector Constraints = ParseConstraints(ConstStr); // Error parsing constraints. if (Constraints.empty() && !ConstStr.empty()) return false; unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0; unsigned NumIndirect = 0; for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { switch (Constraints[i].Type) { case InlineAsm::isOutput: if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0) return false; // outputs before inputs and clobbers. if (!Constraints[i].isIndirect) { ++NumOutputs; break; } ++NumIndirect; // FALLTHROUGH for Indirect Outputs. case InlineAsm::isInput: if (NumClobbers) return false; // inputs before clobbers. ++NumInputs; break; case InlineAsm::isClobber: ++NumClobbers; break; } } switch (NumOutputs) { case 0: if (!Ty->getReturnType()->isVoidTy()) return false; break; case 1: if (Ty->getReturnType()->isStructTy()) return false; break; default: StructType *STy = dyn_cast<StructType>(Ty->getReturnType()); if (!STy || STy->getNumElements() != NumOutputs) return false; break; } if (Ty->getNumParams() != NumInputs) return false; return true; }
// Return LLVM Type if TYPE can be returned as an aggregate, // otherwise return NULL. Type *llvm_mips_aggr_type_for_struct_return(tree type) { Type *Ty = ConvertType(type); StructType *STy = cast<StructType>(Ty); std::vector<Type *> ElementTypes; // Special handling for _Complex. if (llvm_mips_should_not_return_complex_in_memory(type)) { ElementTypes.push_back(Type::getDoubleTy(Context)); ElementTypes.push_back(Type::getDoubleTy(Context)); return StructType::get(Context, ElementTypes, STy->isPacked()); } return NULL; }
static void appendToGlobalArray(const char *Array, Module &M, Function *F, int Priority) { IRBuilder<> IRB(M.getContext()); FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); // Get the current set of static global constructors and add the new ctor // to the list. SmallVector<Constant *, 16> CurrentCtors; StructType *EltTy; if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) { // If there is a global_ctors array, use the existing struct type, which can // have 2 or 3 fields. ArrayType *ATy = cast<ArrayType>(GVCtor->getType()->getElementType()); EltTy = cast<StructType>(ATy->getElementType()); if (Constant *Init = GVCtor->getInitializer()) { unsigned n = Init->getNumOperands(); CurrentCtors.reserve(n + 1); for (unsigned i = 0; i != n; ++i) CurrentCtors.push_back(cast<Constant>(Init->getOperand(i))); } GVCtor->eraseFromParent(); } else { // Use a simple two-field struct if there isn't one already. EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy), nullptr); } // Build a 2 or 3 field global_ctor entry. We don't take a comdat key. Constant *CSVals[3]; CSVals[0] = IRB.getInt32(Priority); CSVals[1] = F; // FIXME: Drop support for the two element form in LLVM 4.0. if (EltTy->getNumElements() >= 3) CSVals[2] = llvm::Constant::getNullValue(IRB.getInt8PtrTy()); Constant *RuntimeCtorInit = ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements())); CurrentCtors.push_back(RuntimeCtorInit); // Create a new initializer. ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size()); Constant *NewInit = ConstantArray::get(AT, CurrentCtors); // Create the new global variable and replace all uses of // the old global variable with the new one. (void)new GlobalVariable(M, NewInit->getType(), false, GlobalValue::AppendingLinkage, NewInit, Array); }
StructTypeDecl* C2Sema::ActOnStructType(const char* name, SourceLocation loc, bool isStruct, bool is_public, bool is_global) { #ifdef SEMA_DEBUG std::cerr << COL_SEMA << "SEMA: Struct/Union Type '" << (name ? name : "<anonymous>"); std::cerr << ANSI_NORMAL << '\n'; #endif QualType qt = typeContext.getStructType(); StructTypeDecl* S = new StructTypeDecl(name, loc, qt, isStruct, is_global, is_public); StructType* ST = cast<StructType>(qt.getTypePtr()); ST->setDecl(S); if (is_global) { ast.addType(S); addSymbol(S); } return S; }
void TypeMapTy::linkDefinedTypeBodies() { SmallVector<Type *, 16> Elements; for (StructType *SrcSTy : SrcDefinitionsToResolve) { StructType *DstSTy = cast<StructType>(MappedTypes[SrcSTy]); assert(DstSTy->isOpaque()); // Map the body of the source type over to a new body for the dest type. Elements.resize(SrcSTy->getNumElements()); for (unsigned I = 0, E = Elements.size(); I != E; ++I) Elements[I] = get(SrcSTy->getElementType(I)); DstSTy->setBody(Elements, SrcSTy->isPacked()); DstStructTypesSet.switchToNonOpaque(DstSTy); } SrcDefinitionsToResolve.clear(); DstResolvedOpaqueTypes.clear(); }
int main(int argc, char **argv) { InitializeNativeTarget(); LLVMContext &Context = getGlobalContext(); Module *m = new Module("test", Context); Type *intTy = Type::getInt64Ty(Context); StructType* structTy = StructType::create(Context, "struct.list"); std::vector<Type*> fields; fields.push_back(intTy); fields.push_back(PointerType::get(structTy, 0)); if (structTy->isOpaque()) { structTy->setBody(fields, false); } /* * int f1(struct x *p) { return p->next->l1; } */ std::vector<Type*> args_type; args_type.push_back(PointerType::get(structTy, 0)); FunctionType *fnTy = FunctionType::get(intTy, args_type, false); Function *func = Function::Create(fnTy, GlobalValue::ExternalLinkage, "f1", m); Value *v = func->arg_begin(); BasicBlock *bb = BasicBlock::Create(Context, "EntryBlock", func); IRBuilder<> *builder = new IRBuilder<>(bb); v = builder->CreateStructGEP(v, 1); v = builder->CreateLoad(v, "load0"); v = builder->CreateStructGEP(v, 0); v = builder->CreateLoad(v, "load1"); builder->CreateRet(v); (*m).dump(); { ExecutionEngine *ee = EngineBuilder(m). setEngineKind(EngineKind::JIT).create(); void *f = ee->getPointerToFunction(func); typedef int (*func_t) (struct x *); struct x o = {10, NULL}, v = {}; v.next = &o; std::cout << ((func_t)f)(&v) << std::endl; } return 0; }
StructType *StructType::get(LLVMContext &Context, ArrayRef<Type*> ETypes, bool isPacked) { LLVMContextImpl *pImpl = Context.pImpl; AnonStructTypeKeyInfo::KeyTy Key(ETypes, isPacked); auto I = pImpl->AnonStructTypes.find_as(Key); StructType *ST; if (I == pImpl->AnonStructTypes.end()) { // Value not found. Create a new type! ST = new (Context.pImpl->TypeAllocator) StructType(Context); ST->setSubclassData(SCDB_IsLiteral); // Literal struct. ST->setBody(ETypes, isPacked); Context.pImpl->AnonStructTypes.insert(ST); } else { ST = *I; } return ST; }
void TypeListItem::CreateChildren( wxTreeCtrl* tree, const wxTreeItemId & id) { std::vector<StructType*> structTypes; module_->findUsedStructTypes(structTypes); for (unsigned i = 0, e = structTypes.size(); i != e; ++i) { StructType *sty = structTypes[i]; llvm::StringRef name; if (sty->isLiteral()) { name = "literal struct"; } else if (sty->hasName()) { name = sty->getName(); } else { continue; } CreateChild(tree, id, new TypeItem(module_, sty, toWxStr(name))); } tree->SortChildren(id); }
static void SplitUpStore(StoreInst *Store) { StructType *STy = cast<StructType>(Store->getValueOperand()->getType()); // Create a separate store instruction for each struct field. for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { SmallVector<Value *, 2> Indexes; Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, 0))); Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, Index))); Value *GEP = CopyDebug(GetElementPtrInst::Create( Store->getPointerOperand(), Indexes, Store->getPointerOperand()->getName() + ".index", Store), Store); SmallVector<unsigned, 1> EVIndexes; EVIndexes.push_back(Index); Value *Field = ExtractValueInst::Create(Store->getValueOperand(), EVIndexes, "", Store); StoreInst *NewStore = new StoreInst(Field, GEP, Store); ProcessLoadOrStoreAttrs(NewStore, Store); } Store->eraseFromParent(); }
/// computeTypeMapping - Loop over all of the linked values to compute type /// mappings. For example, if we link "extern Foo *x" and "Foo *x = NULL", then /// we have two struct types 'Foo' but one got renamed when the module was /// loaded into the same LLVMContext. void ModuleLinker::computeTypeMapping() { // Incorporate globals. for (Module::global_iterator I = SrcM->global_begin(), E = SrcM->global_end(); I != E; ++I) { GlobalValue *DGV = getLinkedToGlobal(I); if (DGV == 0) continue; if (!DGV->hasAppendingLinkage() || !I->hasAppendingLinkage()) { TypeMap.addTypeMapping(DGV->getType(), I->getType()); continue; } // Unify the element type of appending arrays. ArrayType *DAT = cast<ArrayType>(DGV->getType()->getElementType()); ArrayType *SAT = cast<ArrayType>(I->getType()->getElementType()); TypeMap.addTypeMapping(DAT->getElementType(), SAT->getElementType()); } // Incorporate functions. for (Module::iterator I = SrcM->begin(), E = SrcM->end(); I != E; ++I) { if (GlobalValue *DGV = getLinkedToGlobal(I)) TypeMap.addTypeMapping(DGV->getType(), I->getType()); } // Incorporate types by name, scanning all the types in the source module. // At this point, the destination module may have a type "%foo = { i32 }" for // example. When the source module got loaded into the same LLVMContext, if // it had the same type, it would have been renamed to "%foo.42 = { i32 }". // Though it isn't required for correctness, attempt to link these up to clean // up the IR. std::vector<StructType*> SrcStructTypes; SrcM->findUsedStructTypes(SrcStructTypes); SmallPtrSet<StructType*, 32> SrcStructTypesSet(SrcStructTypes.begin(), SrcStructTypes.end()); for (unsigned i = 0, e = SrcStructTypes.size(); i != e; ++i) { StructType *ST = SrcStructTypes[i]; if (!ST->hasName()) continue; // Check to see if there is a dot in the name followed by a digit. size_t DotPos = ST->getName().rfind('.'); if (DotPos == 0 || DotPos == StringRef::npos || ST->getName().back() == '.' || !isdigit(ST->getName()[DotPos+1])) continue; // Check to see if the destination module has a struct with the prefix name. if (StructType *DST = DstM->getTypeByName(ST->getName().substr(0, DotPos))) // Don't use it if this actually came from the source module. They're in // the same LLVMContext after all. if (!SrcStructTypesSet.count(DST)) TypeMap.addTypeMapping(DST, ST); } // Don't bother incorporating aliases, they aren't generally typed well. // Now that we have discovered all of the type equivalences, get a body for // any 'opaque' types in the dest module that are now resolved. TypeMap.linkDefinedTypeBodies(); }
void Preparer::expandGlobal(Module &M, GlobalVariable *GV) { if (GV->isDeclaration()) return; if (GV->getLinkage() == GlobalValue::AppendingLinkage) return; Type *OrigType = GV->getType()->getTypeAtIndex((unsigned)0); StructType *NewType = StructType::create(GV->getContext(), "pad_global_type"); NewType->setBody(OrigType, IntegerType::get(GV->getContext(), 8), NULL); // FIXME: AddressSpace? GlobalVariable *NewGV; Constant *NewInit = NULL; if (GV->hasInitializer()) { assert(GV->getInitializer()->getType() == OrigType); NewInit = ConstantStruct::get(NewType, GV->getInitializer(), ConstantInt::get(IntegerType::get(GV->getContext(), 8), 0), NULL); } NewGV = new GlobalVariable(M, NewType, GV->isConstant(), GV->getLinkage(), NewInit, "pad_global", GV, GV->isThreadLocal(), 0); Constant *NewValue = ConstantExpr::getBitCast(NewGV, GV->getType()); assert(NewValue->getType() == GV->getType()); GV->replaceAllUsesWith(NewValue); }
bool PNaClSjLjEH::runOnModule(Module &M) { Type *JmpBufTy = ArrayType::get(Type::getInt8Ty(M.getContext()), kPNaClJmpBufSize); // Define "struct ExceptionFrame". StructType *ExceptionFrameTy = StructType::create(M.getContext(), "ExceptionFrame"); Type *ExceptionFrameFields[] = { JmpBufTy, // jmp_buf ExceptionFrameTy->getPointerTo(), // struct ExceptionFrame *next Type::getInt32Ty(M.getContext()) // Exception info (clause list ID) }; ExceptionFrameTy->setBody(ExceptionFrameFields); ExceptionInfoWriter ExcInfoWriter(&M.getContext()); for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { FuncRewriter Rewriter(ExceptionFrameTy, &ExcInfoWriter, Func); Rewriter.expandFunc(); } ExcInfoWriter.defineGlobalVariables(&M); return true; }
static bool SplitUpSelect(SelectInst *Select) { StructType *STy = cast<StructType>(Select->getType()); Value *NewStruct = UndefValue::get(STy); bool NeedsAnotherPass = false; // Create a separate SelectInst for each struct field. for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { SmallVector<unsigned, 1> EVIndexes; EVIndexes.push_back(Index); Value *TrueVal = CopyDebug( ExtractValueInst::Create(Select->getTrueValue(), EVIndexes, Select->getName() + ".extract", Select), Select); Value *FalseVal = CopyDebug( ExtractValueInst::Create(Select->getFalseValue(), EVIndexes, Select->getName() + ".extract", Select), Select); Value *NewSelect = CopyDebug(SelectInst::Create(Select->getCondition(), TrueVal, FalseVal, Select->getName() + ".index", Select), Select); NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(NewSelect); // Reconstruct the original struct value. NewStruct = CopyDebug( InsertValueInst::Create(NewStruct, NewSelect, EVIndexes, Select->getName() + ".insert", Select), Select); } Select->replaceAllUsesWith(NewStruct); Select->eraseFromParent(); return NeedsAnotherPass; }
bool AllocaMerging::areTypesEquivalent(const cheerp::TypeSupport& types, cheerp::PointerAnalyzer& PA, Type* a, Type* b) { //TODO: Integer types may be equivalent as well if(a==b) return true; else if(a->isPointerTy() && b->isPointerTy()) return true; else if(a->isFloatingPointTy() && b->isFloatingPointTy()) return true; else if(a->isArrayTy() && b->isArrayTy()) { return cast<ArrayType>(a)->getNumElements()==cast<ArrayType>(b)->getNumElements() && areTypesEquivalent(types, PA, a->getArrayElementType(), b->getArrayElementType()); } else if(a->isStructTy() && b->isStructTy()) { // TODO: Byte layout structs with the same size are equivalent if(cast<StructType>(a)->hasByteLayout() || cast<StructType>(b)->hasByteLayout()) return false; StructType* stA = cast<StructType>(a); StructType* stB = cast<StructType>(b); if(stA->getNumElements() != stB->getNumElements()) return false; for(uint32_t i=0;i<stA->getNumElements();i++) { Type* elementA = stA->getElementType(i); Type* elementB = stB->getElementType(i); // The types needs to have consistent wrapper arrays if(types.useWrapperArrayForMember(PA, stA, i) ^ types.useWrapperArrayForMember(PA, stB, i)) return false; if(!areTypesEquivalent(types, PA, elementA, elementB)) return false; } return true; } else return false; }
/// cmpType - compares two types, /// defines total ordering among the types set. /// See method declaration comments for more details. int FunctionComparator::cmpType(Type *TyL, Type *TyR) const { PointerType *PTyL = dyn_cast<PointerType>(TyL); PointerType *PTyR = dyn_cast<PointerType>(TyR); if (DL) { if (PTyL && PTyL->getAddressSpace() == 0) TyL = DL->getIntPtrType(TyL); if (PTyR && PTyR->getAddressSpace() == 0) TyR = DL->getIntPtrType(TyR); } if (TyL == TyR) return 0; if (int Res = cmpNumbers(TyL->getTypeID(), TyR->getTypeID())) return Res; switch (TyL->getTypeID()) { default: llvm_unreachable("Unknown type!"); // Fall through in Release mode. case Type::IntegerTyID: case Type::VectorTyID: // TyL == TyR would have returned true earlier. return cmpNumbers((uint64_t)TyL, (uint64_t)TyR); case Type::VoidTyID: case Type::FloatTyID: case Type::DoubleTyID: case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: case Type::LabelTyID: case Type::MetadataTyID: return 0; case Type::PointerTyID: { assert(PTyL && PTyR && "Both types must be pointers here."); return cmpNumbers(PTyL->getAddressSpace(), PTyR->getAddressSpace()); } case Type::StructTyID: { StructType *STyL = cast<StructType>(TyL); StructType *STyR = cast<StructType>(TyR); if (STyL->getNumElements() != STyR->getNumElements()) return cmpNumbers(STyL->getNumElements(), STyR->getNumElements()); if (STyL->isPacked() != STyR->isPacked()) return cmpNumbers(STyL->isPacked(), STyR->isPacked()); for (unsigned i = 0, e = STyL->getNumElements(); i != e; ++i) { if (int Res = cmpType(STyL->getElementType(i), STyR->getElementType(i))) return Res; } return 0; } case Type::FunctionTyID: { FunctionType *FTyL = cast<FunctionType>(TyL); FunctionType *FTyR = cast<FunctionType>(TyR); if (FTyL->getNumParams() != FTyR->getNumParams()) return cmpNumbers(FTyL->getNumParams(), FTyR->getNumParams()); if (FTyL->isVarArg() != FTyR->isVarArg()) return cmpNumbers(FTyL->isVarArg(), FTyR->isVarArg()); if (int Res = cmpType(FTyL->getReturnType(), FTyR->getReturnType())) return Res; for (unsigned i = 0, e = FTyL->getNumParams(); i != e; ++i) { if (int Res = cmpType(FTyL->getParamType(i), FTyR->getParamType(i))) return Res; } return 0; } case Type::ArrayTyID: { ArrayType *ATyL = cast<ArrayType>(TyL); ArrayType *ATyR = cast<ArrayType>(TyR); if (ATyL->getNumElements() != ATyR->getNumElements()) return cmpNumbers(ATyL->getNumElements(), ATyR->getNumElements()); return cmpType(ATyL->getElementType(), ATyR->getElementType()); } } }