gollvm: update to LLVM mainline Patch switches to mainline LLVM which implies following changes in gollvm: - Use of new pass manager - Use of opaque pointers and implementing type tracking based on Btype instead of llvm::Type - Use of debug records instead of intrinsics - Fix gollvm unit tests Change-Id: I3b8e3fe4820158a06fd1754ba2e1e0515d65ecca Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/642655 Reviewed-by: Carlos Amedee <carlos@golang.org> Reviewed-by: Than McIntosh <thanm@golang.org> Reviewed-by: Anton Korobeynikov <anton@korobeynikov.info> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2561f8b..f5b8baa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -114,6 +114,16 @@ set(gocdep llvm-goc-token) endif() +if(CXX_SUPPORTS_SUGGEST_OVERRIDE_FLAG) + add_definitions("-Wno-suggest-override") + set_target_properties(gollvm PROPERTIES INTERFACE_COMPILE_OPTIONS "-Wno-suggest-override") +endif() + +if(CXX_SUPPORTS_COVERED_SWITCH_DEFAULT_FLAG) + add_definitions("-Wno-covered-switch-default") + set_target_properties(gollvm PROPERTIES INTERFACE_COMPILE_OPTIONS "-Wno-covered-switch-default") +endif() + # Root of gollvm source code. set(GOLLVM_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/bridge/go-llvm-bexpression.cpp b/bridge/go-llvm-bexpression.cpp index 1b97168..1b0ff3a 100644 --- a/bridge/go-llvm-bexpression.cpp +++ b/bridge/go-llvm-bexpression.cpp
@@ -118,12 +118,6 @@ if (!llvm::isa<llvm::Constant>(value_)) return false; - // Not a constant if there is a pending load - if (value_->getType()->isPointerTy() && - value_->getType()->getPointerElementType() == - btype()->type()) - return false; - // In some cases, even the underlying value is an // llvm::Constant, the expression may be not. For // example, a var expression for a global variable,
diff --git a/bridge/go-llvm-bexpression.h b/bridge/go-llvm-bexpression.h index 767ac47..9f4be88 100644 --- a/bridge/go-llvm-bexpression.h +++ b/bridge/go-llvm-bexpression.h
@@ -83,10 +83,6 @@ VarContext() : addrLevel_(0), lvalue_(false), pending_(false) { } VarContext(bool lvalue, unsigned addrLevel) : addrLevel_(addrLevel), lvalue_(lvalue), pending_(true) { } - explicit VarContext(const VarContext &src) - : addrLevel_(src.addrLevel_), lvalue_(src.lvalue_), - pending_(src.pending_) - { } bool pending() const { return pending_; } unsigned addrLevel() const { return addrLevel_; }
diff --git a/bridge/go-llvm-bfunction.cpp b/bridge/go-llvm-bfunction.cpp index 20aed84..e4b741f 100644 --- a/bridge/go-llvm-bfunction.cpp +++ b/bridge/go-llvm-bfunction.cpp
@@ -74,10 +74,9 @@ return abiOracle_->tm()->tnamegen(tag); } -llvm::Instruction *Bfunction::addAlloca(llvm::Type *typ, - const std::string &name) -{ +llvm::Instruction *Bfunction::addAlloca(Btype *bty, const std::string &name) { llvm::Instruction *insBefore = nullptr; + llvm::Type *typ = bty->type(); TypeManager *tm = abiOracle_->tm(); llvm::Align aaAlign = tm->datalayout()->getABITypeAlign(typ); llvm::Value *aaSize = nullptr; @@ -131,8 +130,7 @@ // Seems weird to create a zero-sized alloca(), but it should // simplify things in that we can avoid having a Bvariable with a // null value. - llvm::Type *llpt = paramTypes[idx]->type(); - llvm::Instruction *inst = addAlloca(llpt, ""); + llvm::Instruction *inst = addAlloca(paramTypes[idx], ""); paramValues_.push_back(inst); break; } @@ -148,8 +146,7 @@ break; } case ParmDirect: { - llvm::Type *llpt = paramTypes[idx]->type(); - llvm::Instruction *inst = addAlloca(llpt, ""); + llvm::Instruction *inst = addAlloca(paramTypes[idx], ""); paramValues_.push_back(inst); if (paramInfo.attr() == AttrSext) arguments_[argIdx]->addAttr(llvm::Attribute::SExt); @@ -229,7 +226,7 @@ // Create the spill slot for the param. std::string spname(name); spname += ".addr"; - llvm::Instruction *inst = addAlloca(btype->type(), spname); + llvm::Instruction *inst = addAlloca(btype, spname); assert(chainVal_); assert(llvm::isa<llvm::Argument>(chainVal_)); chainVal_ = inst; @@ -260,7 +257,7 @@ // to share the same alloca instruction. inst = llvm::cast<llvm::Instruction>(declVar->value()); } else { - inst = addAlloca(btype->type(), name); + inst = addAlloca(btype, name); } if (is_address_taken) { llvm::Instruction *alloca = inst; @@ -285,12 +282,7 @@ llvm::Value *Bfunction::createTemporary(Btype *btype, const std::string &tag) { - return createTemporary(btype->type(), tag); -} - -llvm::Value *Bfunction::createTemporary(llvm::Type *typ, const std::string &tag) -{ - return addAlloca(typ, tag); + return addAlloca(btype, tag); } // This implementation uses an alloca instruction as a placeholder @@ -378,13 +370,6 @@ llvm::Argument *arg = arguments_[paramInfo.sigOffset()]; assert(sploc->getType()->isPointerTy()); llvm::PointerType *llpt = llvm::cast<llvm::PointerType>(sploc->getType()); - if (paramInfo.abiType()->isVectorTy() || - arg->getType() != llpt->getElementType()) { - std::string tag(namegen("cast")); - llvm::Type *ptv = llvm::PointerType::get(paramInfo.abiType(), 0); - llvm::Value *bitcast = builder.CreateBitCast(sploc, ptv, tag); - sploc = bitcast; - } llvm::Instruction *si = builder.CreateStore(arg, sploc); paramVar->setInitializer(si); spillInstructions->appendInstructions(builder.instructions()); @@ -398,16 +383,13 @@ llvm::Type *llst = paramInfo.computeABIStructType(tm); llvm::Type *ptst = llvm::PointerType::get(llst, 0); - // Cast the spill location to a pointer to the struct created above. - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder.CreateBitCast(sploc, ptst, tag); llvm::Instruction *stinst = nullptr; // Generate a store to each field. for (unsigned i = 0; i < paramInfo.abiTypes().size(); ++i) { std::string tag(namegen("field" + std::to_string(i))); llvm::Value *fieldgep = - builder.CreateConstInBoundsGEP2_32(llst, bitcast, 0, i, tag); + builder.CreateConstInBoundsGEP2_32(llst, sploc, 0, i, tag); llvm::Value *argChunk = arguments_[paramInfo.sigOffset() + i]; stinst = builder.CreateStore(argChunk, fieldgep); } @@ -457,11 +439,11 @@ // Append allocas for local variables // FIXME: create lifetime annotations for (auto aa : allocas_) - entry->getInstList().push_back(aa); + aa->insertBefore(*entry, entry->end()); // Param spills for (auto sp : spills.instructions()) - entry->getInstList().push_back(sp); + sp->insertBefore(*entry, entry->end()); // Debug meta-data generation needs to know the position at which a // parameter variable is available for inspection -- this is @@ -496,11 +478,11 @@ // we insert any new temps into the start of the block. if (! temps.empty()) for (auto ai : temps) { - entry->getInstList().push_front(ai); + ai->insertInto(entry, entry->begin()); if (auto *ascast = llvm::dyn_cast<llvm::AddrSpaceCastInst>(ai)) { llvm::Value *op = ascast->getPointerOperand(); assert(llvm::isa<llvm::AllocaInst>(op)); - entry->getInstList().push_front(llvm::cast<llvm::Instruction>(op)); + llvm::cast<llvm::Instruction>(op)->insertInto(entry, entry->begin()); } } } @@ -547,10 +529,8 @@ returnInfo.abiType()); llvm::Type *ptst = llvm::PointerType::get(llrt, 0); BlockLIRBuilder builder(function(), inamegen); - std::string castname(namegen("cast")); - llvm::Value *bitcast = builder.CreateBitCast(toRet->value(), ptst, castname); std::string loadname(namegen("ld")); - llvm::Instruction *ldinst = builder.CreateLoad(llrt, bitcast, loadname); + llvm::Instruction *ldinst = builder.CreateLoad(llrt, toRet->value(), loadname); retInstrs->appendInstructions(builder.instructions()); return ldinst; }
diff --git a/bridge/go-llvm-bfunction.h b/bridge/go-llvm-bfunction.h index f83aafa..e51cb91 100644 --- a/bridge/go-llvm-bfunction.h +++ b/bridge/go-llvm-bfunction.h
@@ -124,7 +124,6 @@ // Return an alloca temporary of the specified type. llvm::Value *createTemporary(Btype *btype, const std::string &tag); - llvm::Value *createTemporary(llvm::Type *type, const std::string &tag); // If the function return value is passing via memory instead of // directly, this function returns the location into which the @@ -155,7 +154,7 @@ // Create an alloca with the specified type. The alloca is recorded // in a list so that it can be picked up during prolog generation. - llvm::Instruction *addAlloca(llvm::Type *vtyp, const std::string &name); + llvm::Instruction *addAlloca(Btype *typ, const std::string &name); // Given an LLVM value, return the Bvariable we created to wrap it (either // local var or parameter var).
diff --git a/bridge/go-llvm-builtins.cpp b/bridge/go-llvm-builtins.cpp index 8e7224a..606d02d 100644 --- a/bridge/go-llvm-builtins.cpp +++ b/bridge/go-llvm-builtins.cpp
@@ -535,14 +535,13 @@ return builder->CreateOr(old, args[1]); } -static llvm::Value *atomicCasMaker(llvm::SmallVectorImpl<llvm::Value*> &args, - BlockLIRBuilder *builder, - Llvm_backend *be) -{ +static llvm::Value *atomicCasMaker(llvm::SmallVectorImpl<llvm::Value *> &args, + BlockLIRBuilder *builder, Llvm_backend *be, + llvm::Type *elemTy) { assert(args.size() == 6); // GCC __atomic_compare_exchange_n takes a pointer to the old value. // We need to load it. - llvm::Value *old = builder->CreateLoad(args[1]->getType()->getPointerElementType(), args[1]); + llvm::Value *old = builder->CreateLoad(elemTy, args[1]); // FIXME: see atomicLoadMaker, but default to SequentiallyConsistent // for success order, Monotonic (i.e. relaxed) for failed order, // and false for weak. @@ -566,6 +565,18 @@ return builder->CreateZExt(ret, be->llvmInt8Type()); } +static llvm::Value *atomicCasMaker4(llvm::SmallVectorImpl<llvm::Value *> &args, + BlockLIRBuilder *builder, + Llvm_backend *be) { + return atomicCasMaker(args, builder, be, be->llvmInt32Type()); +} + +static llvm::Value *atomicCasMaker8(llvm::SmallVectorImpl<llvm::Value *> &args, + BlockLIRBuilder *builder, + Llvm_backend *be) { + return atomicCasMaker(args, builder, be, be->llvmInt64Type()); +} + void BuiltinTable::defineExprBuiltins() { Btype *boolType = tman_->boolType(); @@ -655,13 +666,13 @@ { BuiltinEntryTypeVec typeVec = {boolType, uint32PtrType, uint32PtrType, uint32Type, boolType, int32Type, int32Type}; - registerExprBuiltin("__atomic_compare_exchange_4", nullptr, - typeVec, atomicCasMaker); + registerExprBuiltin("__atomic_compare_exchange_4", nullptr, typeVec, + atomicCasMaker4); } { BuiltinEntryTypeVec typeVec = {boolType, uint64PtrType, uint64PtrType, uint64Type, boolType, int32Type, int32Type}; - registerExprBuiltin("__atomic_compare_exchange_8", nullptr, - typeVec, atomicCasMaker); + registerExprBuiltin("__atomic_compare_exchange_8", nullptr, typeVec, + atomicCasMaker8); } }
diff --git a/bridge/go-llvm-dibuildhelper.cpp b/bridge/go-llvm-dibuildhelper.cpp index 777b8d9..de94946 100644 --- a/bridge/go-llvm-dibuildhelper.cpp +++ b/bridge/go-llvm-dibuildhelper.cpp
@@ -156,13 +156,7 @@ if(var->initializer() && !var->initializerInstruction()->getParent()) return; - // Create the declare instruction, giving it an initial position at - // the end of the entry block (the insertDeclare call below doesn't - // allow a NULL insert location, so we pick end-of-block arbitrarily). assert(entryBlock_); - llvm::Instruction *decl = - dibuilder().insertDeclare(var->value(), dilv, expr, vloc, entryBlock_); - decl->removeFromParent(); // Extract the decl from the end of the entry block and reposition // it according to the var properties. @@ -173,7 +167,11 @@ } else if (var->flavor() == ParamVar) { // parameters passing by reference may have no initializers. // declare them at function entry. - entryBlock_->getInstList().push_front(decl); + if (!entryBlock_->empty()) + dibuilder().insertDeclare(var->value(), dilv, expr, vloc, + &entryBlock_->front()); + else + dibuilder().insertDeclare(var->value(), dilv, expr, vloc, entryBlock_); return; } else { // locals with no initializer should only be zero-sized vars. @@ -185,7 +183,12 @@ assert(! llvm::isa<llvm::BranchInst>(insertionPoint)); assert(insertionPoint != insertionPoint->getParent()->getTerminator()); - decl->insertAfter(insertionPoint); + if (insertionPoint->getNextNode()) + dibuilder().insertDeclare(var->value(), dilv, expr, vloc, + insertionPoint->getNextNode()); + else + dibuilder().insertDeclare(var->value(), dilv, expr, vloc, + insertionPoint->getParent()); } void DIBuildHelper::endFunction(Bfunction *function) @@ -310,7 +313,7 @@ std::string DIBuildHelper::applyDebugPrefix(llvm::StringRef path) { for (const auto &remap : debugPrefixMap_) - if (path.startswith(remap.first)) + if (path.starts_with(remap.first)) return (llvm::Twine(remap.second) + path.substr(remap.first.size())).str(); return path.str();
diff --git a/bridge/go-llvm-irbuilders.cpp b/bridge/go-llvm-irbuilders.cpp index de007b1..d883cec 100644 --- a/bridge/go-llvm-irbuilders.cpp +++ b/bridge/go-llvm-irbuilders.cpp
@@ -25,14 +25,14 @@ BlockLIRBuilder::~BlockLIRBuilder() { - assert(dummyBlock_->getInstList().empty()); + assert(dummyBlock_->empty()); dummyBlock_->removeFromParent(); } std::vector<llvm::Instruction*> BlockLIRBuilder::instructions() { std::vector<llvm::Instruction*> rv; - for (auto &i : dummyBlock_->getInstList()) + for (auto &i : *dummyBlock_) rv.push_back(&i); for (auto &i : rv) { i->removeFromParent();
diff --git a/bridge/go-llvm-irbuilders.h b/bridge/go-llvm-irbuilders.h index 537eb1d..d54f1b6 100644 --- a/bridge/go-llvm-irbuilders.h +++ b/bridge/go-llvm-irbuilders.h
@@ -31,8 +31,7 @@ void setDest(Bexpression *expr) { assert(!expr_); expr_ = expr; } void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, - llvm::BasicBlock *BB, - llvm::BasicBlock::iterator InsertPt) const { + llvm::BasicBlock::iterator InsertPt) const override { assert(expr_); expr_->appendInstruction(I); I->setName(Name);
diff --git a/bridge/go-llvm-materialize.cpp b/bridge/go-llvm-materialize.cpp index 8e89288..3d2bc1a 100644 --- a/bridge/go-llvm-materialize.cpp +++ b/bridge/go-llvm-materialize.cpp
@@ -121,8 +121,7 @@ assert(valtyp->isPointerTy()); if (valtyp->getPointerAddressSpace() != addressSpace_) { llvm::Type *typ = - llvm::PointerType::get(valtyp->getPointerElementType(), - addressSpace_); + llvm::PointerType::get(valtyp->getContext(), addressSpace_); val = new llvm::AddrSpaceCastInst(val, typ, "ascast"); } @@ -176,9 +175,8 @@ } if (lvalue || useCopyForLoadStore(type->type())) { llvm::Type *et = expr->btype()->type(); - if (valType->isPointerTy() && - valType->getPointerElementType() == et) - toType = llvm::PointerType::get(toType, addressSpace_); + if (valType->isPointerTy()) + toType = llvm::PointerType::get(toType->getContext(), addressSpace_); } } @@ -230,8 +228,7 @@ if (val->getType()->getPointerAddressSpace() != 0) { // We are using non-integral pointer. Cast to address space 0 // before casting to int. - llvm::Type *et = val->getType()->getPointerElementType(); - llvm::Type *pt = llvm::PointerType::get(et, 0); + llvm::Type *pt = llvm::PointerType::get(val->getContext(), 0); std::string tname(namegen("ascast")); val = builder.CreateAddrSpaceCast(val, pt, tname); expr = nbuilder_.mkConversion(type, val, expr, location); @@ -248,8 +245,7 @@ if (toType->getPointerAddressSpace() != 0) { // We are using non-integral pointer. Cast to address space 0 // first. - llvm::Type *et = toType->getPointerElementType(); - pt = llvm::PointerType::get(et, 0); + pt = llvm::PointerType::get(toType->getContext(), 0); } std::string tname(namegen("itpcast")); llvm::Value *itpcast = builder.CreateIntToPtr(val, pt, tname); @@ -342,14 +338,13 @@ return rval; } -llvm::Value *Llvm_backend::makePointerOffsetGEP(llvm::PointerType *llpt, - llvm::Value *idxval, - llvm::Value *sptr) -{ +llvm::Value *Llvm_backend::makePointerOffsetGEP(Btype *pt, llvm::Value *idxval, + llvm::Value *sptr) { LIRBuilder builder(context_, llvm::ConstantFolder()); llvm::SmallVector<llvm::Value *, 1> elems(1); elems[0] = idxval; - llvm::Value *val = builder.CreateGEP(llpt->getElementType(), sptr, elems, namegen("ptroff")); + llvm::Type *eltTy = pt->castToBPointerType()->toType()->type(); + llvm::Value *val = builder.CreateGEP(eltTy, sptr, elems, namegen("ptroff")); return val; } @@ -365,12 +360,10 @@ return val; } -llvm::Value *Llvm_backend::makeFieldGEP(unsigned fieldIndex, - llvm::Value *sptr) -{ +llvm::Value *Llvm_backend::makeFieldGEP(unsigned fieldIndex, llvm::Type *sty, + llvm::Value *sptr) { assert(sptr->getType()->isPointerTy()); - llvm::PointerType *srcTyp = llvm::cast<llvm::PointerType>(sptr->getType()); - llvm::StructType *llst = llvm::cast<llvm::StructType>(srcTyp->getElementType()); + llvm::StructType *llst = llvm::cast<llvm::StructType>(sty); LIRBuilder builder(context_, llvm::ConstantFolder()); assert(fieldIndex < llst->getNumElements()); std::string tag(namegen("field")); @@ -401,7 +394,7 @@ if (bstruct->isConstant()) fval = llvm::cast<llvm::Constant>(sval)->getAggregateElement(index); else - fval = makeFieldGEP(index, sval); + fval = makeFieldGEP(index, llt, sval); Btype *bft = elementTypeByIndex(bstruct->btype(), index); // Wrap result in a Bexpression @@ -632,29 +625,9 @@ if (leftType == rightType) return rval; - // Case 1: nil op X - if (llvm::isa<llvm::ConstantPointerNull>(leftVal) && - rightType->isPointerTy()) { - BexprLIRBuilder builder(context_, left); - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder.CreateBitCast(leftVal, rightType, tag); - rval.first = bitcast; - return rval; - } - - // Case 2: X op nil - if (llvm::isa<llvm::ConstantPointerNull>(rightVal) && - leftType->isPointerTy()) { - BexprLIRBuilder builder(context_, right); - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder.CreateBitCast(rightVal, leftType, tag); - rval.second = bitcast; - return rval; - } - // Case 3: shift with different sized operands (ex: int64(v) << uint8(3)). // Promote or demote shift amount operand to match width of left operand. - if ((op == OPERATOR_LSHIFT || op == OPERATOR_RSHIFT) && + if ((op == OPERATOR_LSHIFT || op == OPERATOR_RSHIFT || op == OPERATOR_EQEQ) && leftType != rightType) { BexprLIRBuilder builder(context_, right); llvm::IntegerType *leftITyp = llvm::cast<llvm::IntegerType>(leftType); @@ -668,24 +641,6 @@ return rval; } - // Case 4: pointer type comparison - // We check that if both are pointer types and pointing to the same type, - // insert a cast (it doesn't matter we cast which one). This mostly needed - // for circular pointer types (ex: type T *T; var p, q T; p == &q), where - // the two sides have semantically identical types but with different - // representations (in this case, T vs. *T). - if (leftType->isPointerTy() && rightType->isPointerTy()) { - BPointerType *lbpt = left->btype()->castToBPointerType(); - BPointerType *rbpt = right->btype()->castToBPointerType(); - if (lbpt->toType()->type() == rbpt->toType()->type()) { - BexprLIRBuilder builder(context_, right); - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder.CreateBitCast(rightVal, leftType, tag); - rval.second = bitcast; - return rval; - } - } - return rval; } @@ -1024,10 +979,8 @@ base = resolveVarContext(base); // Construct an appropriate GEP - llvm::PointerType *llpt = - llvm::cast<llvm::PointerType>(base->btype()->type()); llvm::Value *gep = - makePointerOffsetGEP(llpt, index->value(), base->value()); + makePointerOffsetGEP(base->btype(), index->value(), base->value()); // Wrap in a Bexpression Bexpression *rval = nbuilder_.mkPointerOffset(base->btype(), gep, base, @@ -1192,7 +1145,7 @@ if (paramInfo.attr() == AttrByVal && vt->getPointerAddressSpace() != 0) { // We pass a stack address, which is always in address space 0. std::string castname(namegen("ascast")); - llvm::Type *pt = llvm::PointerType::get(vt->getPointerElementType(), 0); + llvm::Type *pt = llvm::PointerType::get(vt->getContext(), 0); val = builder.CreateAddrSpaceCast(val, pt, castname); } @@ -1240,29 +1193,13 @@ Bvariable *cv = genVarForConstant(cval, resarg->btype()); val = cv->value(); } - std::string castname(namegen("cast")); - // We are going to do a load, so the address space does not matter. - // It seems we may get here with either address space, so we just - // do an address-space-preserving cast. - llvm::Type *ptv = - llvm::PointerType::get(paramInfo.abiType(), - val->getType()->getPointerAddressSpace()); - llvm::Value *bitcast = builder.CreateBitCast(val, ptv, castname); std::string ltag(namegen("ld")); - llvm::Value *ld = builder.CreateLoad(paramInfo.abiType(), bitcast, ltag); + llvm::Value *ld = builder.CreateLoad(paramInfo.abiType(), val, ltag); state.llargs.push_back(ld); continue; } // Passing a single 8-byte-or-less argument. - // Apply any necessary pointer type conversions. - if (val->getType()->isPointerTy() && ctx == VE_rvalue) { - llvm::FunctionType *llft = - llvm::cast<llvm::FunctionType>(state.calleeFcnType->type()); - llvm::Type *paramTyp = llft->getParamType(paramInfo.sigOffset()); - val = convertForAssignment(resarg, paramTyp); - } - // Apply any necessary sign-extensions or zero-extensions. if (paramInfo.abiType()->isIntegerTy()) { if (paramInfo.attr() == AttrZext) @@ -1283,7 +1220,6 @@ // Create a struct type of the appropriate shape llvm::Type *llst = paramInfo.computeABIStructType(typeManager()); - llvm::Type *ptst = makeLLVMPointerType(llst); // If the value we're passing is a composite constant, we have to // spill it to memory here in order for the casts below to work. @@ -1299,16 +1235,11 @@ val = cv->value(); } - // Cast the value to the struct type - std::string tag(namegen("cast")); - llvm::Value *bitcast = - builder.CreatePointerBitCastOrAddrSpaceCast(val, ptst, tag); - // Load up each field for ( unsigned i = 0; i < paramInfo.abiTypes().size(); ++i) { std::string ftag(namegen("field"+std::to_string(i))); llvm::Value *fieldgep = - builder.CreateConstInBoundsGEP2_32(llst, bitcast, 0, i, ftag); + builder.CreateConstInBoundsGEP2_32(llst, val, 0, i, ftag); std::string ltag(namegen("ld")); llvm::Value *ld = builder.CreateLoad(paramInfo.abiTypes()[i], fieldgep, ltag); state.llargs.push_back(ld); @@ -1389,13 +1320,8 @@ llvm::Type *rt = (returnInfo.abiTypes().size() == 1 ? returnInfo.abiType() : returnInfo.computeABIStructType(typeManager())); - llvm::Type *ptrt = llvm::PointerType::get(rt, 0); - std::string castname(namegen("cast")); - llvm::Value *bitcast = - state.builder.CreateBitCast(state.sretTemp, - ptrt, castname); std::string stname(namegen("st")); - state.builder.CreateStore(callInst, bitcast); + state.builder.CreateStore(callInst, state.sretTemp); callExpr->appendInstructions(state.builder.instructions()); } } @@ -1605,152 +1531,6 @@ return rval; } -llvm::Value * -Llvm_backend::convertForAssignment(Bexpression *src, - llvm::Type *dstToType) -{ - if (src->value()->getType() == dstToType) - return src->value(); - - llvm::Function *dummyFcn = errorFunction_->function(); - BlockLIRBuilder builder(dummyFcn, this); - llvm::Value *val = convertForAssignment(src->btype(), src->value(), - dstToType, &builder); - src->appendInstructions(builder.instructions()); - return val; -} - -llvm::Value * -Llvm_backend::convertForAssignment(Btype *srcBType, - llvm::Value *srcVal, - llvm::Type *dstToType, - BlockLIRBuilder *builder) -{ - llvm::Type *srcType = srcVal->getType(); - - if (dstToType == srcType) - return srcVal; - - // Case 1: handle discrepancies between representations of function - // descriptors. All front end function descriptor types are structs - // with a single field, however this field can sometimes be a pointer - // to function, and sometimes it can be of uintptr type. - bool srcPtrToFD = isPtrToFuncDescriptorType(srcType); - bool dstPtrToFD = isPtrToFuncDescriptorType(dstToType); - if (srcPtrToFD && dstPtrToFD) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder->CreateBitCast(srcVal, dstToType, tag); - return bitcast; - } - - // Case 2: handle circular function types. - bool dstCircFunc = isCircularFunctionType(dstToType); - bool srcCircFunc = isCircularFunctionType(srcType); - bool srcFuncPtr = isPtrToFuncType(srcType); - if (((srcPtrToFD || srcFuncPtr || srcCircFunc) && dstCircFunc) || - (srcCircFunc && dstPtrToFD)) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder->CreateBitCast(srcVal, dstToType, tag); - return bitcast; - } - - // Case 3: handle raw function pointer assignment (frontend will - // sometimes take a function pointer and assign it to "void *" without - // an explicit conversion). - bool dstPtrToVoid = isPtrToVoidType(dstToType); - if (dstPtrToVoid && srcFuncPtr) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder->CreateBitCast(srcVal, dstToType, tag); - return bitcast; - } - - // Case 4: in some cases when calling a function (for example, __gogo) - // the front end will pass a raw function vale in place of a function - // descriptor. Allow this case. - if (dstPtrToFD && srcFuncPtr) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = - builder->CreatePointerBitCastOrAddrSpaceCast(srcVal, dstToType, tag); - return bitcast; - } - - // Case 5: handle polymorphic nil pointer expressions-- these are - // generated without a type initially, so we need to convert them - // to the appropriate type if they appear in an assignment context. - if (srcVal == nil_pointer_expression()->value()) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder->CreateBitCast(srcVal, dstToType, tag); - return bitcast; - } - - // Case 6: the code that creates interface values stores pointers of - // various flavors into i8*. Ideally it would be better to insert - // forced type conversions in the FE, but for now we allow this case. - bool srcPtrToIface = isPtrToIfaceStructType(srcType); - if (dstPtrToVoid && srcPtrToIface) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder->CreateBitCast(srcVal, dstToType, tag); - return bitcast; - } - - // Case 7: when creating slice values it's common for the frontend - // to mix pointers and arrays, e.g. assign "[3 x i64]*" to "i64**". - // Allow this sort of conversion. - llvm::Type *elt = - (dstToType->isPointerTy() ? - llvm::cast<llvm::PointerType>(dstToType)->getElementType() : nullptr); - if (elt && isPtrToArrayOf(srcType, elt)) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder->CreateBitCast(srcVal, dstToType, tag); - return bitcast; - } - - // Case 8: also when creating slice values it's common for the - // frontend to assign pointer-to-X to unsafe.Pointer (and vice versa) - // without an explicit cast. Allow this for now. - if ((dstToType == llvmPtrType() && llvm::isa<llvm::PointerType>(srcType)) || - (srcType == llvmPtrType() && llvm::isa<llvm::PointerType>(dstToType))) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder->CreatePointerBitCastOrAddrSpaceCast(srcVal, dstToType, tag); - return bitcast; - } - - // Case 9: related to case 1 above, interface value expressions can - // contain C function pointers stored as "void *" instead of - // concrete pointer-to-function values. For example, consider a - // value V1 of the form - // - // { { T1*, void* }, O* } - // - // where T1 is a type descriptor and O is an object; this value can - // sometimes be assigned to a location of type - // - // { { T1*, F* }, O* } - // - // where F is a concrete C pointer-to-function (as opposed to "void*"). - // Allow conversions of this sort for now. - std::set<llvm::Type *> visited; - if (fcnPointerCompatible(dstToType, srcType, visited)) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = - builder->CreatePointerBitCastOrAddrSpaceCast(srcVal, dstToType, tag); - return bitcast; - } - - // Case 10: circular pointer type (ex: type T *T; var p T; p = &p) - BPointerType *srcbpt = srcBType->castToBPointerType(); - if (srcbpt) { - Btype *ctypconv = circularTypeAddrConversion(srcbpt->toType()); - if (ctypconv != nullptr && ctypconv->type() == dstToType) { - std::string tag(namegen("cast")); - llvm::Value *bitcast = builder->CreateBitCast(srcVal, dstToType, tag); - return bitcast; - } - } - - return srcVal; -} - // Walk the specified expression and invoke setVarExprPending on // each var expression, with correct lvalue/rvalue tag depending on // context.
diff --git a/bridge/go-llvm-typemanager.cpp b/bridge/go-llvm-typemanager.cpp index 4301233..d853e43 100644 --- a/bridge/go-llvm-typemanager.cpp +++ b/bridge/go-llvm-typemanager.cpp
@@ -1008,8 +1008,8 @@ // Circular function/pointer types have isPlaceholder false, but they do // need to resolve, so special-case them. if (!placeholder->isPlaceholder() && - circularPointerTypes_.find(placeholder->type()) == circularPointerTypes_.end() && - circularFunctionTypes_.find(placeholder->type()) == circularFunctionTypes_.end()) + circularPointerTypes_.find(placeholder) == circularPointerTypes_.end() && + circularFunctionTypes_.find(placeholder) == circularFunctionTypes_.end()) return true; assert(anonTypes_.find(placeholder) == anonTypes_.end()); @@ -1038,8 +1038,8 @@ } // Circular pointer type handling - circularConversionLoadMap_[cpt->type()] = elt; - circularConversionAddrMap_[elt->type()] = cpt; + circularConversionLoadMap_[cpt] = elt; + circularConversionAddrMap_[elt] = cpt; return setPlaceholderPointerType(placeholder, cpt); } @@ -1056,9 +1056,9 @@ std::cerr << "redir: "; to_type->dump(); } - auto it = circularFunctionTypes_.find(placeholder->type()); + auto it = circularFunctionTypes_.find(placeholder); if (it != circularFunctionTypes_.end()) - circularFunctionTypes_.insert(to_type->type()); + circularFunctionTypes_.insert(to_type); // Update the target type for the pointer BPointerType *bpt = placeholder->castToBPointerType(); @@ -1251,11 +1251,11 @@ // Push marker and placeholder onto a stack so that we can // update them when the appropriate function type is created. circularFunctionPlaceholderTypes_.insert(placeholder); - circularFunctionTypes_.insert(rval->type()); + circularFunctionTypes_.insert(rval); } else { // Set up to start tracking the types that will make up the // loop involved in the cycle. - circularPointerTypes_.insert(circ_typ); + circularPointerTypes_.insert(rval); } if (traceLevel() > 1) { @@ -1278,35 +1278,25 @@ auto it = circularFunctionPlaceholderTypes_.find(btype); if (it != circularFunctionPlaceholderTypes_.end()) return true; - return isCircularFunctionType(btype->type()); -} - -bool TypeManager::isCircularFunctionType(llvm::Type *typ) { - assert(typ); - auto it = circularFunctionTypes_.find(typ); - return it != circularFunctionTypes_.end(); + auto it2 = circularFunctionTypes_.find(btype); + return it2 != circularFunctionTypes_.end(); } // Return whether we might be looking at a circular pointer type. -bool TypeManager::isCircularPointerType(Btype *btype) { - assert(btype); - return isCircularPointerType(btype->type()); -} - -bool TypeManager::isCircularPointerType(llvm::Type *typ) { +bool TypeManager::isCircularPointerType(Btype *typ) { assert(typ); auto it = circularPointerTypes_.find(typ); return it != circularPointerTypes_.end(); } Btype *TypeManager::circularTypeLoadConversion(Btype *typ) { - auto it = circularConversionLoadMap_.find(typ->type()); + auto it = circularConversionLoadMap_.find(typ); return it != circularConversionLoadMap_.end() ? it->second : nullptr; } Btype *TypeManager::circularTypeAddrConversion(Btype *typ) { - auto it = circularConversionAddrMap_.find(typ->type()); + auto it = circularConversionAddrMap_.find(typ); if (it != circularConversionAddrMap_.end()) return it->second; return nullptr; @@ -1506,7 +1496,7 @@ if (btype == errorType_) return 1; llvm::Type *toget = getPlaceholderProxyIfNeeded(btype); - unsigned uval = datalayout_->getABITypeAlignment(toget); + unsigned uval = datalayout_->getABITypeAlign(toget).value(); return static_cast<int64_t>(uval); } @@ -1538,7 +1528,7 @@ llvm::StructType *dummyst = llvm::StructType::get(context_, elems); const llvm::StructLayout *sl = datalayout_->getStructLayout(dummyst); uint64_t uoff = sl->getElementOffset(1); - unsigned talign = datalayout_->getABITypeAlignment(toget); + unsigned talign = datalayout_->getABITypeAlign(toget).value(); int64_t rval = (uoff < talign ? uoff : talign); return rval; } @@ -1564,134 +1554,6 @@ return static_cast<int64_t>(uoff); } -bool TypeManager::isPtrToIfaceStructType(llvm::Type *typ) -{ - if (! typ->isPointerTy()) - return false; - llvm::PointerType *pt = llvm::cast<llvm::PointerType>(typ); - llvm::Type *elt = pt->getElementType(); - if (! elt->isStructTy()) - return false; - llvm::StructType *st = llvm::cast<llvm::StructType>(elt); - if (st->getNumElements() != 2) - return false; - llvm::SmallPtrSet<llvm::Type *, 32> vis; - // expect { ptr, ptr } or { ptr, uintptr } - return (st->getElementType(0)->isPointerTy() && - (st->getElementType(1)->isPointerTy() || - st->getElementType(1) == llvmIntegerType())); -} - -bool TypeManager::isFuncDescriptorType(llvm::Type *typ) -{ - if (! typ->isStructTy()) - return false; - llvm::StructType *st = llvm::cast<llvm::StructType>(typ); - if (st->getNumElements() != 1) - return false; - llvm::Type *f0t = st->getElementType(0); - llvm::PointerType *f0tpt = nullptr; - if (f0t->isPointerTy()) - f0tpt = llvm::cast<llvm::PointerType>(f0t); - if (f0t != llvmIntegerType_ && - !f0t->isFunctionTy() && - !(f0tpt && f0tpt->getElementType()->isFunctionTy())) - return false; - return true; -} - -bool TypeManager::isPtrToFuncDescriptorType(llvm::Type *typ) -{ - if (! typ->isPointerTy()) - return false; - llvm::PointerType *pt = llvm::cast<llvm::PointerType>(typ); - return isFuncDescriptorType(pt->getElementType()); -} - -bool TypeManager::isPtrToFuncType(llvm::Type *typ) -{ - if (! typ->isPointerTy()) - return false; - llvm::PointerType *pt = llvm::cast<llvm::PointerType>(typ); - return pt->getElementType()->isFunctionTy(); -} - -bool TypeManager::isPtrToVoidType(llvm::Type *typ) -{ - if (! typ->isPointerTy()) - return false; - llvm::PointerType *pt = llvm::cast<llvm::PointerType>(typ); - return pt->getElementType() == llvmInt8Type_; -} - -bool TypeManager::isPtrToArrayOf(llvm::Type *typ, llvm::Type *arElmTyp) -{ - if (! typ->isPointerTy()) - return false; - llvm::PointerType *pt = llvm::cast<llvm::PointerType>(typ); - llvm::Type *elt = pt->getElementType(); - if (! elt->isArrayTy()) - return false; - llvm::ArrayType *llat = llvm::cast<llvm::ArrayType>(elt); - llvm::Type *aelt = llat->getElementType(); - if (aelt == arElmTyp) - return true; - if (isCircularFunctionType(aelt) && isCircularFunctionType(arElmTyp)) - return true; // TODO: check they are same circular function type? - return false; -} - -bool TypeManager::fcnPointerCompatible(llvm::Type *left, - llvm::Type *right, - std::set<llvm::Type *> &visited) -{ - // Allow for pointer-to-fp and func-desc matching - bool leftFPD = isPtrToFuncType(left) || isPtrToVoidType(left); - bool rightFPD = isPtrToFuncType(right) || isPtrToVoidType(right); - if (leftFPD && rightFPD) - return true; - - bool visleft = (visited.find(left) != visited.end()); - bool visright = (visited.find(right) != visited.end()); - if (visleft != visright) - return false; - if (visleft) - return true; - visited.insert(left); - visited.insert(right); - - // Compare type ID, children, etc. - if (left->getTypeID() != right->getTypeID()) - return false; - - // For pointer types, visit pointed-to elements - if (left->isPointerTy()) { - llvm::PointerType *ptl = llvm::cast<llvm::PointerType>(left); - llvm::PointerType *ptr = llvm::cast<llvm::PointerType>(right); - llvm::Type *eltl = ptl->getElementType(); - llvm::Type *eltr = ptr->getElementType(); - return fcnPointerCompatible(eltl, eltr, visited); - } - - // For aggregate types, compare children. - if (left->isAggregateType()) { - unsigned leftnct = left->getNumContainedTypes(); - unsigned rightnct = right->getNumContainedTypes(); - if (leftnct != rightnct) - return false; - for (unsigned cti = 0; cti < leftnct; cti++) { - llvm::Type *leftchild = left->getContainedType(cti); - llvm::Type *rightchild = right->getContainedType(cti); - if (!fcnPointerCompatible(leftchild, rightchild, visited)) - return false; - } - return true; - } else { - // For non-aggregate types, we expect underlying llvm types to match - return (left == right); - } -} - std::string TypeManager::typToString(Btype *typ) { std::map<Btype *, std::string> smap; @@ -1750,7 +1612,7 @@ assert(!bpt->isPlaceholder()); // handle circular pointer types - auto cpit = circularPointerTypes_.find(typ->type()); + auto cpit = circularPointerTypes_.find(typ); if (cpit != circularPointerTypes_.end()) { std::string s; llvm::raw_string_ostream os(s); @@ -1848,7 +1710,7 @@ // Now create struct type itself. Q: should this be // getTypeAllocSize here instead of getTypeSizeInBits? uint64_t sizeInBits = datalayout_->getTypeSizeInBits(bst->type()); - uint32_t alignInBits = datalayout_->getABITypeAlignment(bst->type()); + uint32_t alignInBits = datalayout_->getABITypeAlign(bst->type()).value(); llvm::DIType *derivedFrom = nullptr; llvm::DICompositeType *dist = dibuilder.createStructType(scope, typToString(bst), @@ -1976,7 +1838,7 @@ uint64_t arElems = bat->nelSize(); uint64_t arSize = datalayout_->getTypeSizeInBits(bat->type()); uint64_t arAlign = - datalayout_->getABITypeAlignment(bat->elemType()->type()); + datalayout_->getABITypeAlign(bat->elemType()->type()).value(); llvm::SmallVector<llvm::Metadata *, 1> subscripts; subscripts.push_back(dibuilder.getOrCreateSubrange(0, arElems)); llvm::DINodeArray subsAr = dibuilder.getOrCreateArray(subscripts);
diff --git a/bridge/go-llvm-typemanager.h b/bridge/go-llvm-typemanager.h index d77a3ab..4db9ccc 100644 --- a/bridge/go-llvm-typemanager.h +++ b/bridge/go-llvm-typemanager.h
@@ -74,9 +74,7 @@ Btype *namedType(const std::string &, Btype *, Location); Btype *circularPointerType(Btype *, bool); bool isCircularPointerType(Btype *); - bool isCircularPointerType(llvm::Type *); bool isCircularFunctionType(Btype *); - bool isCircularFunctionType(llvm::Type *); int64_t typeSize(Btype *); int64_t typeAlignment(Btype *); int64_t typeFieldAlignment(Btype *); @@ -205,24 +203,6 @@ // found. bool addPlaceholderRefs(Btype *type); - // Helpers - bool isFuncDescriptorType(llvm::Type *typ); - bool isPtrToFuncDescriptorType(llvm::Type *typ); - bool isPtrToIfaceStructType(llvm::Type *typ); - bool isPtrToFuncType(llvm::Type *typ); - bool isPtrToVoidType(llvm::Type *typ); - bool isPtrToArrayOf(llvm::Type *ptyp, llvm::Type *arrayElmTyp); - - // This helper looks at two LLVM types and does a structural - // comparison to determine if 'left' is equivalent to 'right' modulo - // discrepancies between raw function pointers and "void *" (or - // equivalent). This is to allow for cases where the front end will - // store a function pointer in a table or struct somewhere as "void - // *" instead of the precise function type. - bool fcnPointerCompatible(llvm::Type *left, - llvm::Type *right, - std::set<llvm::Type *> &visited); - // If specified type is a pointer flagged as being a circular // type, return conversion needed on load from that type, or NULL // if the type is not circular. @@ -337,15 +317,15 @@ // Set of circular pointer types. These are pointers to opaque types that // are returned by the ::circular_pointer_type() method. - std::unordered_set<llvm::Type *> circularPointerTypes_; + std::unordered_set<Btype *> circularPointerTypes_; // Map from placeholder type to circular pointer type. Key is placeholder // pointer type, value is circular pointer type marker. std::unordered_map<Btype *, Btype *> circularPointerTypeMap_; // Maps for inserting conversions involving circular pointers. - std::unordered_map<llvm::Type *, Btype *> circularConversionLoadMap_; - std::unordered_map<llvm::Type *, Btype *> circularConversionAddrMap_; + std::unordered_map<Btype *, Btype *> circularConversionLoadMap_; + std::unordered_map<Btype *, Btype *> circularConversionAddrMap_; // Set of top-level circular function types. std::unordered_set<Btype *> circularFunctionPlaceholderTypes_; @@ -353,7 +333,7 @@ // This set holds the marker types returned for the self-referential // elements within a circular function type, also any resolved LLVM // function types created from placeholders. - std::unordered_set<llvm::Type *> circularFunctionTypes_; + std::unordered_set<Btype *> circularFunctionTypes_; // Name generation helper NameGen *nametags_;
diff --git a/bridge/go-llvm.cpp b/bridge/go-llvm.cpp index 8ee5a24..be0f0bc 100644 --- a/bridge/go-llvm.cpp +++ b/bridge/go-llvm.cpp
@@ -412,10 +412,7 @@ Bfunction *Llvm_backend::createIntrinsicFcn(const std::string &name, llvm::Function *fcn) { - llvm::PointerType *llpft = - llvm::cast<llvm::PointerType>(fcn->getType()); - llvm::FunctionType *llft = - llvm::cast<llvm::FunctionType>(llpft->getElementType()); + llvm::FunctionType *llft = fcn->getFunctionType(); BFunctionType *fcnType = makeAuxFcnType(llft); Location pdcl = linemap()->get_predeclared_location(); Bfunction *bfunc = new Bfunction(fcn, fcnType, name, name, pdcl, @@ -567,18 +564,10 @@ llvm::Type *vt = val->getType(); assert(vt->isPointerTy()); llvm::Type *llToType = toType->type(); - if (expr->varExprPending()) { - llvm::Type *et = expr->btype()->type(); - if (vt->getPointerElementType() == et) - llToType = llvm::PointerType::get(llToType, vt->getPointerAddressSpace()); - } if (vt == llToType) return expr; - std::string tag(namegen("cast")); - LIRBuilder builder(context_, llvm::ConstantFolder()); - llvm::Value *bitcast = builder.CreatePointerBitCastOrAddrSpaceCast(val, llToType, tag); - return nbuilder_.mkConversion(toType, bitcast, expr, loc); + return nbuilder_.mkConversion(toType, val, expr, loc); } Bexpression *Llvm_backend::genLoad(Bexpression *expr, @@ -593,6 +582,7 @@ // pointer types. Bexpression *space = expr; Btype *loadResultType; + bool needs_extra_deref = false; if (btype) { loadResultType = btype; Btype *tctyp = circularTypeLoadConversion(expr->btype()); @@ -600,6 +590,21 @@ space = genCircularConversion(pointer_type(tctyp), expr, loc); loadResultType = tctyp; } + int flavor = expr->flavor(); + // In most cases loadResultType is the same as value llvm type, + // or they're both pointers. Still in some cases we need additional + // level of indirection. This happens when: + // 1. expr is used to access variable, structure field or is a compound + // expression. Those expression's llvm value is alloca or GEP, which + // is actually a pointer to a value, not value itself. + // 2. expr is dereference (N_Deref), which has not yet been fully handled + // by the bridge. In such case the load instruction has not yet been + // generated. + if (!loadResultType->type()->isPointerTy()) + needs_extra_deref = + ((flavor == N_Deref && expr->varExprPending()) || flavor == N_Var || + flavor == N_StructField || flavor == N_Compound); + } else { // Here we are resolving a pending var expression. The LLVM // value should already be pointer to the expression type. @@ -608,18 +613,10 @@ } llvm::Value *spaceVal = space->value(); - if (spaceVal == nil_pointer_expression()->value()) { - llvm::Function *dummyFcn = errorFunction_->function(); - BlockLIRBuilder builder(dummyFcn, this); - llvm::Type *spaceTyp = llvm::PointerType::get(loadResultType->type(), addressSpace_); - std::string tag(namegen("cast")); - spaceVal = builder.CreateBitCast(spaceVal, spaceTyp, tag); - space->appendInstructions(builder.instructions()); - } - - llvm::PointerType *llpt = - llvm::cast<llvm::PointerType>(spaceVal->getType()); - llvm::Type *llrt = llpt->getElementType(); + llvm::Type *llrt = loadResultType->type(); + if (needs_extra_deref) + llrt = llvm::PointerType::get( + llrt, expr->btype()->type()->getPointerAddressSpace()); // If this type meets our criteria (composite/aggregate whose // size is above a certain threshhold) then assume that the @@ -631,13 +628,11 @@ std::string ldname(tag); ldname += ".ld"; ldname = namegen(ldname); - llvm::Type *vt = spaceVal->getType()->getPointerElementType(); llvm::Instruction *insBefore = nullptr; - llvm::Align ldAlign = datalayout_->getABITypeAlign(vt); + llvm::Align ldAlign = datalayout_->getABITypeAlign(llrt); bool isVolatile = false; - llvm::Instruction *loadInst = new llvm::LoadInst(vt, spaceVal, ldname, - isVolatile, ldAlign, - insBefore); + llvm::Instruction *loadInst = new llvm::LoadInst( + llrt, spaceVal, ldname, isVolatile, ldAlign, insBefore); rval = nbuilder_.mkDeref(loadResultType, loadInst, space, loc); rval->appendInstruction(loadInst); } else { @@ -879,17 +874,6 @@ // Decide whether we want a simple store instruction or a memcpy. if (! useCopyForLoadStore(srcType)) { - if (srcVal->getType()->isPointerTy()) { - llvm::PointerType *dstpt = - llvm::cast<llvm::PointerType>(dstType); - srcVal = convertForAssignment(srcType, srcVal, - dstpt->getElementType(), builder); - } - - // At this point the types should agree - llvm::PointerType *dpt = llvm::cast<llvm::PointerType>(dstType); - assert(srcVal->getType() == dpt->getElementType()); - // Create and return store return builder->CreateStore(srcVal, dstLoc); } @@ -1101,21 +1085,6 @@ // Normal case llvm::Value *varval = var->value(); - - // Special case for zero-sized globals. These require a type conversion, - // since the underlying definition has been coerced to something with - // non-zero size (as a means of avoiding linker misbehavior). - Btype *underlyingType = var->underlyingType(); - if (underlyingType != nullptr) { - LIRBuilder irbuilder(context_, llvm::ConstantFolder()); - std::string tag(namegen("zeroSizeCast")); - llvm::Type *toType = llvm::PointerType::get(var->btype()->type(), - addressSpace_); - llvm::Value *bitcast = - irbuilder.CreateBitCast(var->value(), toType, tag); - varval = bitcast; - } - Bexpression *varexp = nbuilder_.mkVar(var, varval, location); varexp->setTag(var->name().c_str()); return varexp; @@ -1172,13 +1141,13 @@ BIntegerType *bit = btype->castToBIntegerType(); if (bit->isUnsigned()) { uint64_t val = checked_convert_mpz_to_int<uint64_t>(mpz_val); - llvm::APInt apiv(bit->bits(), val); + llvm::APInt apiv(bit->bits(), val, false, true); llvm::Constant *lval = llvm::ConstantInt::get(btype->type(), apiv); Bexpression *bconst = nbuilder_.mkConst(btype, lval); return makeGlobalExpression(bconst, lval, btype, Location()); } else { int64_t val = checked_convert_mpz_to_int<int64_t>(mpz_val); - llvm::APInt apiv(bit->bits(), val, true); + llvm::APInt apiv(bit->bits(), val, true, true); llvm::Constant *lval = llvm::ConstantInt::get(btype->type(), apiv); Bexpression *bconst = nbuilder_.mkConst(btype, lval); return makeGlobalExpression(bconst, lval, btype, Location()); @@ -1310,11 +1279,9 @@ MV_SkipDebug, llvm::GlobalValue::PrivateLinkage, scon, 1); llvm::Constant *varval = llvm::cast<llvm::Constant>(svar->value()); - llvm::Constant *bitcast = - llvm::ConstantExpr::getBitCast(varval, stringType()->type()); - Bexpression *bconst = nbuilder_.mkConst(stringType(), bitcast); + Bexpression *bconst = nbuilder_.mkConst(stringType(), varval); Bexpression *rval = - makeGlobalExpression(bconst, bitcast, stringType(), Location()); + makeGlobalExpression(bconst, varval, stringType(), Location()); stringConstantMap_[scon] = rval; return rval; } @@ -2159,7 +2126,7 @@ llvm::Value *old = nullptr; if (glob && glob->getLinkage() == linkage) { // A global variable with same name already exists. - if (glob->getType()->getElementType() == btype->type()) { + if (glob->getValueType() == btype->type()) { if (isExtInit == MV_NotExternallyInitialized) { // A definition overrides a declaration for external var. glob->setExternallyInitialized(false); @@ -2190,16 +2157,12 @@ // Here we are creating an external declaration // of a different type. We make a bitcast to the // new type. - llvm::Constant *decl = module_->getOrInsertGlobal(gname, btype->type()); - bool addressTaken = true; // for now - Bvariable *bv = - new Bvariable(btype, location, gname, GlobalVar, addressTaken, decl); - assert(valueVarMap_.find(bv->value()) == valueVarMap_.end()); - valueVarMap_[bv->value()] = bv; - if (genDebug == MV_GenDebug && dibuildhelper() && !errorCount_) { - bool exported = (linkage == llvm::GlobalValue::ExternalLinkage); - dibuildhelper()->processGlobal(bv, exported); - } + + // Starting from LLVM-17 we're no longer using bitcasts + // for pointer types + auto it = valueVarMap_.find(glob); + assert(it != valueVarMap_.end()); + Bvariable *bv = it->second; return bv; } } @@ -2239,8 +2202,7 @@ // Fix up old declaration if there is one if (old) { assert(llvm::isa<llvm::PointerType>(old->getType())); - llvm::Type *declTyp = - llvm::cast<llvm::PointerType>(old->getType())->getElementType(); + llvm::Type *declTyp = llvm::cast<llvm::GlobalValue>(old)->getValueType(); llvm::Constant *newDecl = module_->getOrInsertGlobal(gname, declTyp); old->replaceAllUsesWith(newDecl); // NB: previously we had a call to old->deleteValue() here, but this @@ -2534,7 +2496,7 @@ // A global with the same name already declared? llvm::GlobalVariable *glob = module_->getGlobalVariable(gname); if (glob) { - assert(glob->getType()->getElementType() == btype->type()); + assert(glob->getValueType() == btype->type()); auto it = valueVarMap_.find(glob); assert(it != valueVarMap_.end()); Bvariable *bv = it->second; @@ -2784,17 +2746,17 @@ fns == "runtime.mapaccess2_fast64" || fns == "runtime.mapaccess2_faststr" || fns == "runtime.mapaccess2_fat")) - fcn->addFnAttr(llvm::Attribute::ReadOnly); + fcn->setOnlyReadsMemory(); // memcmp-like. if (fns == "runtime.memequal" || fns == "runtime.cmpstring") { - fcn->addFnAttr(llvm::Attribute::ReadOnly); - fcn->addFnAttr(llvm::Attribute::ArgMemOnly); + fcn->setOnlyReadsMemory(); + fcn->setOnlyAccessesArgMemory(); } if (fns == "runtime.memclrNoHeapPointers") - fcn->addFnAttr(llvm::Attribute::ArgMemOnly); + fcn->setOnlyAccessesArgMemory(); // These functions are called in unlikely branches. But they // themselves are not actually cold in the runtime. So only @@ -3152,10 +3114,7 @@ // possibly-excepting call with landing pad. llvm::SmallVector<llvm::Value *, 8> args(call->arg_begin(), call->arg_end()); llvm::Value *callop = call->getCalledOperand(); - llvm::PointerType *pft = - llvm::cast<llvm::PointerType>(callop->getType()); - llvm::FunctionType *fty = - llvm::cast<llvm::FunctionType>(pft->getElementType()); + llvm::FunctionType *fty = call->getFunctionType(); llvm::InvokeInst *invcall = llvm::InvokeInst::Create(fty, callop, contbb, padbb, args, call->getName()); @@ -3284,7 +3243,7 @@ changed = true; if (dibuildhelper_) dibuildhelper_->processExprInst(containingStmt, expr, inst); - curblock->getInstList().push_back(inst); + inst->insertBefore(*curblock, curblock->end()); curblock = pair.second; newinsts.push_back(inst); @@ -3294,7 +3253,7 @@ // current block. LIRBuilder builder(context_, llvm::ConstantFolder()); llvm::Instruction *unreachable = builder.CreateUnreachable(); - curblock->getInstList().push_back(unreachable); + unreachable->insertBefore(*curblock, curblock->end()); curblock = nullptr; changed = true; @@ -3370,7 +3329,7 @@ else { LIRBuilder builder(context_, llvm::ConstantFolder()); llvm::Instruction *unreachable = builder.CreateUnreachable(); - tsucc->getInstList().push_back(unreachable); + unreachable->insertBefore(*tsucc, tsucc->end()); } } @@ -3383,7 +3342,7 @@ else { LIRBuilder builder(context_, llvm::ConstantFolder()); llvm::Instruction *unreachable = builder.CreateUnreachable(); - fsucc->getInstList().push_back(unreachable); + unreachable->insertBefore(*fsucc, fsucc->end()); } } } @@ -3578,12 +3537,12 @@ if (&inst == term) break; // terminator is handled below llvm::Instruction *c = cloneInstruction(&inst, argMap); - curblock->getInstList().push_back(c); + c->insertBefore(*curblock, curblock->end()); } if (llvm::isa<llvm::InvokeInst>(term)) { // This is the call to DEFERRETURN. Copy this then we're done. llvm::Instruction *c = cloneInstruction(term, argMap); - curblock->getInstList().push_back(c); + c->insertBefore(*curblock, curblock->end()); break; } // By construction it should be linear code. @@ -3736,7 +3695,8 @@ // Populate resume block builder.SetInsertPoint(finResBB); std::string ename(be_->namegen("excv")); - llvm::LoadInst *exload = builder.CreateLoad(extmp->getType()->getPointerElementType(), extmp, ename); + llvm::Type *vty = llvm::cast<llvm::AllocaInst>(extmp)->getAllocatedType(); + llvm::LoadInst *exload = builder.CreateLoad(vty, extmp, ename); builder.CreateResume(exload); return finRetBB; @@ -4021,7 +3981,7 @@ llvm::Value *zv = llvm::Constant::getNullValue(rtyp); ri = builder.CreateRet(zv); } - epilog->getInstList().push_back(ri); + ri->insertBefore(*epilog, epilog->end()); } }
diff --git a/bridge/go-llvm.h b/bridge/go-llvm.h index cd4d855..78602e3 100644 --- a/bridge/go-llvm.h +++ b/bridge/go-llvm.h
@@ -65,7 +65,7 @@ struct GenCallState; #include "llvm/IR/GlobalValue.h" -#include "llvm/ADT/Triple.h" +#include "llvm/TargetParser/Triple.h" // // LLVM-specific implementation of the Backend class; the code in @@ -487,7 +487,7 @@ Location location); // Field GEP helper - llvm::Value *makeFieldGEP(unsigned fieldIndex, + llvm::Value *makeFieldGEP(unsigned fieldIndex, llvm::Type *sty, llvm::Value *sptr); // Array indexing GEP helper @@ -496,8 +496,7 @@ llvm::Value *sptr); // Pointer indexing GEP helper - llvm::Value *makePointerOffsetGEP(llvm::PointerType *pt, - llvm::Value *idx, + llvm::Value *makePointerOffsetGEP(Btype *pt, llvm::Value *idx, llvm::Value *sptr); // Assignment helper @@ -614,39 +613,6 @@ // error statement, returning TRUE if so. bool stmtVectorHasError(const std::vector<Bstatement *> &stmts); - // Converts value "src" for assignment to container of type - // "dstType" in assignment-like contexts. This helper exists to help - // with cases where the frontend is creating an assignment of form - // "X = Y" where X and Y's types are considered matching by the - // front end, but are non-matching in an LLVM context. For example, - // - // type Ifi func(int) int - // ... - // var fp Ifi = myfunctionfoobar - // - // Here the right hand side will come out as pointer-to-descriptor, - // whereas variable "fp" will have type "pointer to functon", which are - // not the same. Another example is assignments involving nil, e.g. - // - // var ip *float32 - // ... - // ip = nil - // - // The type of the right hand side of the assignment will be a - // generic "*i64" as opposed to "*float32", since the backend - // "nil_pointer_expression" does not allow for creation of nil - // pointers of specific types. - // - // Return value will be a new convert Bexpression if a convert is - // needed, NULL otherwise. - llvm::Value *convertForAssignment(Bexpression *src, - llvm::Type *dstToType); - // lower-level version of the routine above - llvm::Value *convertForAssignment(Btype *srcType, - llvm::Value *srcVal, - llvm::Type *dstToType, - BlockLIRBuilder *builder); - // Apply type conversion for a binary operation. This helper exists // to resolve situations where expressions are created by the front
diff --git a/bridge/go-sha1.cpp b/bridge/go-sha1.cpp index 54925d5..e978c8e 100644 --- a/bridge/go-sha1.cpp +++ b/bridge/go-sha1.cpp
@@ -47,7 +47,8 @@ std::string Llvm_Sha1_Helper::finish() { - std::string result(ctx_->final().str(), 0, checksum_len); + auto arr = ctx_->final(); + std::string result(std::begin(arr), std::begin(arr) + checksum_len); return result; }
diff --git a/driver-main/llvm-goc.cpp b/driver-main/llvm-goc.cpp index 472dc2f..f635e00 100644 --- a/driver-main/llvm-goc.cpp +++ b/driver-main/llvm-goc.cpp
@@ -26,7 +26,6 @@ #include "Tool.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/IR/DiagnosticInfo.h" @@ -35,7 +34,6 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Verifier.h" -#include "llvm/MC/SubtargetFeature.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" @@ -43,8 +41,8 @@ #include "llvm/Passes/PassBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Format.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -56,8 +54,9 @@ #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/SubtargetFeature.h" +#include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include <algorithm> #include <cstring> @@ -95,7 +94,7 @@ const char *progname = argv[0]; unsigned missingArgIndex, missingArgCount; - ArrayRef<const char *> argvv = makeArrayRef(argv, argc); + ArrayRef<const char *> argvv(argv, argc); args_ = opts_->ParseArgs(argvv.slice(1), missingArgIndex, missingArgCount); // Honor --help first @@ -172,9 +171,8 @@ // that standard input be empty (so as to support the Go tool, but // not act as a general-purposes C compiler). opt::Arg *xarg = args_.getLastArg(gollvm::options::OPT_x); - if (xarg != nullptr && - ! llvm::StringRef(xarg->getValue()).equals("c") && - ! llvm::StringRef(xarg->getValue()).equals("go")) { + if (xarg != nullptr && llvm::StringRef(xarg->getValue()) != "c" && + llvm::StringRef(xarg->getValue()) != "go") { errs() << progname << ": invalid argument '" << xarg->getValue() << "' to '" << xarg->getAsString(args_) << "' option\n";
diff --git a/driver/ArchCpuSetup.cpp b/driver/ArchCpuSetup.cpp index a7eb765..bf91983 100644 --- a/driver/ArchCpuSetup.cpp +++ b/driver/ArchCpuSetup.cpp
@@ -13,8 +13,8 @@ #include "ArchCpuSetup.h" #include "llvm/Option/Arg.h" -#include "llvm/Support/Host.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Host.h" namespace gollvm { namespace arch { #include "ArchCpusAttrs.h"
diff --git a/driver/Command.cpp b/driver/Command.cpp index 2f10e8c..956108a 100644 --- a/driver/Command.cpp +++ b/driver/Command.cpp
@@ -36,13 +36,11 @@ argv.reserve(n); for (size_t i = 0; i < n; ++i) argv.push_back(arguments_[i]); - return llvm::sys::ExecuteAndWait(executable_, - argv, - /*env=*/llvm::None, - /*Redirects*/{}, + return llvm::sys::ExecuteAndWait(executable_, argv, + /*env=*/{}, + /*Redirects*/ {}, /*secondsToWait=*/0, - /*memoryLimit=*/0, - errMsg); + /*memoryLimit=*/0, errMsg); } void Command::print(llvm::raw_ostream &os, bool quoteArgs)
diff --git a/driver/Compilation.cpp b/driver/Compilation.cpp index 4123e40..6abf2f0 100644 --- a/driver/Compilation.cpp +++ b/driver/Compilation.cpp
@@ -127,8 +127,8 @@ return newFileArtifact(ofn.c_str(), false); } -llvm::Optional<Artifact*> Compilation::createTemporaryFileArtifact(Action *act) -{ +std::optional<Artifact *> +Compilation::createTemporaryFileArtifact(Action *act) { llvm::SmallString<128> tempFileName; std::error_code tfcEC = llvm::sys::fs::createTemporaryFile(act->getName(), @@ -137,7 +137,7 @@ if (tfcEC) { llvm::errs() << driver_.progname() << ": error: " << tfcEC.message() << "\n"; - return llvm::None; + return {}; } return newFileArtifact(tempFileName.c_str(), true); }
diff --git a/driver/Compilation.h b/driver/Compilation.h index ec96bc8..4861b60 100644 --- a/driver/Compilation.h +++ b/driver/Compilation.h
@@ -45,9 +45,9 @@ // Generate a new temp file and return an artifact for it. Here // llvm::Optional is used in case the temp file creation fails for // some reason. - llvm::Optional<Artifact*> createTemporaryFileArtifact(Action *act); + std::optional<Artifact *> createTemporaryFileArtifact(Action *act); - // Create new artifact based on file name. If 'isTempfile' is set, + // Create new artifact based on file name. If 'isTempfile' is set, // the file should be scheduled for deletion after compilation finishes. Artifact *newFileArtifact(const char *path, bool isTempFile);
diff --git a/driver/CompileGo.cpp b/driver/CompileGo.cpp index 26af4e7..3601a36 100644 --- a/driver/CompileGo.cpp +++ b/driver/CompileGo.cpp
@@ -41,25 +41,24 @@ #include "llvm/Config/llvm-config.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" -#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Verifier.h" -#include "llvm/MC/SubtargetFeature.h" +#include "llvm/IRPrinter/IRPrintingPasses.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" #include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Remarks/RemarkStreamer.h" #include "llvm/Remarks/YAMLRemarkSerializer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" -#include "llvm/Support/Host.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -70,11 +69,14 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/Host.h" +#include "llvm/TargetParser/SubtargetFeature.h" #include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils.h" +#include "llvm/Transforms/Utils/AddDiscriminators.h" #include <sstream> @@ -111,8 +113,10 @@ const char *progname_; std::string executablePath_; opt::InputArgList &args_; - CodeGenOpt::Level cgolvl_; - unsigned olvl_; + CodeGenOptLevel cgolvl_; + OptimizationLevel olvl_; + PipelineTuningOptions pto_; + std::optional<PGOOptions> pgo_; bool hasError_; std::unique_ptr<Llvm_backend> bridge_; std::unique_ptr<TargetMachine> target_; @@ -129,8 +133,6 @@ std::string sampleProfileFile_; bool enable_gc_; - void createPasses(legacy::PassManager &MPM, - legacy::FunctionPassManager &FPM); void setupGoSearchPath(); void setCConv(); @@ -148,22 +150,13 @@ bool enableVectorization(bool slp); }; -CompileGoImpl::CompileGoImpl(CompileGo &cg, - ToolChain &tc, +CompileGoImpl::CompileGoImpl(CompileGo &cg, ToolChain &tc, const std::string &executablePath) - : cg_(cg), - triple_(tc.driver().triple()), - toolchain_(tc), - driver_(tc.driver()), - cconv_(CallingConvId::MaxID), - progname_(tc.driver().progname()), - executablePath_(executablePath), - args_(tc.driver().args()), - cgolvl_(CodeGenOpt::Default), - olvl_(2), - hasError_(false), - enable_gc_(false) -{ + : cg_(cg), triple_(tc.driver().triple()), toolchain_(tc), + driver_(tc.driver()), cconv_(CallingConvId::MaxID), + progname_(tc.driver().progname()), executablePath_(executablePath), + args_(tc.driver().args()), cgolvl_(CodeGenOptLevel::Default), + olvl_(OptimizationLevel::O2), hasError_(false), enable_gc_(false) { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); @@ -311,21 +304,28 @@ } switch (lev[0]) { case '0': - olvl_ = 0; - cgolvl_ = CodeGenOpt::None; + olvl_ = OptimizationLevel::O0; + cgolvl_ = CodeGenOptLevel::None; break; case '1': - olvl_ = 1; - cgolvl_ = CodeGenOpt::Less; + olvl_ = OptimizationLevel::O1; + cgolvl_ = CodeGenOptLevel::Less; break; - case 's': // TODO: -Os same as -O for now. + case 'z': + olvl_ = OptimizationLevel::Oz; + cgolvl_ = CodeGenOptLevel::Less; + break; + case 's': + olvl_ = OptimizationLevel::Os; + cgolvl_ = CodeGenOptLevel::Less; + break; case '2': - olvl_ = 2; - cgolvl_ = CodeGenOpt::Default; + olvl_ = OptimizationLevel::O2; + cgolvl_ = CodeGenOptLevel::Default; break; case '3': - olvl_ = 3; - cgolvl_ = CodeGenOpt::Aggressive; + olvl_ = OptimizationLevel::O3; + cgolvl_ = CodeGenOptLevel::Aggressive; break; default: errs() << progname_ << ": invalid optimization level.\n"; @@ -333,11 +333,18 @@ } } - go_no_warn = args_.hasArg(gollvm::options::OPT_w); - go_loc_show_column = - driver_.reconcileOptionPair(gollvm::options::OPT_fshow_column, - gollvm::options::OPT_fno_show_column, - true); + pto_.LoopVectorization = enableVectorization(false); + pto_.SLPVectorization = enableVectorization(true); + pto_.LoopUnrolling = driver_.reconcileOptionPair(gollvm::options::OPT_funroll_loops, + gollvm::options::OPT_fno_unroll_loops, true); + pto_.LoopInterleaving = driver_.reconcileOptionPair(gollvm::options::OPT_finterleave_loops, + gollvm::options::OPT_fno_interleave_loops, true); + // Merge identical functions at the LLVM IR level. + pto_.MergeFunctions = driver_.reconcileOptionPair(gollvm::options::OPT_fmerge_functions, + gollvm::options::OPT_fno_merge_functions, false); + // Provide .cgoprofile section for lld to order functions. + pto_.CallGraphProfile = driver_.reconcileOptionPair(gollvm::options::OPT_fcg_profile, + gollvm::options::OPT_fno_cg_profile, false); // AutoFDO. opt::Arg *sprofarg = @@ -365,6 +372,29 @@ } } + pto_.LoopVectorization = enableVectorization(false); + pto_.SLPVectorization = enableVectorization(true); + pto_.LoopUnrolling = + driver_.reconcileOptionPair(gollvm::options::OPT_funroll_loops, + gollvm::options::OPT_fno_unroll_loops, true); + pto_.LoopInterleaving = driver_.reconcileOptionPair( + gollvm::options::OPT_finterleave_loops, + gollvm::options::OPT_fno_interleave_loops, true); + // Merge identical functions at the LLVM IR level. + pto_.MergeFunctions = driver_.reconcileOptionPair( + gollvm::options::OPT_fmerge_functions, + gollvm::options::OPT_fno_merge_functions, false); + // Provide .cgoprofile section for lld to order functions. + pto_.CallGraphProfile = + driver_.reconcileOptionPair(gollvm::options::OPT_fcg_profile, + gollvm::options::OPT_fno_cg_profile, false); + + go_no_warn = args_.hasArg(gollvm::options::OPT_w); + go_loc_show_column = + driver_.reconcileOptionPair(gollvm::options::OPT_fshow_column, + gollvm::options::OPT_fno_show_column, + true); + // Capture optimization record. opt::Arg *optrecordarg = args_.getLastArg(gollvm::options::OPT_fsave_optimization_record, @@ -420,7 +450,7 @@ llvm::DebugCompressionType dct = llvm::DebugCompressionType::None; if (!driver_.determineDebugCompressionType(&dct)) return false; - Options.CompressDebugSections = dct; + Options.MCOptions.CompressDebugSections = dct; // FIXME: this hard-wires on the equivalent of -ffunction-sections // and -fdata-sections, since there doesn't seem to be a high-level @@ -473,7 +503,7 @@ return false; // Create target machine - Optional<llvm::CodeModel::Model> CM = None; + std::optional<llvm::CodeModel::Model> CM = {}; target_.reset( TheTarget->createTargetMachine(triple_.getTriple(), targetCpuAttr_, targetFeaturesAttr_, @@ -497,7 +527,7 @@ std::make_unique<BEDiagnosticHandler>(&this->hasError_, this->remarkCtl_)); - llvm::Optional<unsigned> enable_gc = + std::optional<unsigned> enable_gc = driver_.getLastArgAsInteger(gollvm::options::OPT_enable_gc_EQ, 0u); enable_gc_ = enable_gc && *enable_gc; @@ -523,7 +553,7 @@ bridge_.reset(new Llvm_backend(context_, module_.get(), linemap_.get(), addrspace, triple_, cconv_)); // Honor inline, tracelevel cmd line options - llvm::Optional<unsigned> tl = + std::optional<unsigned> tl = driver_.getLastArgAsInteger(gollvm::options::OPT_tracelevel_EQ, 0u); if (!tl) return false; @@ -601,7 +631,7 @@ true); args.compiling_runtime = args_.hasArg(gollvm::options::OPT_fgo_compiling_runtime); - llvm::Optional<int> del = + std::optional<int> del = driver_.getLastArgAsInteger(gollvm::options::OPT_fgo_debug_escape_EQ, 0); if (!del) return false; @@ -759,7 +789,7 @@ bridge_->dumpModule(); if (!args_.hasArg(gollvm::options::OPT_noverify) && !go_be_saw_errors()) bridge_->verifyModule(); - llvm::Optional<unsigned> tl = + std::optional<unsigned> tl = driver_.getLastArgAsInteger(gollvm::options::OPT_tracelevel_EQ, 0u); if (*tl) std::cerr << "linemap stats:" << linemap_->statistics() << "\n"; @@ -780,7 +810,7 @@ bool CompileGoImpl::enableVectorization(bool slp) { - bool enable = (olvl_ > 1); + bool enable = (olvl_.getSpeedupLevel() > 1); if (slp) return driver_.reconcileOptionPair(gollvm::options::OPT_fslp_vectorize, gollvm::options::OPT_fno_slp_vectorize, @@ -791,108 +821,116 @@ enable); } -static void addAddDiscriminatorsPass(const llvm::PassManagerBuilder &Builder, - llvm::legacy::PassManagerBase &PM) { - PM.add(createAddDiscriminatorsPass()); -} - -void CompileGoImpl::createPasses(legacy::PassManager &MPM, - legacy::FunctionPassManager &FPM) +bool CompileGoImpl::invokeBackEnd(const Action &jobAction) { - if (args_.hasArg(gollvm::options::OPT_disable_llvm_passes)) - return; + LoopAnalysisManager lam; + FunctionAnalysisManager fam; + CGSCCAnalysisManager gcam; + ModuleAnalysisManager mam; - // FIXME: support LTO, ThinLTO, PGO + bool debugPassStructure = false; + bool debugPassManager = args_.hasArg(gollvm::options::OPT_fdebug_pass_manager); + bool verifyEach = args_.hasArg(gollvm::options::OPT_fverify_each); + PassInstrumentationCallbacks pic; + PrintPassOptions printPassOpts; + printPassOpts.Indent = debugPassStructure; + printPassOpts.SkipAnalyses = debugPassStructure; + StandardInstrumentations si(context_, debugPassManager || debugPassStructure, + verifyEach, printPassOpts); - PassManagerBuilder pmb; + // TODO: Maybe better to keep some kind of pass table. + pic.addClassToPassName("GoStatepoints", "go-statepoints"); + pic.addClassToPassName("GoSafeGetgPass", "go-safegetg"); + pic.addClassToPassName("RemoveAddrSpacePass", "remove-addrspacecast"); - // Configure the inliner - if (args_.hasArg(gollvm::options::OPT_fno_inline) || olvl_ == 0) { - // Nothing here at the moment. There is go:noinline, but no equivalent - // of go:alwaysinline. - } else { - bool disableInlineHotCallSite = false; // for autofdo, not yet supported - pmb.Inliner = - createFunctionInliningPass(olvl_, 2, disableInlineHotCallSite); + si.registerCallbacks(pic); + + PassBuilder pb(target_.get(), pto_, pgo_, &pic); + + // Register the target library analysis directly and give it a customized + // preset TLI. + tlii_.reset(new TargetLibraryInfoImpl(triple_)); + fam.registerPass([this] { return TargetLibraryAnalysis(*tlii_); }); + + // Register all the basic analyses with the managers. + pb.registerModuleAnalyses(mam); + pb.registerCGSCCAnalyses(gcam); + pb.registerFunctionAnalyses(fam); + pb.registerLoopAnalyses(lam); + pb.crossRegisterProxies(lam, fam, gcam, mam); + + bool disablePasses = args_.hasArg(gollvm::options::OPT_disable_llvm_passes); + ThinOrFullLTOPhase lto_phase = ThinOrFullLTOPhase::None; + + ModulePassManager modulePasses; + if (!disablePasses) { + if (olvl_ == OptimizationLevel::O0) { + + modulePasses = pb.buildO0DefaultPipeline(olvl_, lto_phase); + } else if (lto_phase == ThinOrFullLTOPhase::ThinLTOPreLink) { + modulePasses = pb.buildThinLTOPreLinkDefaultPipeline(olvl_); + } else if (lto_phase == ThinOrFullLTOPhase::FullLTOPreLink) { + modulePasses = pb.buildLTOPreLinkDefaultPipeline(olvl_); + } else { + modulePasses = pb.buildPerModuleDefaultPipeline(olvl_); + } } - pmb.OptLevel = olvl_; - pmb.SizeLevel = 0; // TODO: decide on right value here - pmb.PrepareForThinLTO = false; - pmb.PrepareForLTO = false; - pmb.SLPVectorize = enableVectorization(true); - pmb.LoopVectorize = enableVectorization(false); + bool needDwarfDiscr = !sampleProfileFile_.empty(); - bool needDwarfDiscr = false; - if (! sampleProfileFile_.empty()) { - pmb.PGOSampleUse = sampleProfileFile_; - needDwarfDiscr = true; - } opt::Arg *dbgprofarg = args_.getLastArg(gollvm::options::OPT_fdebug_info_for_profiling, gollvm::options::OPT_fno_debug_info_for_profiling); if (dbgprofarg) { - if (dbgprofarg->getOption().matches(gollvm::options::OPT_fdebug_info_for_profiling)) + if (dbgprofarg->getOption().matches( + gollvm::options::OPT_fdebug_info_for_profiling)) needDwarfDiscr = true; else needDwarfDiscr = false; } - if (needDwarfDiscr) - pmb.addExtension(llvm::PassManagerBuilder::EP_EarlyAsPossible, - addAddDiscriminatorsPass); - - - FPM.add(new TargetLibraryInfoWrapperPass(*tlii_)); - if (! args_.hasArg(gollvm::options::OPT_noverify)) - FPM.add(createVerifierPass()); - - pmb.populateFunctionPassManager(FPM); - pmb.populateModulePassManager(MPM); -} - -bool CompileGoImpl::invokeBackEnd(const Action &jobAction) -{ - tlii_.reset(new TargetLibraryInfoImpl(triple_)); - - // Set up module and function passes - legacy::PassManager modulePasses; - modulePasses.add( - createTargetTransformInfoWrapperPass(target_->getTargetIRAnalysis())); - legacy::FunctionPassManager functionPasses(module_.get()); - functionPasses.add( - createTargetTransformInfoWrapperPass(target_->getTargetIRAnalysis())); - createPasses(modulePasses, functionPasses); + if (needDwarfDiscr) { + pb.registerPipelineStartEPCallback([](llvm::ModulePassManager &MPM, + llvm::OptimizationLevel) { + MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); + }); + } // Disable inlining getg in some cases on x86_64. if (triple_.getArch() == llvm::Triple::x86_64) { - modulePasses.add(createGoSafeGetgPass()); + modulePasses.addPass(GoSafeGetgPass()); } // Add statepoint insertion pass to the end of optimization pipeline, // right before lowering to machine IR. if (enable_gc_) { - modulePasses.add(createGoStatepointsLegacyPass()); - modulePasses.add(createRemoveAddrSpacePass(target_->createDataLayout())); + modulePasses.addPass(GoStatepoints()); + modulePasses.addPass(RemoveAddrSpacePass(target_->createDataLayout())); } + // We still use the legacy PM to run the codegen pipeline since the new PM + // does not work with the codegen pipeline. legacy::PassManager codeGenPasses; bool noverify = args_.hasArg(gollvm::options::OPT_noverify); - CodeGenFileType ft = (jobAction.type() == Action::A_CompileAndAssemble ? - CGFT_ObjectFile : CGFT_AssemblyFile); // Add passes to emit bitcode or LLVM IR as appropriate. Here we mimic // clang behavior, which is to emit bitcode when "-emit-llvm" is specified // but an LLVM IR dump of "-S -emit-llvm" is used. raw_pwrite_stream *OS = &asmout_->os(); if (args_.hasArg(gollvm::options::OPT_emit_llvm)) { + if (!noverify) { + modulePasses.addPass(VerifierPass()); + } bool bitcode = !args_.hasArg(gollvm::options::OPT_S); bool preserveUseLists = driver_.reconcileOptionPair(gollvm::options::OPT_emit_llvm_uselists, gollvm::options::OPT_no_emit_llvm_uselists, false); - modulePasses.add(bitcode ? - createBitcodeWriterPass(*OS, preserveUseLists) : - createPrintModulePass(*OS, "", preserveUseLists)); + if (bitcode) { + modulePasses.addPass(BitcodeWriterPass(*OS, preserveUseLists, + /* ThinLTO summary */ false)); + } else { + modulePasses.addPass(PrintModulePass(*OS, "", preserveUseLists)); + } goto run; } @@ -909,7 +947,11 @@ // LLVMTargetMachine::addPassesToEmitFile (and its callee). // TODO: error check. { - LLVMTargetMachine *lltm = (LLVMTargetMachine*)(target_.get()); // FIXME: TargetMachine doesn't support llvm::cast? + CodeGenFileType ft = (jobAction.type() == Action::A_CompileAndAssemble + ? CodeGenFileType::ObjectFile + : CodeGenFileType::AssemblyFile); + llvm::TargetMachine *lltm = + target_.get(); // FIXME: TargetMachine doesn't support llvm::cast? TargetPassConfig *passConfig = lltm->createPassConfig(codeGenPasses); // Set PassConfig options provided by TargetMachine. passConfig->setDisableVerify(noverify); @@ -932,15 +974,8 @@ } run: - // Here we go... first function passes - functionPasses.doInitialization(); - for (Function &F : *module_.get()) - if (!F.isDeclaration()) - functionPasses.run(F); - functionPasses.doFinalization(); - // ... then module passes - modulePasses.run(*module_.get()); + modulePasses.run(*module_.get(), mam); // ... and finally code generation if (!args_.hasArg(gollvm::options::OPT_emit_llvm))
diff --git a/driver/Distro.cpp b/driver/Distro.cpp index 2eace0d..0b02411 100644 --- a/driver/Distro.cpp +++ b/driver/Distro.cpp
@@ -12,7 +12,7 @@ #include "Distro.h" -#include "llvm/Support/Host.h" +#include "llvm/TargetParser/Host.h" namespace distro {
diff --git a/driver/Distro.h b/driver/Distro.h index 4bd0a36..086e0e7 100644 --- a/driver/Distro.h +++ b/driver/Distro.h
@@ -14,7 +14,7 @@ #define GOLLVM_DRIVER_DISTRO_H #include "GccUtils.h" -#include "llvm/ADT/Triple.h" +#include "llvm/TargetParser/Triple.h" namespace distro {
diff --git a/driver/Driver.cpp b/driver/Driver.cpp index 777cc2b..4355475 100644 --- a/driver/Driver.cpp +++ b/driver/Driver.cpp
@@ -11,9 +11,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/FileSystem.h" -#include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" +#include "llvm/TargetParser/Host.h" #include <sstream> @@ -185,9 +185,9 @@ value == "--nocompress-debug-sections") { continue; } - if (value.startswith("-compress-debug-sections") || - value.startswith("--compress-debug-sections") || - value.startswith("-march")) { + if (value.starts_with("-compress-debug-sections") || + value.starts_with("--compress-debug-sections") || + value.starts_with("-march")) { continue; } // Unrecognized -Wa,... option @@ -203,11 +203,11 @@ llvm::DebugCompressionType *dct, const char *which) { - if (ga == "zlib") { - *dct = llvm::DebugCompressionType::Z; + if (ga == "zlib" || ga == "zlib-gnu") { + *dct = llvm::DebugCompressionType::Zlib; return dct; - } else if (ga == "zlib-gnu") { - *dct = llvm::DebugCompressionType::GNU; + } else if (ga == "zstd") { + *dct = llvm::DebugCompressionType::Zstd; return dct; } else if (ga == "none") { *dct = llvm::DebugCompressionType::None; @@ -231,7 +231,7 @@ gollvm::options::OPT_Wa_COMMA, gollvm::options::OPT_Xassembler)) { if (arg->getOption().matches(gollvm::options::OPT_gz)) { - *dct = llvm::DebugCompressionType::GNU; + *dct = llvm::DebugCompressionType::Zlib; } else if (arg->getOption().matches(gollvm::options::OPT_gz_EQ)) { auto value = llvm::StringRef(arg->getValue()); if (gzArgToDCT(value, dct, "-gz=") == nullptr) @@ -242,15 +242,15 @@ if (value == "-nocompress-debug-sections" || value == "--nocompress-debug-sections") { *dct = llvm::DebugCompressionType::None; - } else if (value.startswith("-compress-debug-sections") || - value.startswith("--compress-debug-sections")) { + } else if (value.starts_with("-compress-debug-sections") || + value.starts_with("--compress-debug-sections")) { const char *wh = (arg->getOption().matches(gollvm::options::OPT_Xassembler) ? "-Xassembler" : "-Wa,"); value.consume_front("--compress-debug-sections"); value.consume_front("-compress-debug-sections"); auto arg = value; - if (value.startswith("=")) + if (value.starts_with("=")) arg.consume_front("="); else arg = "zlib"; @@ -365,20 +365,16 @@ return false; } -Optional<Reloc::Model> -Driver::reconcileRelocModel() -{ +std::optional<Reloc::Model> Driver::reconcileRelocModel() { auto picLevel = getPicLevel(); if (picLevel != PICLevel::NotPIC) { Reloc::Model R = Reloc::PIC_; return R; } - return None; + return {}; } -Optional<FPOpFusion::FPOpFusionMode> -Driver::getFPOpFusionMode() -{ +std::optional<FPOpFusion::FPOpFusionMode> Driver::getFPOpFusionMode() { opt::Arg *arg = args_.getLastArg(gollvm::options::OPT_ffp_contract_EQ); FPOpFusion::FPOpFusionMode res = FPOpFusion::Standard; if (arg != nullptr) { @@ -393,7 +389,7 @@ errs() << progname_ << ": invalid argument '" << arg->getValue() << "' to '" << arg->getAsString(args_) << "' option\n"; - return None; + return {}; } } return res; @@ -504,8 +500,8 @@ opt::Arg *xarg = args_.getLastArg(gollvm::options::OPT_x); assert(xarg); const char *suf = - (llvm::StringRef(xarg->getValue()).equals("c") ? "c" : - (llvm::StringRef(xarg->getValue()).equals("go") ? "go" : "?")); + (xarg->containsValue("c") ? "c" + : (xarg->containsValue("go") ? "go" : "?")); act = new ReadStdinAction(suf); schedAction = true; } else {
diff --git a/driver/Driver.h b/driver/Driver.h index 3b2813d..6c87d5d 100644 --- a/driver/Driver.h +++ b/driver/Driver.h
@@ -13,16 +13,15 @@ #ifndef GOLLVM_DRIVER_DRIVER_H #define GOLLVM_DRIVER_DRIVER_H -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/TargetParser/Triple.h" #include "Action.h" #include "Artifact.h" @@ -112,14 +111,14 @@ bool supportedAsmOptions(); bool determineDebugCompressionType(llvm::DebugCompressionType *dct); bool usingSplitStack() const { return usingSplitStack_; } - template<typename IT> - llvm::Optional<IT> getLastArgAsInteger(gollvm::options::ID id, - IT defaultValue); - llvm::Optional<llvm::Reloc::Model> reconcileRelocModel(); + template <typename IT> + std::optional<IT> getLastArgAsInteger(gollvm::options::ID id, + IT defaultValue); + std::optional<llvm::Reloc::Model> reconcileRelocModel(); bool reconcileOptionPair(gollvm::options::ID yesOption, gollvm::options::ID noOption, bool defaultVal); - llvm::Optional<llvm::FPOpFusion::FPOpFusionMode> getFPOpFusionMode(); + std::optional<llvm::FPOpFusion::FPOpFusionMode> getFPOpFusionMode(); typedef llvm::SmallVector<llvm::opt::Arg *, 8> inarglist; void appendInputActions(const inarglist &infiles, ActionList &result, @@ -155,11 +154,9 @@ const char *which); }; -template<typename IT> -llvm::Optional<IT> -Driver::getLastArgAsInteger(gollvm::options::ID id, - IT defaultValue) -{ +template <typename IT> +std::optional<IT> Driver::getLastArgAsInteger(gollvm::options::ID id, + IT defaultValue) { IT result = defaultValue; llvm::opt::Arg *arg = args_.getLastArg(id); if (arg != nullptr) { @@ -167,7 +164,7 @@ llvm::errs() << progname_ << ": invalid argument '" << arg->getValue() << "' to '" << arg->getAsString(args_) << "' option\n"; - return llvm::None; + return {}; } } return result;
diff --git a/driver/GollvmOptions.cpp b/driver/GollvmOptions.cpp index 4455b1a..d8697e9 100644 --- a/driver/GollvmOptions.cpp +++ b/driver/GollvmOptions.cpp
@@ -20,23 +20,35 @@ #include "GollvmOptions.inc" #undef PREFIX +#define OPTTABLE_STR_TABLE_CODE +#include "GollvmOptions.inc" +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_VALUES_CODE +#include "GollvmOptions.inc" +#undef OPTTABLE_VALUES_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "GollvmOptions.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE + +#define OPTTABLE_PREFIXES_UNION_CODE +#include "GollvmOptions.inc" +#undef OPTTABLE_PREFIXES_UNION_CODE + static const OptTable::Info InfoTable[] = { -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR, VALUES) \ - {PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, \ - PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUES}, +#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), #include "GollvmOptions.inc" #undef OPTION }; namespace { - -class DriverOptTable : public OptTable { +class DriverOptTable : public PrecomputedOptTable { public: DriverOptTable() - : OptTable(InfoTable) {} + : PrecomputedOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + OptionPrefixesUnion) {} }; - } std::unique_ptr<OptTable> createGollvmDriverOptTable() {
diff --git a/driver/GollvmOptions.h b/driver/GollvmOptions.h index 5ab4477..2a98647 100644 --- a/driver/GollvmOptions.h +++ b/driver/GollvmOptions.h
@@ -9,6 +9,7 @@ #ifndef LLVM_GOLLVM_DRIVER_GOLLVMOPTIONS_H #define LLVM_GOLLVM_DRIVER_GOLLVMOPTIONS_H +#include "llvm/Option/OptTable.h" #include <memory> namespace llvm { @@ -31,9 +32,7 @@ enum ID { OPT_INVALID = 0, // This is not an option ID. -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR, VALUES) \ - OPT_##ID, +#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__), #include "GollvmOptions.inc" LastOption #undef OPTION
diff --git a/driver/GollvmOptions.td b/driver/GollvmOptions.td index 404a1ad..18e0e99 100644 --- a/driver/GollvmOptions.td +++ b/driver/GollvmOptions.td
@@ -275,6 +275,26 @@ def fno_slp_vectorize : Flag<["-"], "fno-slp-vectorize">, Group<f_Group>, HelpText<"Disable the superword-level parallelism vectorization passes">; +def fmerge_functions : Flag<["-"], "fmerge-functions">, Group<f_Group>, + HelpText<"Enable merging identical functions">; +def fno_merge_functions : Flag<["-"], "fno-merge-functions">, Group<f_Group>, + HelpText<"Disable merging identical functions">; + +def funroll_loops : Flag<["-"], "funroll-loops">, Group<f_Group>, + HelpText<"Enable loop unrolling">; +def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group<f_Group>, + HelpText<"Disable loop unrolling">; + +def finterleave_loops : Flag<["-"], "finterleave-loops">, Group<f_Group>, + HelpText<"Enable loop interleaving">; +def fno_interleave_loops : Flag<["-"], "fno-interleave-loops">, Group<f_Group>, + HelpText<"Disable loop interleaving">; + +def fcg_profile : Flag<["-"], "fcg-profile">, Group<f_Group>, + HelpText<"Enable linker re-ordering functions by CG profile (supported by LLD)">; +def fno_cg_profile : Flag<["-"], "fno-cg-profile">, Group<f_Group>, + HelpText<"Disable linker re-ordering functions by CG profile">; + def ffp_contract_EQ : Joined<["-"], "ffp-contract=">, Group<f_Group>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)" " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">, @@ -443,9 +463,6 @@ def finline_functions : Flag<["-"], "finline-functions">, Flags<[Ignored]>, HelpText<"This option is ignored">; -def funroll_loops : Flag<["-"], "funroll-loops">, - Flags<[Ignored]>, HelpText<"This option is ignored">; - def pedantic_errors : Flag<["-"], "pedantic-errors">, Flags<[Ignored]>, HelpText<"This option is ignored">; @@ -519,3 +536,9 @@ def enable_gc_EQ : Joined<["-"], "enable-gc=">, HelpText<"Enable stack map generation">; + +def fdebug_pass_manager : Flag<["-"], "fdebug-pass-manager">, + HelpText<"Print passes run and other information for debugging the pass manager">; + +def fverify_each : Flag<["-"], "fverify-each">, + HelpText<"Run verification after each pass in new pass manager">;
diff --git a/driver/IntegAssembler.cpp b/driver/IntegAssembler.cpp index a40be9f..0cdea73 100644 --- a/driver/IntegAssembler.cpp +++ b/driver/IntegAssembler.cpp
@@ -27,7 +27,6 @@ #include "Driver.h" #include "ToolChain.h" -#include "llvm/ADT/Triple.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/LLVMContext.h" #include "llvm/MC/MCAsmBackend.h" @@ -52,7 +51,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" @@ -63,6 +61,8 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/Host.h" +#include "llvm/TargetParser/Triple.h" #include <sstream> @@ -194,7 +194,7 @@ // Ensure MCAsmInfo initialization occurs before any use, otherwise sections // may be created with a combination of default and explicit settings. - MAI->setCompressDebugSections(CompressDebugSections); + MCOptions.CompressDebugSections = CompressDebugSections; // Build up the feature string from the target feature list. std::string FS; @@ -242,8 +242,7 @@ Out = BOS.get(); } - std::unique_ptr<MCCodeEmitter> CE( - TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); + std::unique_ptr<MCCodeEmitter> CE(TheTarget->createMCCodeEmitter(*MCII, Ctx)); std::unique_ptr<MCAsmBackend> MAB( TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); std::unique_ptr<MCObjectWriter> OW = MAB->createObjectWriter(*Out);
diff --git a/driver/LinuxToolChain.cpp b/driver/LinuxToolChain.cpp index a12b794..f8ebea7 100644 --- a/driver/LinuxToolChain.cpp +++ b/driver/LinuxToolChain.cpp
@@ -101,7 +101,7 @@ Tool *Linux::buildCompiler() { llvm::opt::Arg *xarg = driver().args().getLastArg(gollvm::options::OPT_x); - if (xarg != nullptr && llvm::StringRef(xarg->getValue()).equals("c")) { + if (xarg != nullptr && xarg->containsValue("c")) { // This is a dummy C compile. return new DummyCompileC(*this, driver().executablePath()); }
diff --git a/driver/Tool.h b/driver/Tool.h index abde3ca..17d3b19 100644 --- a/driver/Tool.h +++ b/driver/Tool.h
@@ -13,9 +13,9 @@ #ifndef GOLLVM_DRIVER_TOOL_H #define GOLLVM_DRIVER_TOOL_H -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" #include "Artifact.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/TargetParser/Triple.h" namespace gollvm { namespace driver {
diff --git a/driver/ToolChain.h b/driver/ToolChain.h index c20e14b..89a28df 100644 --- a/driver/ToolChain.h +++ b/driver/ToolChain.h
@@ -13,9 +13,9 @@ #ifndef GOLLVM_DRIVER_TOOLCHAIN_H #define GOLLVM_DRIVER_TOOLCHAIN_H -#include <string> -#include "llvm/ADT/Triple.h" #include "llvm/Option/ArgList.h" +#include "llvm/TargetParser/Triple.h" +#include <string> #include "Action.h" #include "Tool.h"
diff --git a/libgo/godumpspec/godumpspec.cpp b/libgo/godumpspec/godumpspec.cpp index 37a854d..15a66d2 100644 --- a/libgo/godumpspec/godumpspec.cpp +++ b/libgo/godumpspec/godumpspec.cpp
@@ -26,6 +26,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h"
diff --git a/passes/GC.cpp b/passes/GC.cpp index 3932bab..e5dd0bc 100644 --- a/passes/GC.cpp +++ b/passes/GC.cpp
@@ -44,7 +44,7 @@ // TODO: write barrier? } - Optional<bool> isGCManagedPointer(const Type *Ty) const override { + std::optional<bool> isGCManagedPointer(const Type *Ty) const override { return isa<PointerType>(Ty); } }; @@ -171,7 +171,7 @@ for (uint8_t Byte : V) OS.emitIntValue(Byte, 1); } - OS.emitValueToAlignment(8); + OS.emitValueToAlignment(llvm::Align(8)); } } @@ -183,7 +183,7 @@ // Create the section. MCSection *StackMapSection = OutContext.getObjectFileInfo()->getStackMapSection(); - OS.SwitchSection(StackMapSection); + OS.switchSection(StackMapSection); emitCallsiteEntries(SM, OS);
diff --git a/passes/GoAnnotation.cpp b/passes/GoAnnotation.cpp index 95f5fe3..d180248 100644 --- a/passes/GoAnnotation.cpp +++ b/passes/GoAnnotation.cpp
@@ -19,6 +19,7 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/IR/Module.h" #include "llvm/PassRegistry.h" #include "llvm/Target/TargetMachine.h"
diff --git a/passes/GoNilChecks.cpp b/passes/GoNilChecks.cpp index 7561d65..e091699 100644 --- a/passes/GoNilChecks.cpp +++ b/passes/GoNilChecks.cpp
@@ -25,8 +25,6 @@ #include "GollvmPasses.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" @@ -102,11 +100,11 @@ /// If non-None, then an instruction in \p Insts that also must be /// hoisted. - Optional<ArrayRef<MachineInstr *>::iterator> PotentialDependence; + std::optional<ArrayRef<MachineInstr *>::iterator> PotentialDependence; /*implicit*/ DependenceResult( bool CanReorder, - Optional<ArrayRef<MachineInstr *>::iterator> PotentialDependence) + std::optional<ArrayRef<MachineInstr *>::iterator> PotentialDependence) : CanReorder(CanReorder), PotentialDependence(PotentialDependence) { assert((!PotentialDependence || CanReorder) && "!CanReorder && PotentialDependence.hasValue() not allowed!"); @@ -252,18 +250,18 @@ assert(llvm::all_of(Block, canHandle) && "Check this first!"); assert(!is_contained(Block, MI) && "Block must be exclusive of MI!"); - Optional<ArrayRef<MachineInstr *>::iterator> Dep; + std::optional<ArrayRef<MachineInstr *>::iterator> Dep; for (auto I = Block.begin(), E = Block.end(); I != E; ++I) { if (canReorder(*I, MI)) continue; - if (Dep == None) { + if (!Dep.has_value()) { // Found one possible dependency, keep track of it. Dep = I; } else { // We found two dependencies, so bail out. - return {false, None}; + return {false, {}}; } } @@ -654,7 +652,7 @@ // Insert an *unconditional* branch to not-null successor. if (!CheckBB->isLayoutSuccessor(NC.getNotNullSucc())) TII->insertBranch(*CheckBB, NC.getNotNullSucc(), nullptr, - /*Cond=*/None, DL); + /*Cond=*/{}, DL); NumImplicitNullChecks++; @@ -724,7 +722,7 @@ MI.eraseFromParent(); break; } - TII->insertBranch(*FaultBB, PadBB, nullptr, None, DL); + TII->insertBranch(*FaultBB, PadBB, nullptr, {}, DL); } // Add EH labels before and after the faulting op.
diff --git a/passes/GoSafeGetg.cpp b/passes/GoSafeGetg.cpp index 52b54c2..66dbedd 100644 --- a/passes/GoSafeGetg.cpp +++ b/passes/GoSafeGetg.cpp
@@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "GoSafeGetg.h" #include "GollvmPasses.h" #include "llvm/IR/BasicBlock.h" @@ -76,8 +77,7 @@ // found, replace it with a call of runtime.getg (i.e. undoing the // inlining). // -bool -GoSafeGetg::runOnModule(Module &M) { +static bool updateModule(Module &M) { GlobalVariable *GV = M.getGlobalVariable("runtime.g"); if (!GV) return false; // no access of g, nothing to do @@ -132,3 +132,12 @@ return Changed; } + +bool GoSafeGetg::runOnModule(Module &M) { return updateModule(M); } + +PreservedAnalyses GoSafeGetgPass::run(Module &M, ModuleAnalysisManager &AM) { + bool Changed = updateModule(M); + if (!Changed) + return PreservedAnalyses::all(); + return PreservedAnalyses::none(); +}
diff --git a/passes/GoSafeGetg.h b/passes/GoSafeGetg.h new file mode 100644 index 0000000..89e9d23 --- /dev/null +++ b/passes/GoSafeGetg.h
@@ -0,0 +1,26 @@ +//===--- GoSafeGetg.h -----------------------------------------------------===// +// +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +//===----------------------------------------------------------------------===// +// +// Make sure the TLS address is not cached across a thread switch. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GOLLVM_PASSES_GOSAFEGETG_H +#define LLVM_GOLLVM_PASSES_GOSAFEGETG_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +struct GoSafeGetgPass : public PassInfoMixin<GoSafeGetgPass> { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // namespace llvm + +#endif // LLVM_GOLLVM_PASSES_GOSAFEGETG_H
diff --git a/passes/GoStatepoints.cpp b/passes/GoStatepoints.cpp index 6453db4..02062f6 100644 --- a/passes/GoStatepoints.cpp +++ b/passes/GoStatepoints.cpp
@@ -22,8 +22,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallSet.h" @@ -34,6 +32,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Argument.h" +#include "llvm/IR/AttributeMask.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constant.h" @@ -58,8 +57,8 @@ #include "llvm/IR/User.h" #include "llvm/IR/Value.h" #include "llvm/IR/ValueHandle.h" -#include "llvm/Pass.h" #include "llvm/InitializePasses.h" +#include "llvm/Pass.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" @@ -120,6 +119,32 @@ static bool shouldRewriteStatepointsIn(Function &F); +static Type *getPointerElementType(Value *V) { + assert(V->getType()->isPointerTy()); + if (Argument *A = dyn_cast<Argument>(V)) { + if (A->hasByValAttr()) + return A->getParamByValType(); + // FIXME: Do we need to handle other types of arguments? + // fallback to ptr + return V->getType(); + + } else if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) { + return AI->getAllocatedType(); + } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(V)) { + return GEP->getResultElementType(); + } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { + auto *Inst = CE->getAsInstruction(); + Type *ITy = getPointerElementType(CE->getAsInstruction()); + Inst->deleteValue(); + return ITy; + } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) { + return GV->getValueType(); + } else { + // fallback to ptr + return V->getType(); + } +} + PreservedAnalyses GoStatepoints::run(Module &M, ModuleAnalysisManager &AM) { // Create a sentinel global variable for stack maps. @@ -993,8 +1018,9 @@ // TODO: In many cases, the new instruction is just EE itself. We should // exploit this, but can't do it here since it would break the invariant // about the BDV not being known to be a base. - auto *BaseInst = ExtractElementInst::Create( - State.getBaseValue(), EE->getIndexOperand(), "base_ee", EE); + auto *BaseInst = ExtractElementInst::Create(State.getBaseValue(), + EE->getIndexOperand(), + "base_ee", EE->getIterator()); BaseInst->setMetadata("is_base_value", MDNode::get(I->getContext(), {})); States[I] = BDVState(BDVState::Base, BaseInst); } @@ -1015,29 +1041,30 @@ int NumPreds = pred_size(BB); assert(NumPreds > 0 && "how did we reach here"); std::string Name = suffixed_name_or(I, ".base", "base_phi"); - return PHINode::Create(I->getType(), NumPreds, Name, I); + return PHINode::Create(I->getType(), NumPreds, Name, I->getIterator()); } else if (SelectInst *SI = dyn_cast<SelectInst>(I)) { // The undef will be replaced later UndefValue *Undef = UndefValue::get(SI->getType()); std::string Name = suffixed_name_or(I, ".base", "base_select"); - return SelectInst::Create(SI->getCondition(), Undef, Undef, Name, SI); + return SelectInst::Create(SI->getCondition(), Undef, Undef, Name, + SI->getIterator()); } else if (auto *EE = dyn_cast<ExtractElementInst>(I)) { UndefValue *Undef = UndefValue::get(EE->getVectorOperand()->getType()); std::string Name = suffixed_name_or(I, ".base", "base_ee"); return ExtractElementInst::Create(Undef, EE->getIndexOperand(), Name, - EE); + EE->getIterator()); } else if (auto *IE = dyn_cast<InsertElementInst>(I)) { UndefValue *VecUndef = UndefValue::get(IE->getOperand(0)->getType()); UndefValue *ScalarUndef = UndefValue::get(IE->getOperand(1)->getType()); std::string Name = suffixed_name_or(I, ".base", "base_ie"); - return InsertElementInst::Create(VecUndef, ScalarUndef, - IE->getOperand(2), Name, IE); + return InsertElementInst::Create( + VecUndef, ScalarUndef, IE->getOperand(2), Name, IE->getIterator()); } else { auto *SV = cast<ShuffleVectorInst>(I); UndefValue *VecUndef = UndefValue::get(SV->getOperand(0)->getType()); std::string Name = suffixed_name_or(I, ".base", "base_sv"); return new ShuffleVectorInst(VecUndef, VecUndef, SV->getOperand(2), - Name, SV); + Name, SV->getIterator()); } }; Instruction *BaseInst = MakeBaseInstPlaceholder(I); @@ -1067,7 +1094,8 @@ assert(Base && "Can't be null"); // The cast is needed since base traversal may strip away bitcasts if (Base->getType() != Input->getType() && InsertPt) - Base = CastInst::CreatePointerBitCastOrAddrSpaceCast(Base, Input->getType(), "cast", InsertPt); + Base = CastInst::CreatePointerBitCastOrAddrSpaceCast( + Base, Input->getType(), "cast", InsertPt->getIterator()); return Base; }; @@ -1262,8 +1290,6 @@ // both function declarations and call sites. static constexpr Attribute::AttrKind FnAttrsToStrip[] = {Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly, - Attribute::ArgMemOnly, Attribute::InaccessibleMemOnly, - Attribute::InaccessibleMemOrArgMemOnly, Attribute::NoSync, Attribute::NoFree}; // List of all parameter and return attributes which must be stripped when @@ -1356,7 +1382,7 @@ // Note: we've inserted instructions, so the call to llvm.deoptimize may // not necessarily be followed by the matching return. auto *RI = cast<ReturnInst>(OldI->getParent()->getTerminator()); - new UnreachableInst(RI->getContext(), RI); + new UnreachableInst(RI->getContext(), RI->getIterator()); RI->eraseFromParent(); } @@ -1430,7 +1456,7 @@ if (isa<AllocaInst>(V) || (isa<Argument>(V) && cast<Argument>(V)->hasByValAttr())) { // Byval argument is at a fixed frame offset. Treat it the same as alloca. - Type *T = cast<PointerType>(V->getType())->getElementType(); + Type *T = getPointerElementType(V); if (hasPointer(T)) { PtrFields.push_back(V); getPtrBitmapForType(T, DL, PtrFields); @@ -1627,8 +1653,9 @@ SetVector<Value *> AllAllocas; if (ClobberNonLive) for (Instruction &I : F.getEntryBlock()) - if (isa<AllocaInst>(I) && hasPointer(I.getType()->getPointerElementType())) - AllAllocas.insert(&I); + if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) + if (hasPointer(AI->getAllocatedType())) + AllAllocas.insert(&I); computeLiveInValues(DT, F, OriginalLivenessData, AddrTakenAllocas, ToZero, BadLoads, DVCache); @@ -1702,7 +1729,7 @@ } else if (ToZero.count(V) != 0) { // Non-addrtaken alloca. Just insert zeroing, keep the lifetime marker. IRBuilder<> Builder(I.getNextNode()); - Value *Zero = Constant::getNullValue(V->getType()->getPointerElementType()); + Value *Zero = Constant::getNullValue(getPointerElementType(V)); Builder.CreateStore(Zero, V); // Don't remove V from ToZero for now, as there may be multiple // lifetime start markers, where we need to insert zeroing. @@ -1737,14 +1764,14 @@ for (Instruction &I : F.getEntryBlock()) if (ToZero.count(&I) != 0) { IRBuilder<> Builder(I.getNextNode()); - Type *ElemTyp = I.getType()->getPointerElementType(); if (AddrTakenAllocas.count(&I) != 0) { + Type *ElemTyp = cast<AllocaInst>(I).getAllocatedType(); // For addrtaken alloca, we removed the lifetime marker above. // Insert a new one at the entry block. unsigned Size = DL.getTypeStoreSize(ElemTyp); Builder.CreateLifetimeStart(&I, ConstantInt::get(Int64Ty, Size)); } - Value *Zero = Constant::getNullValue(ElemTyp); + Value *Zero = Constant::getNullValue(getPointerElementType(&I)); Builder.CreateStore(Zero, &I); ToZero.remove(&I); } @@ -1942,8 +1969,8 @@ // That Value* no longer exists and we need to use the new gc_result. // Thankfully, the live set is embedded in the statepoint (and updated), so // we just grab that. - Live.insert(Live.end(), Info.StatepointToken->gc_args_begin(), - Info.StatepointToken->gc_args_end()); + Live.insert(Live.end(), Info.StatepointToken->gc_live_begin(), + Info.StatepointToken->gc_live_end()); #ifndef NDEBUG // Do some basic sanity checks on our liveness results before performing // relocation. Relocation can and will turn mistakes in liveness results @@ -1951,7 +1978,7 @@ // TODO: It would be nice to test consistency as well assert(DT.isReachableFromEntry(Info.StatepointToken->getParent()) && "statepoint must be reachable or liveness is meaningless"); - for (Value *V : Info.StatepointToken->gc_args()) { + for (Value *V : Info.StatepointToken->gc_live()) { if (!isa<Instruction>(V)) // Non-instruction values trivial dominate all possible uses continue; @@ -2024,7 +2051,7 @@ if (isa<PointerType>(F.getReturnType())) RemoveNonValidAttrAtIndex(Ctx, F, AttributeList::ReturnIndex); - for (auto Attr : FnAttrsToStrip) + for (auto Attr : FnAttrsToStrip) F.removeFnAttr(Attr); } @@ -2161,11 +2188,12 @@ // Create a dummy landing pad block. LLVMContext &C = F.getContext(); BasicBlock *PadBB = BasicBlock::Create(C, "dummy", &F); - Type *ExnTy = StructType::get(Type::getInt8PtrTy(C), Type::getInt32Ty(C)); + Type *ExnTy = + StructType::get(PointerType::getUnqual(C), Type::getInt32Ty(C)); LandingPadInst *LPad = LandingPadInst::Create(ExnTy, 1, "dummy.ex", PadBB); - LPad->addClause(Constant::getNullValue(Type::getInt8PtrTy(C))); + LPad->addClause(Constant::getNullValue(PointerType::getUnqual(C))); new UnreachableInst(PadBB->getContext(), PadBB); BasicBlock *Old = CI->getParent(); @@ -2179,7 +2207,7 @@ for (DomTreeNode *I : Children) DT.changeImmediateDominator(I, NewNode); - DTU.insertEdge(Old, PadBB); + DTU.applyUpdates({{DominatorTree::Insert, Old, PadBB}}); } } @@ -2269,10 +2297,11 @@ static Value* isTrackedAlloca(Value *V, DefiningValueMapTy &DVCache) { - Value *Base = isAlloca(V, DVCache); - if (Base && - hasPointer(Base->getType()->getPointerElementType())) - return Base; + if (Value *Base = isAlloca(V, DVCache)) { + Type *AllocedTy = cast<AllocaInst>(Base)->getAllocatedType(); + if (Base && hasPointer(AllocedTy)) + return Base; + } return nullptr; } @@ -2450,7 +2479,7 @@ // Use the metadata inserted by the FE. for (Instruction &I : F.getEntryBlock()) if (isa<AllocaInst>(I) && I.getMetadata("go_addrtaken") && - hasPointer(I.getType()->getPointerElementType())) + hasPointer(cast<AllocaInst>(I).getAllocatedType())) AddrTakenAllocas.insert(&I); // The FE's addrtaken mark may be imprecise. Look for certain @@ -2581,7 +2610,7 @@ SetVector<Value *> &ToZero, DefiningValueMapTy &DVCache) { unsigned PtrSize = DL.getPointerSize(); - unsigned Size = DL.getTypeStoreSize(V->getType()->getPointerElementType()); + unsigned Size = DL.getTypeStoreSize(cast<AllocaInst>(V)->getAllocatedType()); if (Size <= PtrSize) return; @@ -2597,7 +2626,8 @@ if (hasStructRetAttr(CI)) { Value *Ptr = CI->getOperand(0); if (isTrackedAlloca(Ptr, DVCache) == V) - StoreSize += DL.getTypeStoreSize(Ptr->getType()->getPointerElementType()); + StoreSize += + DL.getTypeStoreSize(cast<AllocaInst>(Ptr)->getAllocatedType()); } if (Function *Fn = CI->getCalledFunction()) switch (Fn->getIntrinsicID()) { @@ -2621,7 +2651,9 @@ if (hasStructRetAttr(II)) { Value *Ptr = II->getOperand(0); if (isTrackedAlloca(Ptr, DVCache) == V) - if (DL.getTypeStoreSize(Ptr->getType()->getPointerElementType()) + PtrSize - 1 >= Size) + if (DL.getTypeStoreSize(cast<AllocaInst>(Ptr)->getAllocatedType()) + + PtrSize - 1 >= + Size) // We are storing the whole type return; @@ -2919,8 +2951,8 @@ Value *V = Ptr->stripPointerCasts(); const DataLayout &DL = Inst->getModule()->getDataLayout(); if (!Data.LiveIn[BB].count(V) && - (DL.getTypeStoreSize(Ptr->getType()->getPointerElementType()) >= - DL.getTypeStoreSize(V->getType()->getPointerElementType()))) + (DL.getTypeStoreSize(getPointerElementType(Ptr)) >= + DL.getTypeStoreSize(getPointerElementType(V)))) LiveOut.remove(V); } @@ -2935,7 +2967,7 @@ Value *Bad = ConstantInt::get(Int8Ty, 0xff); for (Value *Alloca : ToClobber) { unsigned Siz = - DL.getTypeStoreSize(Alloca->getType()->getPointerElementType()); + DL.getTypeStoreSize(cast<AllocaInst>(Alloca)->getAllocatedType()); Builder.CreateMemSet(Alloca, Bad, Siz, MaybeAlign(0)); //dbgs() << "clobber " << *Alloca << " at " << *Inst << "\n"; } @@ -2962,7 +2994,7 @@ for (Instruction &I : instructions(F)) { if (auto *CI = dyn_cast<CallInst>(&I)) if (Function *Callee = CI->getCalledFunction()) { - if (Callee->getName().equals("runtime.gcWriteBarrier")) { + if (Callee->getName() == "runtime.gcWriteBarrier") { // gcWriteBarrier(dst, val) // there is an extra "nest" argument. Value *Dst = CI->getArgOperand(1), *Val = CI->getArgOperand(2); @@ -2974,7 +3006,7 @@ PointerType::get(Val->getType(), AS)); Builder.CreateStore(Val, Dst); ToDel.insert(CI); - } else if (Callee->getName().equals("runtime.typedmemmove")) { + } else if (Callee->getName() == "runtime.typedmemmove") { // typedmemmove(typ, dst, src) // there is an extra "nest" argument. Value *Dst = CI->getArgOperand(2), *Src = CI->getArgOperand(3); @@ -2986,7 +3018,7 @@ // for now. The size is the first field. The optimizer should be // able to constant-fold it. Value *TD = CI->getArgOperand(1); - Type *etyp = TD->getType()->getPointerElementType(); + Type *etyp = cast<GlobalValue>(TD)->getValueType(); Value *GEP = Builder.CreateConstInBoundsGEP2_32( etyp, TD, 0, 0); Value *Siz = Builder.CreateLoad(etyp, GEP);
diff --git a/passes/GollvmPasses.h b/passes/GollvmPasses.h index 398df82..d1900a4 100644 --- a/passes/GollvmPasses.h +++ b/passes/GollvmPasses.h
@@ -11,6 +11,10 @@ #include "llvm/ADT/SmallVector.h" +#include "GoSafeGetg.h" +#include "GoStatepoints.h" +#include "RemoveAddrSpace.h" + namespace llvm { class DataLayout; @@ -25,14 +29,14 @@ void initializeGoSafeGetgPass(PassRegistry&); void initializeGoStatepointsLegacyPassPass(PassRegistry&); void initializeGoWrappersPass(PassRegistry&); -void initializeRemoveAddrSpacePassPass(PassRegistry&); +void initializeRemoveAddrSpaceWrapperPass(PassRegistry&); FunctionPass *createGoAnnotationPass(); FunctionPass *createGoNilChecksPass(); ModulePass *createGoSafeGetgPass(); ModulePass *createGoStatepointsLegacyPass(); FunctionPass *createGoWrappersPass(); -ModulePass *createRemoveAddrSpacePass(const DataLayout&); +ModulePass *createRemoveAddrSpaceWrapper(const DataLayout&); void linkGoGC(); void linkGoGCPrinter();
diff --git a/passes/RemoveAddrSpace.cpp b/passes/RemoveAddrSpace.cpp index e31e9ac..085db3d 100644 --- a/passes/RemoveAddrSpace.cpp +++ b/passes/RemoveAddrSpace.cpp
@@ -1,4 +1,4 @@ -//===--- GoStackMap.cpp ---------------------------------------------------===// +//===--- RemoveAddrSpace.cpp ----------------------------------------------===// // // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "RemoveAddrSpace.h" #include "GollvmPasses.h" #include "llvm/ADT/DenseSet.h" @@ -27,21 +28,8 @@ namespace { -class RemoveAddrSpacePass : public ModulePass { - public: - static char ID; - - RemoveAddrSpacePass() : ModulePass(ID), DL("") {} - - RemoveAddrSpacePass(const DataLayout &DL) : ModulePass(ID), DL(DL) { - initializeRemoveAddrSpacePassPass( - *PassRegistry::getPassRegistry()); - } - - bool runOnModule(Module &M) override; - - private: - Type *IntTy; // type of uintptr_t, used to cast pointer to/from integer +class RemoveAddrSpace { + Type *IntTy {nullptr}; // type of uintptr_t, used to cast pointer to/from integer DataLayout DL; // data layout without non-integral pointer, passed in from the driver DenseSet<Constant*> Visited; // handle circular references @@ -49,20 +37,44 @@ // of ptr-to-int and int-to-ptr casts, as codegen cannot handle // addrspacecast in static initializer. void removeAddrSpaceCast(Constant *C); + +public: + RemoveAddrSpace(const DataLayout &DL) : DL(DL) {} + bool runOnModule(Module &M); +}; + + +class RemoveAddrSpaceWrapper : public ModulePass { + DataLayout DL; + + public: + static char ID; + + RemoveAddrSpaceWrapper() : ModulePass(ID), DL("") {} + + RemoveAddrSpaceWrapper(const DataLayout &DL) : ModulePass(ID), DL(DL) { + initializeRemoveAddrSpaceWrapperPass( + *PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override { + RemoveAddrSpace R(DL); + return R.runOnModule(M); + } }; } // namespace -char RemoveAddrSpacePass::ID = 0; -INITIALIZE_PASS(RemoveAddrSpacePass, "remove-addrspacecast", +char RemoveAddrSpaceWrapper::ID = 0; +INITIALIZE_PASS(RemoveAddrSpaceWrapper, "remove-addrspacecast", "Remove addrspacecast instructions", false, false) -ModulePass *llvm::createRemoveAddrSpacePass(const DataLayout &DL) { - return new RemoveAddrSpacePass(DL); +ModulePass *llvm::createRemoveAddrSpaceWrapper(const DataLayout &DL) { + return new RemoveAddrSpaceWrapper(DL); } void -RemoveAddrSpacePass::removeAddrSpaceCast(Constant *C) { +RemoveAddrSpace::removeAddrSpaceCast(Constant *C) { if (Visited.count(C)) return; Visited.insert(C); @@ -86,7 +98,7 @@ } bool -RemoveAddrSpacePass::runOnModule(Module &M) { +RemoveAddrSpace::runOnModule(Module &M) { // At this point we no longer need non-integral pointers. // Set data layout back to default. M.setDataLayout(DL); @@ -97,3 +109,10 @@ removeAddrSpaceCast(GV.getInitializer()); return true; } + +PreservedAnalyses llvm::RemoveAddrSpacePass::run(Module &M, + ModuleAnalysisManager &AM) { + RemoveAddrSpace R(DL); + R.runOnModule(M); + return PreservedAnalyses::all(); +}
diff --git a/passes/RemoveAddrSpace.h b/passes/RemoveAddrSpace.h new file mode 100644 index 0000000..e994139 --- /dev/null +++ b/passes/RemoveAddrSpace.h
@@ -0,0 +1,36 @@ +//===--- RemoveAddrSpace.h ------------------------------------------------===// +// +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +//===----------------------------------------------------------------------===// +// +// LLVM backend pass to remove addrspacecast instructions +// in static initializers (because codegen cannot handle +// them). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GOLLVM_PASSES_REMOVEADDRSPACE_H +#define LLVM_GOLLVM_PASSES_REMOVEADDRSPACE_H + +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class RemoveAddrSpacePass : public PassInfoMixin<RemoveAddrSpacePass> { + DataLayout DL; // data layout without non-integral pointer + +public: + /// Construct a pass with update data layout optional optmizations. + RemoveAddrSpacePass(const DataLayout &DL) : DL(DL) {} + + /// Run the pass over the module. + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // namespace llvm + +#endif // LLVM_GOLLVM_PASSES_REMOVEADDRSPACE_H
diff --git a/passes/Util.cpp b/passes/Util.cpp index 08b3ddb..00bc3bd 100644 --- a/passes/Util.cpp +++ b/passes/Util.cpp
@@ -61,7 +61,7 @@ for (unsigned i = 0, n = T->getArrayNumElements(); i < n; ++i) { Value *ivals[2] = { ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, i) }; - ArrayRef<Value*> Idx = makeArrayRef(ivals, 2); + ArrayRef<Value *> Idx(ivals, 2); uint64_t Offset = DL.getIndexedOffsetInType(T, Idx); getPtrBitmapForTypeHelper(ET, DL, BaseOffset+Offset, BV); } @@ -73,7 +73,7 @@ for (unsigned i = 0, n = VT->getNumElements(); i < n; ++i) { Value *ivals[2] = { ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, i) }; - ArrayRef<Value*> Idx = makeArrayRef(ivals, 2); + ArrayRef<Value *> Idx(ivals, 2); uint64_t Offset = DL.getIndexedOffsetInType(T, Idx); getPtrBitmapForTypeHelper(ET, DL, BaseOffset+Offset, BV); } @@ -86,7 +86,7 @@ continue; Value *ivals[2] = { ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, i) }; - ArrayRef<Value*> Idx = makeArrayRef(ivals, 2); + ArrayRef<Value *> Idx(ivals, 2); uint64_t Offset = DL.getIndexedOffsetInType(T, Idx); getPtrBitmapForTypeHelper(ET, DL, BaseOffset+Offset, BV); }
diff --git a/unittests/BackendCore/BackendArrayStruct.cpp b/unittests/BackendCore/BackendArrayStruct.cpp index a488338..4fd7244 100644 --- a/unittests/BackendCore/BackendArrayStruct.cpp +++ b/unittests/BackendCore/BackendArrayStruct.cpp
@@ -79,19 +79,18 @@ h.mkAssign(bfex2, bc2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast { i8*, i32 }* %loc1 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ({ i8*, i32 }* @const.0 to i8*), i64 16, i1 false) - store { i8*, i32 }* %loc1, { i8*, i32 }** %loc2, align 8 - store i32 0, i32* %x, align 4 - %field.0 = getelementptr inbounds { i8*, i32 }, { i8*, i32 }* %loc1, i32 0, i32 1 - %loc1.field.ld.0 = load i32, i32* %field.0, align 4 - store i32 %loc1.field.ld.0, i32* %x, align 4 - store i8 0, i8* %b2, align 1 - %field.1 = getelementptr inbounds { i8*, i32 }, { i8*, i32 }* %loc1, i32 0, i32 0 - store i8* %b2, i8** %field.1, align 8 - %loc2.ld.0 = load { i8*, i32 }*, { i8*, i32 }** %loc2, align 8 - %field.2 = getelementptr inbounds { i8*, i32 }, { i8*, i32 }* %loc2.ld.0, i32 0, i32 1 - store i32 2, i32* %field.2, align 4 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %loc1, ptr align 8 @const.0, i64 16, i1 false) + store ptr %loc1, ptr %loc2, align 8 + store i32 0, ptr %x, align 4 + %field.0 = getelementptr inbounds { ptr, i32 }, ptr %loc1, i32 0, i32 1 + %loc1.field.ld.0 = load i32, ptr %field.0, align 4 + store i32 %loc1.field.ld.0, ptr %x, align 4 + store i8 0, ptr %b2, align 1 + %field.1 = getelementptr inbounds { ptr, i32 }, ptr %loc1, i32 0, i32 0 + store ptr %b2, ptr %field.1, align 8 + %loc2.ld.0 = load ptr, ptr %loc2, align 8 + %field.2 = getelementptr inbounds { ptr, i32 }, ptr %loc2.ld.0, i32 0, i32 1 + store i32 2, ptr %field.2, align 4 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -145,24 +144,24 @@ h.mkAssign(vex2, fex2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { + define void @foo(ptr nest %nest.0) #0 { entry: - %tmp.0 = alloca { i8*, i32 }, align 8 + %tmp.0 = alloca { ptr, i32 }, align 8 %x = alloca i32, align 4 %y = alloca i32, align 4 %z = alloca i32, align 4 - store i32 0, i32* %x, align 4 - store i32 0, i32* %y, align 4 - %y.ld.0 = load i32, i32* %y, align 4 - %field.0 = getelementptr inbounds { i8*, i32 }, { i8*, i32 }* %tmp.0, i32 0, i32 0 - store i8* null, i8** %field.0, align 8 - %field.1 = getelementptr inbounds { i8*, i32 }, { i8*, i32 }* %tmp.0, i32 0, i32 1 - store i32 %y.ld.0, i32* %field.1, align 4 - %field.2 = getelementptr inbounds { i8*, i32 }, { i8*, i32 }* %tmp.0, i32 0, i32 1 - %.field.ld.0 = load i32, i32* %field.2, align 4 - store i32 %.field.ld.0, i32* %x, align 4 - store i32 0, i32* %z, align 4 - store i32 42, i32* %z, align 4 + store i32 0, ptr %x, align 4 + store i32 0, ptr %y, align 4 + %y.ld.0 = load i32, ptr %y, align 4 + %field.0 = getelementptr inbounds { ptr, i32 }, ptr %tmp.0, i32 0, i32 0 + store ptr null, ptr %field.0, align 8 + %field.1 = getelementptr inbounds { ptr, i32 }, ptr %tmp.0, i32 0, i32 1 + store i32 %y.ld.0, ptr %field.1, align 4 + %field.2 = getelementptr inbounds { ptr, i32 }, ptr %tmp.0, i32 0, i32 1 + %.field.ld.0 = load i32, ptr %field.2, align 4 + store i32 %.field.ld.0, ptr %x, align 4 + store i32 0, ptr %z, align 4 + store i32 42, ptr %z, align 4 ret void } )RAW_RESULT"); @@ -231,34 +230,34 @@ h.mkAssign(vex3, eex3); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { + define void @foo(ptr nest %nest.0) #0 { entry: %tmp.0 = alloca [4 x i64], align 8 %x = alloca i64, align 8 %y = alloca i64, align 8 %z = alloca i64, align 8 %w = alloca i64, align 8 - store i64 0, i64* %x, align 8 - store i64 0, i64* %y, align 8 - %y.ld.0 = load i64, i64* %y, align 8 - %index.0 = getelementptr [4 x i64], [4 x i64]* %tmp.0, i32 0, i32 0 - store i64 %y.ld.0, i64* %index.0, align 8 - %index.1 = getelementptr [4 x i64], [4 x i64]* %tmp.0, i32 0, i32 1 - store i64 3, i64* %index.1, align 8 - %index.2 = getelementptr [4 x i64], [4 x i64]* %tmp.0, i32 0, i32 2 - store i64 2, i64* %index.2, align 8 - %index.3 = getelementptr [4 x i64], [4 x i64]* %tmp.0, i32 0, i32 3 - store i64 1, i64* %index.3, align 8 - %index.4 = getelementptr [4 x i64], [4 x i64]* %tmp.0, i32 0, i32 1 - %.index.ld.0 = load i64, i64* %index.4, align 8 - store i64 %.index.ld.0, i64* %x, align 8 - store i64 0, i64* %z, align 8 - store i64 3, i64* %z, align 8 - store i64 0, i64* %w, align 8 - %x.ld.0 = load i64, i64* %x, align 8 - %index.5 = getelementptr [4 x i64], [4 x i64]* @const.0, i32 0, i64 %x.ld.0 - %.index.ld.1 = load i64, i64* %index.5, align 8 - store i64 %.index.ld.1, i64* %w, align 8 + store i64 0, ptr %x, align 8 + store i64 0, ptr %y, align 8 + %y.ld.0 = load i64, ptr %y, align 8 + %index.0 = getelementptr [4 x i64], ptr %tmp.0, i32 0, i32 0 + store i64 %y.ld.0, ptr %index.0, align 8 + %index.1 = getelementptr [4 x i64], ptr %tmp.0, i32 0, i32 1 + store i64 3, ptr %index.1, align 8 + %index.2 = getelementptr [4 x i64], ptr %tmp.0, i32 0, i32 2 + store i64 2, ptr %index.2, align 8 + %index.3 = getelementptr [4 x i64], ptr %tmp.0, i32 0, i32 3 + store i64 1, ptr %index.3, align 8 + %index.4 = getelementptr [4 x i64], ptr %tmp.0, i32 0, i32 1 + %.index.ld.0 = load i64, ptr %index.4, align 8 + store i64 %.index.ld.0, ptr %x, align 8 + store i64 0, ptr %z, align 8 + store i64 3, ptr %z, align 8 + store i64 0, ptr %w, align 8 + %x.ld.0 = load i64, ptr %x, align 8 + %index.5 = getelementptr [4 x i64], ptr @const.0, i32 0, i64 %x.ld.0 + %.index.ld.1 = load i64, ptr %index.5, align 8 + store i64 %.index.ld.1, ptr %w, align 8 ret void } )RAW_RESULT"); @@ -306,20 +305,18 @@ h.mkLocal("ac", at4, arcon3); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast [4 x i64]* %aa to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ([4 x i64]* @const.0 to i8*), i64 32, i1 false) - %cast.1 = bitcast [4 x i64]* %ab to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.1, i8* align 8 bitcast ([4 x i64]* @const.1 to i8*), i64 32, i1 false) - store i64 0, i64* %z, align 8 - %z.ld.0 = load i64, i64* %z, align 8 - %index.0 = getelementptr [4 x i64], [4 x i64]* %ac, i32 0, i32 0 - store i64 0, i64* %index.0, align 8 - %index.1 = getelementptr [4 x i64], [4 x i64]* %ac, i32 0, i32 1 - store i64 %z.ld.0, i64* %index.1, align 8 - %index.2 = getelementptr [4 x i64], [4 x i64]* %ac, i32 0, i32 2 - store i64 0, i64* %index.2, align 8 - %index.3 = getelementptr [4 x i64], [4 x i64]* %ac, i32 0, i32 3 - store i64 0, i64* %index.3, align 8 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %aa, ptr align 8 @const.0, i64 32, i1 false) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %ab, ptr align 8 @const.1, i64 32, i1 false) + store i64 0, ptr %z, align 8 + %z.ld.0 = load i64, ptr %z, align 8 + %index.0 = getelementptr [4 x i64], ptr %ac, i32 0, i32 0 + store i64 0, ptr %index.0, align 8 + %index.1 = getelementptr [4 x i64], ptr %ac, i32 0, i32 1 + store i64 %z.ld.0, ptr %index.1, align 8 + %index.2 = getelementptr [4 x i64], ptr %ac, i32 0, i32 2 + store i64 0, ptr %index.2, align 8 + %index.3 = getelementptr [4 x i64], ptr %ac, i32 0, i32 3 + store i64 0, ptr %index.3, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -367,14 +364,13 @@ h.mkLocal("loc2", s2t, scon2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast { i32*, i32 }* %loc1 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ({ i32*, i32 }* @const.0 to i8*), i64 16, i1 false) - %field.0 = getelementptr inbounds { i32*, i32 }, { i32*, i32 }* %loc1, i32 0, i32 1 - %loc1.field.ld.0 = load i32, i32* %field.0, align 4 - %field.1 = getelementptr inbounds { i32*, i32 }, { i32*, i32 }* %loc2, i32 0, i32 0 - store i32* %param1.addr, i32** %field.1, align 8 - %field.2 = getelementptr inbounds { i32*, i32 }, { i32*, i32 }* %loc2, i32 0, i32 1 - store i32 %loc1.field.ld.0, i32* %field.2, align 4 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %loc1, ptr align 8 @const.0, i64 16, i1 false) + %field.0 = getelementptr inbounds { ptr, i32 }, ptr %loc1, i32 0, i32 1 + %loc1.field.ld.0 = load i32, ptr %field.0, align 4 + %field.1 = getelementptr inbounds { ptr, i32 }, ptr %loc2, i32 0, i32 0 + store ptr %param1.addr, ptr %field.1, align 8 + %field.2 = getelementptr inbounds { ptr, i32 }, ptr %loc2, i32 0, i32 1 + store i32 %loc1.field.ld.0, ptr %field.2, align 4 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -423,18 +419,15 @@ h.mkAssign(vex, scon2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast { { i32*, i32 }, float }* %loc1 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ({ { i32*, i32 }, float }* @const.0 to i8*), i64 24, i1 false) - %field.0 = getelementptr inbounds { i32*, i32 }, { i32*, i32 }* %tmp.0, i32 0, i32 0 - store i32* %param1.addr, i32** %field.0, align 8 - %field.1 = getelementptr inbounds { i32*, i32 }, { i32*, i32 }* %tmp.0, i32 0, i32 1 - store i32 3, i32* %field.1, align 4 - %field.2 = getelementptr inbounds { { i32*, i32 }, float }, { { i32*, i32 }, float }* %loc1, i32 0, i32 0 - %cast.1 = bitcast { i32*, i32 }* %field.2 to i8* - %cast.2 = bitcast { i32*, i32 }* %tmp.0 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.1, i8* align 8 %cast.2, i64 16, i1 false) - %field.3 = getelementptr inbounds { { i32*, i32 }, float }, { { i32*, i32 }, float }* %loc1, i32 0, i32 1 - store float 3.000000e+00, float* %field.3, align 4 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %loc1, ptr align 8 @const.0, i64 24, i1 false) + %field.0 = getelementptr inbounds { ptr, i32 }, ptr %tmp.0, i32 0, i32 0 + store ptr %param1.addr, ptr %field.0, align 8 + %field.1 = getelementptr inbounds { ptr, i32 }, ptr %tmp.0, i32 0, i32 1 + store i32 3, ptr %field.1, align 4 + %field.2 = getelementptr inbounds { { ptr, i32 }, float }, ptr %loc1, i32 0, i32 0 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %field.2, ptr align 8 %tmp.0, i64 16, i1 false) + %field.3 = getelementptr inbounds { { ptr, i32 }, float }, ptr %loc1, i32 0, i32 1 + store float 3.000000e+00, ptr %field.3, align 4 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -472,12 +465,12 @@ h.mkAssign(dex, scon); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %p0.ld.0 = load { i32*, i32 }*, { i32*, i32 }** %p0.addr, align 8 - %p1.ld.0 = load i32*, i32** %p1.addr, align 8 - %field.0 = getelementptr inbounds { i32*, i32 }, { i32*, i32 }* %p0.ld.0, i32 0, i32 0 - store i32* %p1.ld.0, i32** %field.0, align 8 - %field.1 = getelementptr inbounds { i32*, i32 }, { i32*, i32 }* %p0.ld.0, i32 0, i32 1 - store i32 101, i32* %field.1, align 4 + %p0.ld.0 = load ptr, ptr %p0.addr, align 8 + %p1.ld.0 = load ptr, ptr %p1.addr, align 8 + %field.0 = getelementptr inbounds { ptr, i32 }, ptr %p0.ld.0, i32 0, i32 0 + store ptr %p1.ld.0, ptr %field.0, align 8 + %field.1 = getelementptr inbounds { ptr, i32 }, ptr %p0.ld.0, i32 0, i32 1 + store i32 101, ptr %field.1, align 4 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -521,11 +514,11 @@ h.mkLocal("t2", s1t, scon2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %x.ld.0 = load i32, i32* @x, align 4 - store i32 %x.ld.0, i32* getelementptr inbounds ({ i32 }, { i32 }* @t, i32 0, i32 0), align 4 - %t.field.ld.0 = load i32, i32* getelementptr inbounds ({ i32 }, { i32 }* @t, i32 0, i32 0), align 4 - %field.2 = getelementptr inbounds { i32 }, { i32 }* %t2, i32 0, i32 0 - store i32 %t.field.ld.0, i32* %field.2, align 4 + %x.ld.0 = load i32, ptr @x, align 4 + store i32 %x.ld.0, ptr @t, align 4 + %t.field.ld.0 = load i32, ptr @t, align 4 + %field.2 = getelementptr inbounds { i32 }, ptr %t2, i32 0, i32 0 + store i32 %t.field.ld.0, ptr %field.2, align 4 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -575,16 +568,15 @@ h.mkAssign(aa4, aa3); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast [4 x i64]* %aa to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ([4 x i64]* @const.0 to i8*), i64 32, i1 false) - %index.0 = getelementptr [4 x i64], [4 x i64]* %aa, i32 0, i32 1 - %aa.index.ld.0 = load i64, i64* %index.0, align 8 - %index.1 = getelementptr [4 x i64], [4 x i64]* %aa, i32 0, i64 %aa.index.ld.0 - %index.2 = getelementptr [4 x i64], [4 x i64]* %aa, i32 0, i64 3 - %aa.index.ld.1 = load i64, i64* %index.2, align 8 - %index.3 = getelementptr [4 x i64], [4 x i64]* %aa, i32 0, i64 %aa.index.ld.1 - %aa.index.ld.2 = load i64, i64* %index.3, align 8 - store i64 %aa.index.ld.2, i64* %index.1, align 8 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %aa, ptr align 8 @const.0, i64 32, i1 false) + %index.0 = getelementptr [4 x i64], ptr %aa, i32 0, i32 1 + %aa.index.ld.0 = load i64, ptr %index.0, align 8 + %index.1 = getelementptr [4 x i64], ptr %aa, i32 0, i64 %aa.index.ld.0 + %index.2 = getelementptr [4 x i64], ptr %aa, i32 0, i64 3 + %aa.index.ld.1 = load i64, ptr %index.2, align 8 + %index.3 = getelementptr [4 x i64], ptr %aa, i32 0, i64 %aa.index.ld.1 + %aa.index.ld.2 = load i64, ptr %index.3, align 8 + store i64 %aa.index.ld.2, ptr %index.1, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -644,15 +636,12 @@ h.mkAssign(fx, bi64five); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast [10 x { i8, [4 x { i64, i64 }*], i8 }*]* %t1 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ([10 x { i8, [4 x { i64, i64 }*], i8 }*]* @const.0 to i8*), i64 80, i1 false) - %index.0 = getelementptr [10 x { i8, [4 x { i64, i64 }*], i8 }*], [10 x { i8, [4 x { i64, i64 }*], i8 }*]* %t1, i32 0, i32 7 - %t1.index.ld.0 = load { i8, [4 x { i64, i64 }*], i8 }*, { i8, [4 x { i64, i64 }*], i8 }** %index.0, align 8 - %field.0 = getelementptr inbounds { i8, [4 x { i64, i64 }*], i8 }, { i8, [4 x { i64, i64 }*], i8 }* %t1.index.ld.0, i32 0, i32 1 - %index.1 = getelementptr [4 x { i64, i64 }*], [4 x { i64, i64 }*]* %field.0, i32 0, i32 3 - %.field.index.ld.0 = load { i64, i64 }*, { i64, i64 }** %index.1, align 8 - %field.1 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %.field.index.ld.0, i32 0, i32 0 - store i64 5, i64* %field.1, align 8 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %t1, ptr align 8 @const.0, i64 80, i1 false) + %index.0 = getelementptr [10 x ptr], ptr %t1, i32 0, i32 7 + %field.0 = getelementptr inbounds { i8, [4 x ptr], i8 }, ptr %index.0, i32 0, i32 1 + %index.1 = getelementptr [4 x ptr], ptr %field.0, i32 0, i32 3 + %field.1 = getelementptr inbounds { i64, i64 }, ptr %index.1, i32 0, i32 0 + store i64 5, ptr %field.1, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -675,14 +664,12 @@ h.mkLocal("q", bi64t, fx); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %index.2 = getelementptr [10 x { i8, [4 x { i64, i64 }*], i8 }*], [10 x { i8, [4 x { i64, i64 }*], i8 }*]* %t1, i32 0, i32 0 - %t1.index.ld.1 = load { i8, [4 x { i64, i64 }*], i8 }*, { i8, [4 x { i64, i64 }*], i8 }** %index.2, align 8 - %field.2 = getelementptr inbounds { i8, [4 x { i64, i64 }*], i8 }, { i8, [4 x { i64, i64 }*], i8 }* %t1.index.ld.1, i32 0, i32 1 - %index.3 = getelementptr [4 x { i64, i64 }*], [4 x { i64, i64 }*]* %field.2, i32 0, i32 0 - %.field.index.ld.1 = load { i64, i64 }*, { i64, i64 }** %index.3, align 8 - %field.3 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %.field.index.ld.1, i32 0, i32 1 - %.field.ld.0 = load i64, i64* %field.3, align 8 - store i64 %.field.ld.0, i64* %q, align 8 + %index.2 = getelementptr [10 x ptr], ptr %t1, i32 0, i32 0 + %field.2 = getelementptr inbounds { i8, [4 x ptr], i8 }, ptr %index.2, i32 0, i32 1 + %index.3 = getelementptr [4 x ptr], ptr %field.2, i32 0, i32 0 + %field.3 = getelementptr inbounds { i64, i64 }, ptr %index.3, i32 0, i32 1 + %.field.ld.0 = load i64, ptr %field.3, align 8 + store i64 %.field.ld.0, ptr %q, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -725,20 +712,12 @@ h.mkAssign(ve3, ve4); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast { i8* }* %x1 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ({ i8* }* @const.0 to i8*), i64 8, i1 false) - %cast.1 = bitcast { i8* }* %y1 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.1, i8* align 8 bitcast ({ i8* }* @const.0 to i8*), i64 8, i1 false) - %cast.2 = bitcast { i64, i64, i64, i64, i64, i64 }* %x2 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.2, i8* align 8 bitcast ({ i64, i64, i64, i64, i64, i64 }* @const.1 to i8*), i64 48, i1 false) - %cast.3 = bitcast { i64, i64, i64, i64, i64, i64 }* %y2 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.3, i8* align 8 bitcast ({ i64, i64, i64, i64, i64, i64 }* @const.1 to i8*), i64 48, i1 false) - %cast.4 = bitcast { i8* }* %x1 to i8* - %cast.5 = bitcast { i8* }* %y1 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.4, i8* align 8 %cast.5, i64 8, i1 false) - %cast.6 = bitcast { i64, i64, i64, i64, i64, i64 }* %x2 to i8* - %cast.7 = bitcast { i64, i64, i64, i64, i64, i64 }* %y2 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.6, i8* align 8 %cast.7, i64 48, i1 false) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %x1, ptr align 8 @const.0, i64 8, i1 false) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %y1, ptr align 8 @const.0, i64 8, i1 false) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %x2, ptr align 8 @const.1, i64 48, i1 false) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %y2, ptr align 8 @const.1, i64 48, i1 false) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %x1, ptr align 8 %y1, i64 8, i1 false) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %x2, ptr align 8 %y2, i64 48, i1 false) )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -780,11 +759,10 @@ h.mkLocal("a2", bpi32t, aex2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast { i32 }* %t1 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.0, i8* align 4 bitcast ({ i32 }* @const.0 to i8*), i64 4, i1 false) - %field.0 = getelementptr inbounds { i32 }, { i32 }* %t1, i32 0, i32 0 - store i32* %field.0, i32** %a1, align 8 - store i32* getelementptr inbounds ({ i32 }, { i32 }* @t2, i32 0, i32 0), i32** %a2, align 8 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 4 %t1, ptr align 4 @const.0, i64 4, i1 false) + %field.0 = getelementptr inbounds { i32 }, ptr %t1, i32 0, i32 0 + store ptr %field.0, ptr %a1, align 8 + store ptr @t2, ptr %a2, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp);
diff --git a/unittests/BackendCore/BackendCABIOracleTests.cpp b/unittests/BackendCore/BackendCABIOracleTests.cpp index 3f3c902..e675043 100644 --- a/unittests/BackendCore/BackendCABIOracleTests.cpp +++ b/unittests/BackendCore/BackendCABIOracleTests.cpp
@@ -55,7 +55,7 @@ CABIOracle cab(befty1, be->typeManager()); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( Return: Direct { { double, double } } sigOffset: -1 - Param 1: Direct AttrNest { i8* } sigOffset: 0 + Param 1: Direct AttrNest { ptr } sigOffset: 0 Param 2: Direct AttrSext { i8 } sigOffset: 1 Param 3: Direct { float } sigOffset: 2 Param 4: Ignore { void } sigOffset: -1 @@ -65,7 +65,7 @@ bool equal = difftokens(exp.content, cab.toString(), reason); EXPECT_EQ("pass", equal ? "pass" : reason); EXPECT_EQ(repr(cab.getFunctionTypeForABI()), - "{ double, double } (i8*, i8, float, i64)"); + "{ double, double } (ptr, i8, float, i64)"); } } @@ -118,99 +118,98 @@ std::vector<FcnItem> items = { // 1 - FcnItem( { }, { }, + FcnItem({}, {}, "Return: Ignore { void } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0", - "void (i8*)"), + "Param 1: Direct AttrNest { ptr } sigOffset: 0", + "void (ptr)"), // 2 - FcnItem( { bi8t }, { }, + FcnItem({bi8t}, {}, "Return: Direct AttrSext { i8 } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0", - "i8 (i8*)"), + "Param 1: Direct AttrNest { ptr } sigOffset: 0", + "i8 (ptr)"), // 3 - FcnItem( { }, { bi8t }, + FcnItem({}, {bi8t}, "Return: Ignore { void } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct AttrSext { i8 } sigOffset: 1", - "void (i8*, i8)"), + "void (ptr, i8)"), // 4 - FcnItem( { }, { st5, bpf64t }, + FcnItem({}, {st5, bpf64t}, "Return: Ignore { void } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { float } sigOffset: 1 " - "Param 3: Direct { double* } sigOffset: 2", - "void (i8*, float, double*)"), + "Param 3: Direct { ptr } sigOffset: 2", + "void (ptr, float, ptr)"), // 5 - FcnItem({ bi8t, bf64t }, { bi8t, bu8t, st0 }, + FcnItem({bi8t, bf64t}, {bi8t, bu8t, st0}, "Return: Direct { { i8, double } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct AttrSext { i8 } sigOffset: 1 " "Param 3: Direct AttrZext { i8 } sigOffset: 2 " "Param 4: Ignore { void } sigOffset: -1", - "{ i8, double } (i8*, i8, i8)"), + "{ i8, double } (ptr, i8, i8)"), // 6 - FcnItem({ st2 }, { st2, st0, st4, st1 }, + FcnItem({st2}, {st2, st0, st4, st1}, "Return: Direct { { double, double } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { double, double } sigOffset: 1 " "Param 3: Ignore { void } sigOffset: -1 " "Param 4: Direct { <2 x float> } sigOffset: 3 " "Param 5: Direct { i64 } sigOffset: 4 ", - "{ double, double } (i8*, double, double, <2 x float>, i64)"), + "{ double, double } (ptr, double, double, <2 x float>, i64)"), // 7 - FcnItem({ st3 }, { st3, st0, bu8t }, - "Return: Indirect AttrStructReturn { { { double, double }, i8 }* } sigOffset: 0 " - "Param 1: Direct AttrNest { i8* } sigOffset: 1 " - "Param 2: Indirect AttrByVal { { { double, double }, i8 }* } sigOffset: 2 " + FcnItem({st3}, {st3, st0, bu8t}, + "Return: Indirect AttrStructReturn { ptr } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 1 " + "Param 2: Indirect AttrByVal { ptr } sigOffset: 2 " "Param 3: Ignore { void } sigOffset: -1 " "Param 4: Direct AttrZext { i8 } sigOffset: 3 ", - "void ({ { double, double }, i8 }*, i8*, " - "{ { double, double }, i8 }*, i8)"), + "void (ptr, ptr, ptr, i8)"), // 8 - FcnItem( { st6 }, { st6, st6 }, + FcnItem({st6}, {st6, st6}, "Return: Direct { { i64, i64 } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i64, i64 } sigOffset: 1 " "Param 3: Direct { i64, i64 } sigOffset: 3", - "{ i64, i64 } (i8*, i64, i64, i64, i64)"), + "{ i64, i64 } (ptr, i64, i64, i64, i64)"), // 9 - FcnItem( { st8 }, { st8 }, + FcnItem({st8}, {st8}, "Return: Direct { { i64, i32 } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i64, i32 } sigOffset: 1", - "{ i64, i32 } (i8*, i64, i32)"), + "{ i64, i32 } (ptr, i64, i32)"), // 10 - FcnItem( { at0 }, { at1 }, + FcnItem({at0}, {at1}, "Return: Ignore { void } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i32 } sigOffset: 1", - "void (i8*, i32)"), + "void (ptr, i32)"), // 11 - FcnItem( { at2 }, { at3 }, + FcnItem({at2}, {at3}, "Return: Direct { { i64, i32 } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i64, i64 } sigOffset: 1", - "{ i64, i32 } (i8*, i64, i64)"), + "{ i64, i32 } (ptr, i64, i64)"), // 12 // Make sure pointerness is preserved. - FcnItem( { stip }, { stii, stpp, stpi }, - "Return: Direct { { i64, i8* } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + FcnItem({stip}, {stii, stpp, stpi}, + "Return: Direct { { i64, ptr } } sigOffset: -1 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i64, i64 } sigOffset: 1 " - "Param 3: Direct { i8*, i8* } sigOffset: 3 " - "Param 4: Direct { i8*, i64 } sigOffset: 5", - "{ i64, i8* } (i8*, i64, i64, i8*, i8*, i8*, i64)"), + "Param 3: Direct { ptr, ptr } sigOffset: 3 " + "Param 4: Direct { ptr, i64 } sigOffset: 5", + "{ i64, ptr } (ptr, i64, i64, ptr, ptr, ptr, i64)"), }; unsigned count = 1; @@ -303,99 +302,97 @@ // 1 FcnItem({}, {}, "Return: Ignore { void } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0", - "void (i8*)"), + "Param 1: Direct AttrNest { ptr } sigOffset: 0", + "void (ptr)"), // 2 FcnItem({bi8t}, {}, "Return: Direct AttrSext { i8 } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0", - "i8 (i8*)"), + "Param 1: Direct AttrNest { ptr } sigOffset: 0", + "i8 (ptr)"), // 3 FcnItem({}, {bi8t}, "Return: Ignore { void } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct AttrSext { i8 } sigOffset: 1", - "void (i8*, i8)"), + "void (ptr, i8)"), // 4 FcnItem({}, {st5, bpf64t}, "Return: Ignore { void } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { float } sigOffset: 1 " - "Param 3: Direct { double* } sigOffset: 2", - "void (i8*, float, double*)"), + "Param 3: Direct { ptr } sigOffset: 2", + "void (ptr, float, ptr)"), // 5 FcnItem({bi8t, bf64t}, {bi8t, bu8t, st0}, "Return: Direct { { i64, i64 } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct AttrSext { i8 } sigOffset: 1 " "Param 3: Direct AttrZext { i8 } sigOffset: 2 " "Param 4: Ignore { void } sigOffset: -1", - "{ i64, i64 } (i8*, i8, i8)"), + "{ i64, i64 } (ptr, i8, i8)"), // 6 FcnItem({st2}, {st2, st0, st4, st1}, "Return: Direct { { double, double } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { [2 x double] } sigOffset: 1 " "Param 3: Ignore { void } sigOffset: -1 " "Param 4: Direct { [2 x float] } sigOffset: 2 " "Param 5: Direct { i64 } sigOffset: 3", - "{ double, double } (i8*, [2 x double], [2 x float], i64)"), + "{ double, double } (ptr, [2 x double], [2 x float], i64)"), // 7 FcnItem({st3}, {st3, st0, bu8t}, - "Return: Indirect AttrStructReturn { { { double, double }, i8 " - "}* } sigOffset: 0 " - "Param 1: Direct AttrNest { i8* } sigOffset: 1 " - "Param 2: Indirect AttrDoCopy { { { double, double }, i8 }* } " + "Return: Indirect AttrStructReturn { ptr } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 1 " + "Param 2: Indirect AttrDoCopy { ptr } " "sigOffset: 2 " "Param 3: Ignore { void } sigOffset: -1 " "Param 4: Direct AttrZext { i8 } sigOffset: 3 ", - "void ({ { double, double }, i8 }*, i8*, " - "{ { double, double }, i8 }*, i8)"), + "void (ptr, ptr, ptr, i8)"), // 8 FcnItem({st6}, {st6, st6}, "Return: Direct { { i64, i64 } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i64, i64 } sigOffset: 1 " "Param 3: Direct { i64, i64 } sigOffset: 3", - "{ i64, i64 } (i8*, i64, i64, i64, i64)"), + "{ i64, i64 } (ptr, i64, i64, i64, i64)"), // 9 FcnItem({st8}, {st8}, "Return: Direct { { i64, i32 } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i64, i32 } sigOffset: 1", - "{ i64, i32 } (i8*, i64, i32)"), + "{ i64, i32 } (ptr, i64, i32)"), // 10 FcnItem({at0}, {at1}, "Return: Ignore { void } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i32 } sigOffset: 1", - "void (i8*, i32)"), + "void (ptr, i32)"), // 11 FcnItem({at2}, {at3}, "Return: Direct { { i64, i32 } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i64, i64 } sigOffset: 1", - "{ i64, i32 } (i8*, i64, i64)"), + "{ i64, i32 } (ptr, i64, i64)"), // 12 // Make sure pointerness is preserved. FcnItem({stip}, {stii, stpp, stpi}, - "Return: Direct { { i64, i8* } } sigOffset: -1 " - "Param 1: Direct AttrNest { i8* } sigOffset: 0 " + "Return: Direct { { i64, ptr } } sigOffset: -1 " + "Param 1: Direct AttrNest { ptr } sigOffset: 0 " "Param 2: Direct { i64, i64 } sigOffset: 1 " - "Param 3: Direct { i8*, i8* } sigOffset: 3 " - "Param 4: Direct { i8*, i64 } sigOffset: 5", - "{ i64, i8* } (i8*, i64, i64, i8*, i8*, i8*, i64)"), + "Param 3: Direct { ptr, ptr } sigOffset: 3 " + "Param 4: Direct { ptr, i64 } sigOffset: 5", + "{ i64, ptr } (ptr, i64, i64, ptr, ptr, ptr, i64)"), }; unsigned count = 1; @@ -532,24 +529,20 @@ Bstatement *rst2 = h.mkReturn(rvals2, FcnTestHarness::NoAppend); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %p3.ld.0 = load i8, i8* %p3.addr, align 1 + %p3.ld.0 = load i8, ptr %p3.addr, align 1 %sub.0 = sub i8 %p3.ld.0, 1 - %p4.ld.0 = load i8, i8* %p4.addr, align 1 - %cast.1 = bitcast { float, float, i16, i16, i16 }* %p0.addr to { <2 x float>, i48 }* - %field0.0 = getelementptr inbounds { <2 x float>, i48 }, { <2 x float>, i48 }* %cast.1, i32 0, i32 0 - %ld.1 = load <2 x float>, <2 x float>* %field0.0, align 8 - %field1.0 = getelementptr inbounds { <2 x float>, i48 }, { <2 x float>, i48 }* %cast.1, i32 0, i32 1 - %ld.2 = load i48, i48* %field1.0, align 8 - %cast.2 = bitcast { double, float, float }* %p1.addr to { double, <2 x float> }* - %field0.1 = getelementptr inbounds { double, <2 x float> }, { double, <2 x float> }* %cast.2, i32 0, i32 0 - %ld.3 = load double, double* %field0.1, align 8 - %field1.1 = getelementptr inbounds { double, <2 x float> }, { double, <2 x float> }* %cast.2, i32 0, i32 1 - %ld.4 = load <2 x float>, <2 x float>* %field1.1, align 8 - %call.0 = call addrspace(0) { double, <2 x float> } @foo(i8* nest undef, <2 x float> %ld.1, i48 %ld.2, double %ld.3, <2 x float> %ld.4, i8 zeroext %sub.0, i8 signext %p4.ld.0, { { float, float, i16, i16, i16 }, { double, float, float } }* byval({ { float, float, i16, i16, i16 }, { double, float, float } }) %p5) - %cast.3 = bitcast { double, float, float }* %sret.actual.0 to { double, <2 x float> }* - store { double, <2 x float> } %call.0, { double, <2 x float> }* %cast.3, align 8 - %cast.4 = bitcast { double, float, float }* %sret.actual.0 to { double, <2 x float> }* - %ld.5 = load { double, <2 x float> }, { double, <2 x float> }* %cast.4, align 8 + %p4.ld.0 = load i8, ptr %p4.addr, align 1 + %field0.0 = getelementptr inbounds { <2 x float>, i48 }, ptr %p0.addr, i32 0, i32 0 + %ld.1 = load <2 x float>, ptr %field0.0, align 8 + %field1.0 = getelementptr inbounds { <2 x float>, i48 }, ptr %p0.addr, i32 0, i32 1 + %ld.2 = load i48, ptr %field1.0, align 8 + %field0.1 = getelementptr inbounds { double, <2 x float> }, ptr %p1.addr, i32 0, i32 0 + %ld.3 = load double, ptr %field0.1, align 8 + %field1.1 = getelementptr inbounds { double, <2 x float> }, ptr %p1.addr, i32 0, i32 1 + %ld.4 = load <2 x float>, ptr %field1.1, align 8 + %call.0 = call addrspace(0) { double, <2 x float> } @foo(ptr nest undef, <2 x float> %ld.1, i48 %ld.2, double %ld.3, <2 x float> %ld.4, i8 zeroext %sub.0, i8 signext %p4.ld.0, ptr byval({ { float, float, i16, i16, i16 }, { double, float, float } }) %p5) + store { double, <2 x float> } %call.0, ptr %sret.actual.0, align 8 + %ld.5 = load { double, <2 x float> }, ptr %sret.actual.0, align 8 ret { double, <2 x float> } %ld.5 )RAW_RESULT"); @@ -651,27 +644,21 @@ Bstatement *rst2 = h.mkReturn(rvals2, FcnTestHarness::NoAppend); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %p3.ld.0 = load i8, i8* %p3.addr, align 1 + %p3.ld.0 = load i8, ptr %p3.addr, align 1 %sub.0 = sub i8 %p3.ld.0, 1 - %p4.ld.0 = load i8, i8* %p4.addr, align 1 - %cast.1 = bitcast { float, float, i16, i16, i16 }* %p0.addr to { i64, i48 }* - %field0.0 = getelementptr inbounds { i64, i48 }, { i64, i48 }* %cast.1, i32 0, i32 0 - %ld.1 = load i64, i64* %field0.0, align 8 - %field1.0 = getelementptr inbounds { i64, i48 }, { i64, i48 }* %cast.1, i32 0, i32 1 - %ld.2 = load i48, i48* %field1.0, align 8 - %cast.2 = bitcast { double, float, float }* %p1.addr to { i64, i64 }* - %field0.1 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %cast.2, i32 0, i32 0 - %ld.3 = load i64, i64* %field0.1, align 8 - %field1.1 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %cast.2, i32 0, i32 1 - %ld.4 = load i64, i64* %field1.1, align 8 - %cast.3 = bitcast { { float, float, i16, i16, i16 }, { double, float, float } }* %doCopy.addr.0 to i8* - %cast.4 = bitcast { { float, float, i16, i16, i16 }, { double, float, float } }* %p5 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.3, i8* align 8 %cast.4, i64 32, i1 false) - %call.0 = call addrspace(0) { i64, i64 } @foo(i8* nest undef, i64 %ld.1, i48 %ld.2, i64 %ld.3, i64 %ld.4, i8 zeroext %sub.0, i8 signext %p4.ld.0, { { float, float, i16, i16, i16 }, { double, float, float } }* %doCopy.addr.0) - %cast.5 = bitcast { double, float, float }* %sret.actual.0 to { i64, i64 }* - store { i64, i64 } %call.0, { i64, i64 }* %cast.5, align 8 - %cast.6 = bitcast { double, float, float }* %sret.actual.0 to { i64, i64 }* - %ld.5 = load { i64, i64 }, { i64, i64 }* %cast.6, align 8 + %p4.ld.0 = load i8, ptr %p4.addr, align 1 + %field0.0 = getelementptr inbounds { i64, i48 }, ptr %p0.addr, i32 0, i32 0 + %ld.1 = load i64, ptr %field0.0, align 8 + %field1.0 = getelementptr inbounds { i64, i48 }, ptr %p0.addr, i32 0, i32 1 + %ld.2 = load i48, ptr %field1.0, align 8 + %field0.1 = getelementptr inbounds { i64, i64 }, ptr %p1.addr, i32 0, i32 0 + %ld.3 = load i64, ptr %field0.1, align 8 + %field1.1 = getelementptr inbounds { i64, i64 }, ptr %p1.addr, i32 0, i32 1 + %ld.4 = load i64, ptr %field1.1, align 8 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %doCopy.addr.0, ptr align 8 %p5, i64 32, i1 false) + %call.0 = call addrspace(0) { i64, i64 } @foo(ptr nest undef, i64 %ld.1, i48 %ld.2, i64 %ld.3, i64 %ld.4, i8 zeroext %sub.0, i8 signext %p4.ld.0, ptr %doCopy.addr.0) + store { i64, i64 } %call.0, ptr %sret.actual.0, align 8 + %ld.5 = load { i64, i64 }, ptr %sret.actual.0, align 8 ret { i64, i64 } %ld.5 )RAW_RESULT"); @@ -716,12 +703,9 @@ h.mkReturn(rvals); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast [2 x float]* %p0.addr to <2 x float>* - %ld.0 = load <2 x float>, <2 x float>* %cast.0, align 8 - call addrspace(0) void @foo([3 x double]* sret([3 x double]) "go_sret" %sret.actual.0, i8* nest undef, <2 x float> %ld.0) - %cast.1 = bitcast [3 x double]* %sret.formal.0 to i8* - %cast.2 = bitcast [3 x double]* %sret.actual.0 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.1, i8* align 8 %cast.2, i64 24, i1 false) + %ld.0 = load <2 x float>, ptr %p0.addr, align 8 + call addrspace(0) void @foo(ptr sret([3 x double]) "go_sret" %sret.actual.0, ptr nest undef, <2 x float> %ld.0) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %sret.formal.0, ptr align 8 %sret.actual.0, i64 24, i1 false) ret void )RAW_RESULT"); @@ -760,12 +744,10 @@ h.mkReturn(rvals); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %ld.0 = load [2 x float], [2 x float]* %p0.addr, align 4 - %call.0 = call addrspace(0) { double, double, double } @foo(i8* nest undef, [2 x float] %ld.0) - %cast.1 = bitcast [3 x double]* %sret.actual.0 to { double, double, double }* - store { double, double, double } %call.0, { double, double, double }* %cast.1, align 8 - %cast.2 = bitcast [3 x double]* %sret.actual.0 to { double, double, double }* - %ld.1 = load { double, double, double }, { double, double, double }* %cast.2, align 8 + %ld.0 = load [2 x float], ptr %p0.addr, align 4 + %call.0 = call addrspace(0) { double, double, double } @foo(ptr nest undef, [2 x float] %ld.0) + store { double, double, double } %call.0, ptr %sret.actual.0, align 8 + %ld.1 = load { double, double, double }, ptr %sret.actual.0, align 8 ret { double, double, double } %ld.1 )RAW_RESULT"); @@ -813,7 +795,7 @@ h.mkReturn(rvals); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - call addrspace(0) void @foo(i8* nest undef, i32 4) + call addrspace(0) void @foo(ptr nest undef, i32 4) ret void )RAW_RESULT"); @@ -895,26 +877,20 @@ h.mkReturn(rvals); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast { float, float }* %p0.addr to <2 x float>* - %ld.0 = load <2 x float>, <2 x float>* %cast.0, align 8 - %field0.0 = getelementptr inbounds { double, double }, { double, double }* %p1.addr, i32 0, i32 0 - %ld.1 = load double, double* %field0.0, align 8 - %field1.0 = getelementptr inbounds { double, double }, { double, double }* %p1.addr, i32 0, i32 1 - %ld.2 = load double, double* %field1.0, align 8 - %call.0 = call addrspace(0) <2 x float> @foo(i8* nest undef, <2 x float> %ld.0, double %ld.1, double %ld.2) - %cast.2 = bitcast { float, float }* %sret.actual.0 to <2 x float>* - store <2 x float> %call.0, <2 x float>* %cast.2, align 8 - %cast.3 = bitcast { float, float }* %z to i8* - %cast.4 = bitcast { float, float }* %sret.actual.0 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.3, i8* align 4 %cast.4, i64 8, i1 false) - %ld.3 = load <2 x float>, <2 x float>* bitcast ({ float, float }* @const.0 to <2 x float>*), align 8 - %ld.4 = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @const.1, i32 0, i32 0), align 8 - %ld.5 = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @const.1, i32 0, i32 1), align 8 - %call.1 = call addrspace(0) <2 x float> @foo(i8* nest undef, <2 x float> %ld.3, double %ld.4, double %ld.5) - %cast.7 = bitcast { float, float }* %sret.actual.1 to <2 x float>* - store <2 x float> %call.1, <2 x float>* %cast.7, align 8 - %cast.8 = bitcast { float, float }* %sret.actual.1 to <2 x float>* - %ld.6 = load <2 x float>, <2 x float>* %cast.8, align 8 + %ld.0 = load <2 x float>, ptr %p0.addr, align 8 + %field0.0 = getelementptr inbounds { double, double }, ptr %p1.addr, i32 0, i32 0 + %ld.1 = load double, ptr %field0.0, align 8 + %field1.0 = getelementptr inbounds { double, double }, ptr %p1.addr, i32 0, i32 1 + %ld.2 = load double, ptr %field1.0, align 8 + %call.0 = call addrspace(0) <2 x float> @foo(ptr nest undef, <2 x float> %ld.0, double %ld.1, double %ld.2) + store <2 x float> %call.0, ptr %sret.actual.0, align 8 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 4 %z, ptr align 4 %sret.actual.0, i64 8, i1 false) + %ld.3 = load <2 x float>, ptr @const.0, align 8 + %ld.4 = load double, ptr @const.1, align 8 + %ld.5 = load double, ptr getelementptr inbounds ({ double, double }, ptr @const.1, i32 0, i32 1), align 8 + %call.1 = call addrspace(0) <2 x float> @foo(ptr nest undef, <2 x float> %ld.3, double %ld.4, double %ld.5) + store <2 x float> %call.1, ptr %sret.actual.1, align 8 + %ld.6 = load <2 x float>, ptr %sret.actual.1, align 8 ret <2 x float> %ld.6 )RAW_RESULT"); @@ -968,20 +944,16 @@ h.mkReturn(rvals); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast { float, float }* %p0.addr to [2 x float]* - %ld.0 = load [2 x float], [2 x float]* %cast.0, align 4 - %cast.1 = bitcast { double, double }* %p1.addr to [2 x double]* - %ld.1 = load [2 x double], [2 x double]* %cast.1, align 8 - %call.0 = call addrspace(0) { float, float } @foo(i8* nest undef, [2 x float] %ld.0, [2 x double] %ld.1) - store { float, float } %call.0, { float, float }* %sret.actual.0, align 4 - %cast.3 = bitcast { float, float }* %z to i8* - %cast.4 = bitcast { float, float }* %sret.actual.0 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.3, i8* align 4 %cast.4, i64 8, i1 false) - %ld.2 = load [2 x float], [2 x float]* bitcast ({ float, float }* @const.0 to [2 x float]*), align 4 - %ld.3 = load [2 x double], [2 x double]* bitcast ({ double, double }* @const.1 to [2 x double]*), align 8 - %call.1 = call addrspace(0) { float, float } @foo(i8* nest undef, [2 x float] %ld.2, [2 x double] %ld.3) - store { float, float } %call.1, { float, float }* %sret.actual.1, align 4 - %ld.4 = load { float, float }, { float, float }* %sret.actual.1, align 4 + %ld.0 = load [2 x float], ptr %p0.addr, align 4 + %ld.1 = load [2 x double], ptr %p1.addr, align 8 + %call.0 = call addrspace(0) { float, float } @foo(ptr nest undef, [2 x float] %ld.0, [2 x double] %ld.1) + store { float, float } %call.0, ptr %sret.actual.0, align 4 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 4 %z, ptr align 4 %sret.actual.0, i64 8, i1 false) + %ld.2 = load [2 x float], ptr @const.0, align 4 + %ld.3 = load [2 x double], ptr @const.1, align 8 + %call.1 = call addrspace(0) { float, float } @foo(ptr nest undef, [2 x float] %ld.2, [2 x double] %ld.3) + store { float, float } %call.1, ptr %sret.actual.1, align 4 + %ld.4 = load { float, float }, ptr %sret.actual.1, align 4 ret { float, float } %ld.4 )RAW_RESULT");
diff --git a/unittests/BackendCore/BackendCallTests.cpp b/unittests/BackendCore/BackendCallTests.cpp index b8d7eaf..bd9da2a 100644 --- a/unittests/BackendCore/BackendCallTests.cpp +++ b/unittests/BackendCore/BackendCallTests.cpp
@@ -47,9 +47,9 @@ h.mkReturn(be->var_expression(x, loc)); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %call.0 = call addrspace(0) i64 @foo(i8* nest undef, i32 3, i32 6, i64* null) - store i64 %call.0, i64* %x, align 8 - %x.ld.0 = load i64, i64* %x, align 8 + %call.0 = call addrspace(0) i64 @foo(ptr nest undef, i32 3, i32 6, ptr null) + store i64 %call.0, ptr %x, align 8 + %x.ld.0 = load i64, ptr %x, align 8 ret i64 %x.ld.0 )RAW_RESULT"); @@ -80,7 +80,7 @@ h.mkExprStmt(call); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - call addrspace(0) void @bar(i8* nest undef) + call addrspace(0) void @bar(ptr nest undef) )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -119,8 +119,7 @@ { DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast { i8*, i32*, i64*, i64 }* %sret.formal.0 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ({ i8*, i32*, i64*, i64 }* @const.0 to i8*), i64 32, i1 false) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %sret.formal.0, ptr align 8 @const.0, i64 32, i1 false) ret void )RAW_RESULT"); @@ -143,19 +142,17 @@ { DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %p0.ld.0 = load i8*, i8** %p0.addr, align 8 - %field.0 = getelementptr inbounds { i8*, i32*, i64*, i64 }, { i8*, i32*, i64*, i64 }* %tmp.0, i32 0, i32 0 - store i8* %p0.ld.0, i8** %field.0, align 8 - %field.1 = getelementptr inbounds { i8*, i32*, i64*, i64 }, { i8*, i32*, i64*, i64 }* %tmp.0, i32 0, i32 1 - store i32* null, i32** %field.1, align 8 - %field.2 = getelementptr inbounds { i8*, i32*, i64*, i64 }, { i8*, i32*, i64*, i64 }* %tmp.0, i32 0, i32 2 - store i64* null, i64** %field.2, align 8 - %field.3 = getelementptr inbounds { i8*, i32*, i64*, i64 }, { i8*, i32*, i64*, i64 }* %tmp.0, i32 0, i32 3 - store i64 101, i64* %field.3, align 8 - %cast.2 = bitcast { i8*, i32*, i64*, i64 }* %sret.formal.0 to i8* - %cast.3 = bitcast { i8*, i32*, i64*, i64 }* %tmp.0 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.2, i8* align 8 %cast.3, i64 32, i1 false) - ret void + %p0.ld.0 = load ptr, ptr %p0.addr, align 8 + %field.0 = getelementptr inbounds { ptr, ptr, ptr, i64 }, ptr %tmp.0, i32 0, i32 0 + store ptr %p0.ld.0, ptr %field.0, align 8 + %field.1 = getelementptr inbounds { ptr, ptr, ptr, i64 }, ptr %tmp.0, i32 0, i32 1 + store ptr null, ptr %field.1, align 8 + %field.2 = getelementptr inbounds { ptr, ptr, ptr, i64 }, ptr %tmp.0, i32 0, i32 2 + store ptr null, ptr %field.2, align 8 + %field.3 = getelementptr inbounds { ptr, ptr, ptr, i64 }, ptr %tmp.0, i32 0, i32 3 + store i64 101, ptr %field.3, align 8 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %sret.formal.0, ptr align 8 %tmp.0, i64 32, i1 false) + ret void )RAW_RESULT"); bool isOK = h.expectStmt(s2, exp); @@ -206,12 +203,12 @@ FcnTestHarness::YesAppend); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { + define void @foo(ptr nest %nest.0) #0 { entry: br i1 true, label %then.0, label %else.0 then.0: ; preds = %entry - call void @noret(i8* nest undef) + call void @noret(ptr nest undef) unreachable fallthrough.0: ; preds = %else.0 @@ -283,18 +280,18 @@ h.mkReturn(be->var_expression(z, loc)); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %asmcall.0 = call addrspace(0) i64* asm sideeffect "adrp x0, :tlsdesc:runtime.g\0Aldr $0, [x0, :tlsdesc_lo12:runtime.g]\0Aadd x0, x0, :tlsdesc_lo12:runtime.g\0A.tlsdesccall runtime.g\0Ablr $0\0Amrs $0, TPIDR_EL0\0Aldr $0, [$0, x0]\0A", "=r,~{x0}"() - store i64* %asmcall.0, i64** %x, align 8 - call addrspace(0) void @bar(i8* nest undef) - %asmcall.1 = call addrspace(0) i64* asm sideeffect "adrp x0, :tlsdesc:runtime.g\0Aldr $0, [x0, :tlsdesc_lo12:runtime.g]\0Aadd x0, x0, :tlsdesc_lo12:runtime.g\0A.tlsdesccall runtime.g\0Ablr $0\0Amrs $0, TPIDR_EL0\0Aldr $0, [$0, x0]\0A", "=r,~{x0}"() - store i64* %asmcall.1, i64** %y, align 8 - %x.ld.0 = load i64*, i64** %x, align 8 - %.ld.0 = load i64, i64* %x.ld.0, align 8 - %y.ld.0 = load i64*, i64** %y, align 8 - %.ld.1 = load i64, i64* %y.ld.0, align 8 + %asmcall.0 = call addrspace(0) ptr asm sideeffect "adrp x0, :tlsdesc:runtime.g\0Aldr $0, [x0, :tlsdesc_lo12:runtime.g]\0Aadd x0, x0, :tlsdesc_lo12:runtime.g\0A.tlsdesccall runtime.g\0Ablr $0\0Amrs $0, TPIDR_EL0\0Aldr $0, [$0, x0]\0A", "=r,~{x0}"() + store ptr %asmcall.0, ptr %x, align 8 + call addrspace(0) void @bar(ptr nest undef) + %asmcall.1 = call addrspace(0) ptr asm sideeffect "adrp x0, :tlsdesc:runtime.g\0Aldr $0, [x0, :tlsdesc_lo12:runtime.g]\0Aadd x0, x0, :tlsdesc_lo12:runtime.g\0A.tlsdesccall runtime.g\0Ablr $0\0Amrs $0, TPIDR_EL0\0Aldr $0, [$0, x0]\0A", "=r,~{x0}"() + store ptr %asmcall.1, ptr %y, align 8 + %x.ld.0 = load ptr, ptr %x, align 8 + %.ld.0 = load i64, ptr %x.ld.0, align 8 + %y.ld.0 = load ptr, ptr %y, align 8 + %.ld.1 = load i64, ptr %y.ld.0, align 8 %add.0 = add i64 %.ld.0, %.ld.1 - store i64 %add.0, i64* %z, align 8 - %z.ld.0 = load i64, i64* %z, align 8 + store i64 %add.0, ptr %z, align 8 + %z.ld.0 = load i64, ptr %z, align 8 ret i64 %z.ld.0 )RAW_RESULT");
diff --git a/unittests/BackendCore/BackendCoreTests.cpp b/unittests/BackendCore/BackendCoreTests.cpp index 30923a0..9ca75f5 100644 --- a/unittests/BackendCore/BackendCoreTests.cpp +++ b/unittests/BackendCore/BackendCoreTests.cpp
@@ -86,7 +86,7 @@ ASSERT_TRUE(best != nullptr); ASSERT_TRUE(llst != nullptr); EXPECT_EQ(llst, best->type()); - EXPECT_EQ(repr(best->type()), "{ i8, float*, i64 }"); + EXPECT_EQ(repr(best->type()), "{ i8, ptr, i64 }"); // If a field has error type, entire struct has error type std::vector<Backend::Btyped_identifier> fields = { @@ -186,14 +186,14 @@ Btype *phpt2 = be->placeholder_pointer_type("ph", loc, false); Btype *phpt3 = be->placeholder_pointer_type("ph", loc, false); ASSERT_TRUE(phpt2 != phpt3); - EXPECT_TRUE(phpt2->type() != phpt3->type()); + // ptr == ptr + EXPECT_TRUE(phpt2->type() == phpt3->type()); // Replace placeholder pointer type Btype *pst = be->pointer_type(mkBackendThreeFieldStruct(be.get())); be->set_placeholder_pointer_type(phpt1, pst); ASSERT_TRUE(phpt1->type()->isPointerTy()); PointerType *llpt = cast<PointerType>(phpt1->type()); - EXPECT_TRUE(llpt->getElementType()->isStructTy()); // Placeholder struct type Btype *phst1 = be->placeholder_struct_type("ph", loc); @@ -398,8 +398,6 @@ // However the underlying LLVM types should be considered // assignment-compatible. std::set<llvm::Type *> visited; - bool equiv = tm->fcnPointerCompatible(pht->type(), pht2->type(), visited); - EXPECT_TRUE(equiv); bool broken = h.finish(PreserveDebugInfo); EXPECT_FALSE(broken && "Module failed to verify."); @@ -468,9 +466,9 @@ EXPECT_FALSE(broken && "Module failed to verify."); bool ok = h.expectModuleDumpContains( - "@gv = global { { i8, i8*, i32 }, %ph.0 } { { i8, i8*, i32 } { i8 0, " - "i8* " - "null, i32 101 }, %ph.0 { i8 0, i8* null, i32 101 } }"); + "@gv = global { { i8, ptr, i32 }, %ph.0 } { { i8, ptr, i32 } { i8 0, " + "ptr " + "null, i32 101 }, %ph.0 { i8 0, ptr null, i32 101 } }"); EXPECT_TRUE(ok); }
diff --git a/unittests/BackendCore/BackendDebugEmit.cpp b/unittests/BackendCore/BackendDebugEmit.cpp index 7859104..f880cb2 100644 --- a/unittests/BackendCore/BackendDebugEmit.cpp +++ b/unittests/BackendCore/BackendDebugEmit.cpp
@@ -42,13 +42,13 @@ h.mkLocal("x", bu32t); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { - entry: - %x = alloca i32, align 4 - store i32 0, i32* %x, align 4 - call void @llvm.dbg.declare(metadata i32* %x, metadata !4, metadata !DIExpression()), !dbg !12 - ret void - } + define void @foo(ptr nest %nest.0) #0 { + entry: + %x = alloca i32, align 4 + store i32 0, ptr %x, align 4 + #dbg_declare(ptr %x, !4, !DIExpression(), !12) + ret void + } )RAW_RESULT"); bool broken = h.finish(PreserveDebugInfo); @@ -76,11 +76,11 @@ EXPECT_FALSE(broken && "Module failed to verify."); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0, { i64, i64, i64 }* byval({ i64, i64, i64 }) %p0) #0 { - entry: - call void @llvm.dbg.declare(metadata { i64, i64, i64 }* %p0, metadata !4, metadata !DIExpression()), !dbg !18 - ret void - } + define void @foo(ptr nest %nest.0, ptr byval({ i64, i64, i64 }) %p0) #0 { + entry: + #dbg_declare(ptr %p0, !4, !DIExpression(), !18) + ret void + } )RAW_RESULT"); bool isOK = h.expectValue(func->function(), exp); @@ -103,10 +103,9 @@ EXPECT_FALSE(broken && "Module failed to verify."); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0, { i64, i64, i64 }* %p0) #0 { + define void @foo(ptr nest %nest.0, ptr %p0) #0 { entry: - call void @llvm.dbg.declare(metadata { i64, i64, i64 }* %p0, metadata !4, - metadata !DIExpression()), !dbg !18 + #dbg_declare(ptr %p0, !4, !DIExpression(), !18) ret void } )RAW_RESULT"); @@ -188,7 +187,7 @@ std::vector<std::string> tokens = tokenize(fdump); unsigned declcount = 0; for (auto t : tokens) - if (t == "@llvm.dbg.declare(metadata") + if (t == "#dbg_declare(ptr") declcount += 1; // seven formals and six locals => 13 var decls @@ -210,11 +209,11 @@ h.mkLocal("x", bu32t); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 !dbg !4 { - entry: - %x = alloca i32, align 4 - ret void, !dbg !10 - } + define void @foo(ptr nest %nest.0) #0 !dbg !4 { + entry: + %x = alloca i32, align 4 + ret void, !dbg !10 + } )RAW_RESULT"); bool broken = h.finish(PreserveDebugInfo);
diff --git a/unittests/BackendCore/BackendExprTests.cpp b/unittests/BackendCore/BackendExprTests.cpp index a476f06..5ead97e 100644 --- a/unittests/BackendCore/BackendExprTests.cpp +++ b/unittests/BackendCore/BackendExprTests.cpp
@@ -196,7 +196,7 @@ Btype *pbt = be->pointer_type(bt); Bexpression *bpzero = be->zero_expression(pbt); ASSERT_TRUE(bpzero != nullptr); - EXPECT_EQ(repr(bpzero->value()), "i8* null"); + EXPECT_EQ(repr(bpzero->value()), "ptr null"); Btype *bi32t = be->integer_type(false, 32); Btype *s2t = mkBackendStruct(be, pbt, "f1", bi32t, "f2", nullptr); Bexpression *bszero = be->zero_expression(s2t); @@ -244,10 +244,9 @@ h.mkAssign(fex, mkInt32Const(be, 22)); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %x, align 8 - %cast.0 = bitcast i64* %x to { i32, i32 }* - %field.0 = getelementptr inbounds { i32, i32 }, { i32, i32 }* %cast.0, i32 0, i32 1 - store i32 22, i32* %field.0, align 4 + store i64 0, ptr %x, align 8 + %field.0 = getelementptr inbounds { i32, i32 }, ptr %x, i32 0, i32 1 + store i32 22, ptr %field.0, align 4 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -295,14 +294,13 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %param3.ld.0 = load i64*, i64** %param3.addr, align 8 - %cast.0 = bitcast i64* %param3.ld.0 to i32* - store i32 5, i32* %cast.0, align 4 - store double 0.000000e+00, double* %p, align 8 - %p.ld.0 = load double, double* %p, align 8 + %param3.ld.0 = load ptr, ptr %param3.addr, align 8 + store i32 5, ptr %param3.ld.0, align 4 + store double 0.000000e+00, ptr %p, align 8 + %p.ld.0 = load double, ptr %p, align 8 %ftoui.0 = fptoui double %p.ld.0 to i64 - %itpcast.0 = inttoptr i64 %ftoui.0 to i32* - store i32 5, i32* %itpcast.0, align 4 + %itpcast.0 = inttoptr i64 %ftoui.0 to ptr + store i32 5, ptr %itpcast.0, align 4 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -354,92 +352,92 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %p1.ld.0 = load double, double* %p1.addr, align 8 + %p1.ld.0 = load double, ptr %p1.addr, align 8 %fptrunc.0 = fptrunc double %p1.ld.0 to float - store float %fptrunc.0, float* %p0.addr, align 4 - %p0.ld.0 = load float, float* %p0.addr, align 4 + store float %fptrunc.0, ptr %p0.addr, align 4 + %p0.ld.0 = load float, ptr %p0.addr, align 4 %fpext.0 = fpext float %p0.ld.0 to double - store double %fpext.0, double* %p1.addr, align 8 - %p2.ld.0 = load i32, i32* %p2.addr, align 4 + store double %fpext.0, ptr %p1.addr, align 8 + %p2.ld.0 = load i32, ptr %p2.addr, align 4 %sitof.0 = sitofp i32 %p2.ld.0 to float - store float %sitof.0, float* %p0.addr, align 4 - %p0.ld.1 = load float, float* %p0.addr, align 4 + store float %sitof.0, ptr %p0.addr, align 4 + %p0.ld.1 = load float, ptr %p0.addr, align 4 %ftosi.0 = fptosi float %p0.ld.1 to i32 - store i32 %ftosi.0, i32* %p2.addr, align 4 - %p2.ld.1 = load i32, i32* %p2.addr, align 4 + store i32 %ftosi.0, ptr %p2.addr, align 4 + %p2.ld.1 = load i32, ptr %p2.addr, align 4 %sitof.1 = sitofp i32 %p2.ld.1 to double - store double %sitof.1, double* %p1.addr, align 8 - %p1.ld.1 = load double, double* %p1.addr, align 8 + store double %sitof.1, ptr %p1.addr, align 8 + %p1.ld.1 = load double, ptr %p1.addr, align 8 %ftosi.1 = fptosi double %p1.ld.1 to i32 - store i32 %ftosi.1, i32* %p2.addr, align 4 - %p3.ld.0 = load i64, i64* %p3.addr, align 8 + store i32 %ftosi.1, ptr %p2.addr, align 4 + %p3.ld.0 = load i64, ptr %p3.addr, align 8 %sitof.2 = sitofp i64 %p3.ld.0 to float - store float %sitof.2, float* %p0.addr, align 4 - %p0.ld.2 = load float, float* %p0.addr, align 4 + store float %sitof.2, ptr %p0.addr, align 4 + %p0.ld.2 = load float, ptr %p0.addr, align 4 %ftosi.2 = fptosi float %p0.ld.2 to i64 - store i64 %ftosi.2, i64* %p3.addr, align 8 - %p3.ld.1 = load i64, i64* %p3.addr, align 8 + store i64 %ftosi.2, ptr %p3.addr, align 8 + %p3.ld.1 = load i64, ptr %p3.addr, align 8 %sitof.3 = sitofp i64 %p3.ld.1 to double - store double %sitof.3, double* %p1.addr, align 8 - %p1.ld.2 = load double, double* %p1.addr, align 8 + store double %sitof.3, ptr %p1.addr, align 8 + %p1.ld.2 = load double, ptr %p1.addr, align 8 %ftosi.3 = fptosi double %p1.ld.2 to i64 - store i64 %ftosi.3, i64* %p3.addr, align 8 - %p3.ld.2 = load i64, i64* %p3.addr, align 8 + store i64 %ftosi.3, ptr %p3.addr, align 8 + %p3.ld.2 = load i64, ptr %p3.addr, align 8 %trunc.0 = trunc i64 %p3.ld.2 to i32 - store i32 %trunc.0, i32* %p2.addr, align 4 - %p2.ld.2 = load i32, i32* %p2.addr, align 4 + store i32 %trunc.0, ptr %p2.addr, align 4 + %p2.ld.2 = load i32, ptr %p2.addr, align 4 %sext.0 = sext i32 %p2.ld.2 to i64 - store i64 %sext.0, i64* %p3.addr, align 8 - %p4.ld.0 = load i32, i32* %p4.addr, align 4 + store i64 %sext.0, ptr %p3.addr, align 8 + %p4.ld.0 = load i32, ptr %p4.addr, align 4 %uitof.0 = uitofp i32 %p4.ld.0 to float - store float %uitof.0, float* %p0.addr, align 4 - %p0.ld.3 = load float, float* %p0.addr, align 4 + store float %uitof.0, ptr %p0.addr, align 4 + %p0.ld.3 = load float, ptr %p0.addr, align 4 %ftoui.0 = fptoui float %p0.ld.3 to i32 - store i32 %ftoui.0, i32* %p4.addr, align 4 - %p4.ld.1 = load i32, i32* %p4.addr, align 4 + store i32 %ftoui.0, ptr %p4.addr, align 4 + %p4.ld.1 = load i32, ptr %p4.addr, align 4 %uitof.1 = uitofp i32 %p4.ld.1 to double - store double %uitof.1, double* %p1.addr, align 8 - %p1.ld.3 = load double, double* %p1.addr, align 8 + store double %uitof.1, ptr %p1.addr, align 8 + %p1.ld.3 = load double, ptr %p1.addr, align 8 %ftoui.1 = fptoui double %p1.ld.3 to i32 - store i32 %ftoui.1, i32* %p4.addr, align 4 - %p4.ld.2 = load i32, i32* %p4.addr, align 4 - store i32 %p4.ld.2, i32* %p2.addr, align 4 - %p2.ld.3 = load i32, i32* %p2.addr, align 4 - store i32 %p2.ld.3, i32* %p4.addr, align 4 - %p4.ld.3 = load i32, i32* %p4.addr, align 4 + store i32 %ftoui.1, ptr %p4.addr, align 4 + %p4.ld.2 = load i32, ptr %p4.addr, align 4 + store i32 %p4.ld.2, ptr %p2.addr, align 4 + %p2.ld.3 = load i32, ptr %p2.addr, align 4 + store i32 %p2.ld.3, ptr %p4.addr, align 4 + %p4.ld.3 = load i32, ptr %p4.addr, align 4 %zext.0 = zext i32 %p4.ld.3 to i64 - store i64 %zext.0, i64* %p3.addr, align 8 - %p3.ld.3 = load i64, i64* %p3.addr, align 8 + store i64 %zext.0, ptr %p3.addr, align 8 + %p3.ld.3 = load i64, ptr %p3.addr, align 8 %trunc.1 = trunc i64 %p3.ld.3 to i32 - store i32 %trunc.1, i32* %p4.addr, align 4 - %p5.ld.0 = load i64, i64* %p5.addr, align 8 + store i32 %trunc.1, ptr %p4.addr, align 4 + %p5.ld.0 = load i64, ptr %p5.addr, align 8 %uitof.2 = uitofp i64 %p5.ld.0 to float - store float %uitof.2, float* %p0.addr, align 4 - %p0.ld.4 = load float, float* %p0.addr, align 4 + store float %uitof.2, ptr %p0.addr, align 4 + %p0.ld.4 = load float, ptr %p0.addr, align 4 %ftoui.2 = fptoui float %p0.ld.4 to i64 - store i64 %ftoui.2, i64* %p5.addr, align 8 - %p5.ld.1 = load i64, i64* %p5.addr, align 8 + store i64 %ftoui.2, ptr %p5.addr, align 8 + %p5.ld.1 = load i64, ptr %p5.addr, align 8 %uitof.3 = uitofp i64 %p5.ld.1 to double - store double %uitof.3, double* %p1.addr, align 8 - %p1.ld.4 = load double, double* %p1.addr, align 8 + store double %uitof.3, ptr %p1.addr, align 8 + %p1.ld.4 = load double, ptr %p1.addr, align 8 %ftoui.3 = fptoui double %p1.ld.4 to i64 - store i64 %ftoui.3, i64* %p5.addr, align 8 - %p5.ld.2 = load i64, i64* %p5.addr, align 8 + store i64 %ftoui.3, ptr %p5.addr, align 8 + %p5.ld.2 = load i64, ptr %p5.addr, align 8 %trunc.2 = trunc i64 %p5.ld.2 to i32 - store i32 %trunc.2, i32* %p2.addr, align 4 - %p2.ld.4 = load i32, i32* %p2.addr, align 4 + store i32 %trunc.2, ptr %p2.addr, align 4 + %p2.ld.4 = load i32, ptr %p2.addr, align 4 %sext.1 = sext i32 %p2.ld.4 to i64 - store i64 %sext.1, i64* %p5.addr, align 8 - %p5.ld.3 = load i64, i64* %p5.addr, align 8 - store i64 %p5.ld.3, i64* %p3.addr, align 8 - %p3.ld.4 = load i64, i64* %p3.addr, align 8 - store i64 %p3.ld.4, i64* %p5.addr, align 8 - %p5.ld.4 = load i64, i64* %p5.addr, align 8 + store i64 %sext.1, ptr %p5.addr, align 8 + %p5.ld.3 = load i64, ptr %p5.addr, align 8 + store i64 %p5.ld.3, ptr %p3.addr, align 8 + %p3.ld.4 = load i64, ptr %p3.addr, align 8 + store i64 %p3.ld.4, ptr %p5.addr, align 8 + %p5.ld.4 = load i64, ptr %p5.addr, align 8 %trunc.3 = trunc i64 %p5.ld.4 to i32 - store i32 %trunc.3, i32* %p4.addr, align 4 - %p4.ld.4 = load i32, i32* %p4.addr, align 4 + store i32 %trunc.3, ptr %p4.addr, align 4 + %p4.ld.4 = load i32, ptr %p4.addr, align 4 %zext.1 = zext i32 %p4.ld.4 to i64 - store i64 %zext.1, i64* %p5.addr, align 8 + store i64 %zext.1, ptr %p5.addr, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -493,7 +491,7 @@ h.mkAssign(xvex4, convex4); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { + define void @foo(ptr nest %nest.0) #0 { entry: %tmp.3 = alloca { double, double }, align 8 %tmp.2 = alloca { float, float }, align 4 @@ -503,52 +501,36 @@ %b = alloca { float, float }, align 4 %x = alloca { double, double }, align 8 %y = alloca { double, double }, align 8 - %cast.0 = bitcast { float, float }* %a to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.0, i8* align 4 bitcast ({ float, float }* @const.0 to i8*), i64 8, i1 false) - %cast.1 = bitcast { float, float }* %b to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.1, i8* align 4 bitcast ({ float, float }* @const.0 to i8*), i64 8, i1 false) - %cast.2 = bitcast { double, double }* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.2, i8* align 8 bitcast ({ double, double }* @const.1 to i8*), i64 16, i1 false) - %cast.3 = bitcast { double, double }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.3, i8* align 8 bitcast ({ double, double }* @const.1 to i8*), i64 16, i1 false) - %cast.4 = bitcast { double, double }* %tmp.0 to i8* - %cast.5 = bitcast { double, double }* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.4, i8* align 8 %cast.5, i64 16, i1 false) - %field.0 = getelementptr inbounds { double, double }, { double, double }* %tmp.0, i32 0, i32 0 - %.real.ld.0 = load double, double* %field.0, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 @const.0, i64 8, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %b, ptr align 4 @const.0, i64 8, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 @const.1, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %y, ptr align 8 @const.1, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.0, ptr align 8 %x, i64 16, i1 false) + %field.0 = getelementptr inbounds { double, double }, ptr %tmp.0, i32 0, i32 0 + %.real.ld.0 = load double, ptr %field.0, align 8 %fptrunc.0 = fptrunc double %.real.ld.0 to float - %field.1 = getelementptr inbounds { double, double }, { double, double }* %tmp.0, i32 0, i32 1 - %.imag.ld.0 = load double, double* %field.1, align 8 + %field.1 = getelementptr inbounds { double, double }, ptr %tmp.0, i32 0, i32 1 + %.imag.ld.0 = load double, ptr %field.1, align 8 %fptrunc.1 = fptrunc double %.imag.ld.0 to float - %field.2 = getelementptr inbounds { float, float }, { float, float }* %tmp.1, i32 0, i32 0 - store float %fptrunc.0, float* %field.2, align 4 - %field.3 = getelementptr inbounds { float, float }, { float, float }* %tmp.1, i32 0, i32 1 - store float %fptrunc.1, float* %field.3, align 4 - %cast.6 = bitcast { float, float }* %a to i8* - %cast.7 = bitcast { float, float }* %tmp.1 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.6, i8* align 4 %cast.7, i64 8, i1 false) - %cast.8 = bitcast { float, float }* %tmp.2 to i8* - %cast.9 = bitcast { float, float }* %b to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.8, i8* align 4 %cast.9, i64 8, i1 false) - %field.4 = getelementptr inbounds { float, float }, { float, float }* %tmp.2, i32 0, i32 0 - %.real.ld.1 = load float, float* %field.4, align 4 + %field.2 = getelementptr inbounds { float, float }, ptr %tmp.1, i32 0, i32 0 + store float %fptrunc.0, ptr %field.2, align 4 + %field.3 = getelementptr inbounds { float, float }, ptr %tmp.1, i32 0, i32 1 + store float %fptrunc.1, ptr %field.3, align 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %tmp.1, i64 8, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp.2, ptr align 4 %b, i64 8, i1 false) + %field.4 = getelementptr inbounds { float, float }, ptr %tmp.2, i32 0, i32 0 + %.real.ld.1 = load float, ptr %field.4, align 4 %fpext.0 = fpext float %.real.ld.1 to double - %field.5 = getelementptr inbounds { float, float }, { float, float }* %tmp.2, i32 0, i32 1 - %.imag.ld.1 = load float, float* %field.5, align 4 + %field.5 = getelementptr inbounds { float, float }, ptr %tmp.2, i32 0, i32 1 + %.imag.ld.1 = load float, ptr %field.5, align 4 %fpext.1 = fpext float %.imag.ld.1 to double - %field.6 = getelementptr inbounds { double, double }, { double, double }* %tmp.3, i32 0, i32 0 - store double %fpext.0, double* %field.6, align 8 - %field.7 = getelementptr inbounds { double, double }, { double, double }* %tmp.3, i32 0, i32 1 - store double %fpext.1, double* %field.7, align 8 - %cast.10 = bitcast { double, double }* %y to i8* - %cast.11 = bitcast { double, double }* %tmp.3 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.10, i8* align 8 %cast.11, i64 16, i1 false) - %cast.12 = bitcast { float, float }* %a to i8* - %cast.13 = bitcast { float, float }* %b to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.12, i8* align 4 %cast.13, i64 8, i1 false) - %cast.14 = bitcast { double, double }* %x to i8* - %cast.15 = bitcast { double, double }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.14, i8* align 8 %cast.15, i64 16, i1 false) + %field.6 = getelementptr inbounds { double, double }, ptr %tmp.3, i32 0, i32 0 + store double %fpext.0, ptr %field.6, align 8 + %field.7 = getelementptr inbounds { double, double }, ptr %tmp.3, i32 0, i32 1 + store double %fpext.1, ptr %field.7, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %y, ptr align 8 %tmp.3, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %b, i64 8, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 16, i1 false) ret void } )RAW_RESULT"); @@ -630,61 +612,61 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %x, align 8 - store i64 0, i64* %y, align 8 - store double 0.000000e+00, double* %z, align 8 - %x.ld.0 = load i64, i64* %x, align 8 + store i64 0, ptr %x, align 8 + store i64 0, ptr %y, align 8 + store double 0.000000e+00, ptr %z, align 8 + %x.ld.0 = load i64, ptr %x, align 8 %icmp.0 = icmp eq i64 9, %x.ld.0 %zext.0 = zext i1 %icmp.0 to i8 - %x.ld.1 = load i64, i64* %x, align 8 + %x.ld.1 = load i64, ptr %x, align 8 %icmp.1 = icmp ne i64 9, %x.ld.1 %zext.1 = zext i1 %icmp.1 to i8 - %x.ld.2 = load i64, i64* %x, align 8 + %x.ld.2 = load i64, ptr %x, align 8 %icmp.2 = icmp slt i64 9, %x.ld.2 %zext.2 = zext i1 %icmp.2 to i8 - %x.ld.3 = load i64, i64* %x, align 8 + %x.ld.3 = load i64, ptr %x, align 8 %icmp.3 = icmp sle i64 9, %x.ld.3 %zext.3 = zext i1 %icmp.3 to i8 - %x.ld.4 = load i64, i64* %x, align 8 + %x.ld.4 = load i64, ptr %x, align 8 %icmp.4 = icmp sgt i64 9, %x.ld.4 %zext.4 = zext i1 %icmp.4 to i8 - %x.ld.5 = load i64, i64* %x, align 8 + %x.ld.5 = load i64, ptr %x, align 8 %icmp.5 = icmp sge i64 9, %x.ld.5 %zext.5 = zext i1 %icmp.5 to i8 - %y.ld.0 = load i64, i64* %y, align 8 + %y.ld.0 = load i64, ptr %y, align 8 %icmp.6 = icmp eq i64 9, %y.ld.0 %zext.6 = zext i1 %icmp.6 to i8 - %y.ld.1 = load i64, i64* %y, align 8 + %y.ld.1 = load i64, ptr %y, align 8 %icmp.7 = icmp ne i64 9, %y.ld.1 %zext.7 = zext i1 %icmp.7 to i8 - %y.ld.2 = load i64, i64* %y, align 8 + %y.ld.2 = load i64, ptr %y, align 8 %icmp.8 = icmp ult i64 9, %y.ld.2 %zext.8 = zext i1 %icmp.8 to i8 - %y.ld.3 = load i64, i64* %y, align 8 + %y.ld.3 = load i64, ptr %y, align 8 %icmp.9 = icmp ule i64 9, %y.ld.3 %zext.9 = zext i1 %icmp.9 to i8 - %y.ld.4 = load i64, i64* %y, align 8 + %y.ld.4 = load i64, ptr %y, align 8 %icmp.10 = icmp ugt i64 9, %y.ld.4 %zext.10 = zext i1 %icmp.10 to i8 - %y.ld.5 = load i64, i64* %y, align 8 + %y.ld.5 = load i64, ptr %y, align 8 %icmp.11 = icmp uge i64 9, %y.ld.5 %zext.11 = zext i1 %icmp.11 to i8 - %z.ld.0 = load double, double* %z, align 8 + %z.ld.0 = load double, ptr %z, align 8 %fcmp.0 = fcmp oeq double 9.000000e+00, %z.ld.0 %zext.12 = zext i1 %fcmp.0 to i8 - %z.ld.1 = load double, double* %z, align 8 + %z.ld.1 = load double, ptr %z, align 8 %fcmp.1 = fcmp une double 9.000000e+00, %z.ld.1 %zext.13 = zext i1 %fcmp.1 to i8 - %z.ld.2 = load double, double* %z, align 8 + %z.ld.2 = load double, ptr %z, align 8 %fcmp.2 = fcmp olt double 9.000000e+00, %z.ld.2 %zext.14 = zext i1 %fcmp.2 to i8 - %z.ld.3 = load double, double* %z, align 8 + %z.ld.3 = load double, ptr %z, align 8 %fcmp.3 = fcmp ole double 9.000000e+00, %z.ld.3 %zext.15 = zext i1 %fcmp.3 to i8 - %z.ld.4 = load double, double* %z, align 8 + %z.ld.4 = load double, ptr %z, align 8 %fcmp.4 = fcmp ogt double 9.000000e+00, %z.ld.4 %zext.16 = zext i1 %fcmp.4 to i8 - %z.ld.5 = load double, double* %z, align 8 + %z.ld.5 = load double, ptr %z, align 8 %fcmp.5 = fcmp oge double 9.000000e+00, %z.ld.5 %zext.17 = zext i1 %fcmp.5 to i8 )RAW_RESULT"); @@ -727,15 +709,15 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %x, align 8 - store double 0.000000e+00, double* %y, align 8 - %x.ld.0 = load i64, i64* %x, align 8 + store i64 0, ptr %x, align 8 + store double 0.000000e+00, ptr %y, align 8 + %x.ld.0 = load i64, ptr %x, align 8 %add.0 = add i64 9, %x.ld.0 - %x.ld.1 = load i64, i64* %x, align 8 + %x.ld.1 = load i64, ptr %x, align 8 %sub.0 = sub i64 9, %x.ld.1 - %y.ld.0 = load double, double* %y, align 8 + %y.ld.0 = load double, ptr %y, align 8 %fadd.0 = fadd double 9.000000e+00, %y.ld.0 - %y.ld.1 = load double, double* %y, align 8 + %y.ld.1 = load double, ptr %y, align 8 %fsub.0 = fsub double 9.000000e+00, %y.ld.1 )RAW_RESULT"); @@ -769,16 +751,16 @@ h.mkAssign(vex, ypzpw); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %x, align 8 - store i64 9, i64* %y, align 8 - store i64 10, i64* %z, align 8 - store i64 11, i64* %w, align 8 - %y.ld.0 = load i64, i64* %y, align 8 - %z.ld.0 = load i64, i64* %z, align 8 + store i64 0, ptr %x, align 8 + store i64 9, ptr %y, align 8 + store i64 10, ptr %z, align 8 + store i64 11, ptr %w, align 8 + %y.ld.0 = load i64, ptr %y, align 8 + %z.ld.0 = load i64, ptr %z, align 8 %add.0 = add i64 %y.ld.0, %z.ld.0 - %w.ld.0 = load i64, i64* %w, align 8 + %w.ld.0 = load i64, ptr %w, align 8 %add.1 = add i64 %add.0, %w.ld.0 - store i64 %add.1, i64* %x, align 8 + store i64 %add.1, ptr %x, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -825,65 +807,65 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %x, align 8 - store i64 0, i64* %y, align 8 - store i8 0, i8* %z, align 1 - store i64 0, i64* %x2, align 8 - store i64 0, i64* %y2, align 8 - store i8 0, i8* %z2, align 1 - %x.ld.0 = load i64, i64* %x, align 8 - %x2.ld.0 = load i64, i64* %x2, align 8 + store i64 0, ptr %x, align 8 + store i64 0, ptr %y, align 8 + store i8 0, ptr %z, align 1 + store i64 0, ptr %x2, align 8 + store i64 0, ptr %y2, align 8 + store i8 0, ptr %z2, align 1 + %x.ld.0 = load i64, ptr %x, align 8 + %x2.ld.0 = load i64, ptr %x2, align 8 %iand.0 = and i64 %x.ld.0, %x2.ld.0 - %x.ld.1 = load i64, i64* %x, align 8 - %x2.ld.1 = load i64, i64* %x2, align 8 + %x.ld.1 = load i64, ptr %x, align 8 + %x2.ld.1 = load i64, ptr %x2, align 8 %ior.0 = or i64 %x.ld.1, %x2.ld.1 - %x.ld.2 = load i64, i64* %x, align 8 - %x2.ld.2 = load i64, i64* %x2, align 8 + %x.ld.2 = load i64, ptr %x, align 8 + %x2.ld.2 = load i64, ptr %x2, align 8 %iand.1 = and i64 %x.ld.2, %x2.ld.2 - %x.ld.3 = load i64, i64* %x, align 8 - %x2.ld.3 = load i64, i64* %x2, align 8 + %x.ld.3 = load i64, ptr %x, align 8 + %x2.ld.3 = load i64, ptr %x2, align 8 %ior.1 = or i64 %x.ld.3, %x2.ld.3 - %x.ld.4 = load i64, i64* %x, align 8 - %x2.ld.4 = load i64, i64* %x2, align 8 + %x.ld.4 = load i64, ptr %x, align 8 + %x2.ld.4 = load i64, ptr %x2, align 8 %xor.0 = xor i64 %x.ld.4, %x2.ld.4 - %x.ld.5 = load i64, i64* %x, align 8 - %x2.ld.5 = load i64, i64* %x2, align 8 + %x.ld.5 = load i64, ptr %x, align 8 + %x2.ld.5 = load i64, ptr %x2, align 8 %iand.2 = and i64 %x.ld.5, %x2.ld.5 - %y.ld.0 = load i64, i64* %y, align 8 - %y2.ld.0 = load i64, i64* %y2, align 8 + %y.ld.0 = load i64, ptr %y, align 8 + %y2.ld.0 = load i64, ptr %y2, align 8 %iand.3 = and i64 %y.ld.0, %y2.ld.0 - %y.ld.1 = load i64, i64* %y, align 8 - %y2.ld.1 = load i64, i64* %y2, align 8 + %y.ld.1 = load i64, ptr %y, align 8 + %y2.ld.1 = load i64, ptr %y2, align 8 %ior.2 = or i64 %y.ld.1, %y2.ld.1 - %y.ld.2 = load i64, i64* %y, align 8 - %y2.ld.2 = load i64, i64* %y2, align 8 + %y.ld.2 = load i64, ptr %y, align 8 + %y2.ld.2 = load i64, ptr %y2, align 8 %iand.4 = and i64 %y.ld.2, %y2.ld.2 - %y.ld.3 = load i64, i64* %y, align 8 - %y2.ld.3 = load i64, i64* %y2, align 8 + %y.ld.3 = load i64, ptr %y, align 8 + %y2.ld.3 = load i64, ptr %y2, align 8 %ior.3 = or i64 %y.ld.3, %y2.ld.3 - %y.ld.4 = load i64, i64* %y, align 8 - %y2.ld.4 = load i64, i64* %y2, align 8 + %y.ld.4 = load i64, ptr %y, align 8 + %y2.ld.4 = load i64, ptr %y2, align 8 %xor.1 = xor i64 %y.ld.4, %y2.ld.4 - %y.ld.5 = load i64, i64* %y, align 8 - %y2.ld.5 = load i64, i64* %y2, align 8 + %y.ld.5 = load i64, ptr %y, align 8 + %y2.ld.5 = load i64, ptr %y2, align 8 %iand.5 = and i64 %y.ld.5, %y2.ld.5 - %z.ld.0 = load i8, i8* %z, align 1 - %z2.ld.0 = load i8, i8* %z2, align 1 + %z.ld.0 = load i8, ptr %z, align 1 + %z2.ld.0 = load i8, ptr %z2, align 1 %iand.6 = and i8 %z.ld.0, %z2.ld.0 - %z.ld.1 = load i8, i8* %z, align 1 - %z2.ld.1 = load i8, i8* %z2, align 1 + %z.ld.1 = load i8, ptr %z, align 1 + %z2.ld.1 = load i8, ptr %z2, align 1 %ior.4 = or i8 %z.ld.1, %z2.ld.1 - %z.ld.2 = load i8, i8* %z, align 1 - %z2.ld.2 = load i8, i8* %z2, align 1 + %z.ld.2 = load i8, ptr %z, align 1 + %z2.ld.2 = load i8, ptr %z2, align 1 %iand.7 = and i8 %z.ld.2, %z2.ld.2 - %z.ld.3 = load i8, i8* %z, align 1 - %z2.ld.3 = load i8, i8* %z2, align 1 + %z.ld.3 = load i8, ptr %z, align 1 + %z2.ld.3 = load i8, ptr %z2, align 1 %ior.5 = or i8 %z.ld.3, %z2.ld.3 - %z.ld.4 = load i8, i8* %z, align 1 - %z2.ld.4 = load i8, i8* %z2, align 1 + %z.ld.4 = load i8, ptr %z, align 1 + %z2.ld.4 = load i8, ptr %z2, align 1 %xor.2 = xor i8 %z.ld.4, %z2.ld.4 - %z.ld.5 = load i8, i8* %z, align 1 - %z2.ld.5 = load i8, i8* %z2, align 1 + %z.ld.5 = load i8, ptr %z, align 1 + %z2.ld.5 = load i8, ptr %z2, align 1 %iand.8 = and i8 %z.ld.5, %z2.ld.5 )RAW_RESULT"); @@ -931,24 +913,24 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i16 0, i16* %x, align 2 - store i16 0, i16* %y, align 2 - store double 0.000000e+00, double* %z, align 8 - %x.ld.0 = load i16, i16* %x, align 2 + store i16 0, ptr %x, align 2 + store i16 0, ptr %y, align 2 + store double 0.000000e+00, ptr %z, align 8 + %x.ld.0 = load i16, ptr %x, align 2 %mul.0 = mul i16 -17, %x.ld.0 - %x.ld.1 = load i16, i16* %x, align 2 + %x.ld.1 = load i16, ptr %x, align 2 %div.0 = sdiv i16 -17, %x.ld.1 - %x.ld.2 = load i16, i16* %x, align 2 + %x.ld.2 = load i16, ptr %x, align 2 %mod.0 = srem i16 -17, %x.ld.2 - %y.ld.0 = load i16, i16* %y, align 2 + %y.ld.0 = load i16, ptr %y, align 2 %mul.1 = mul i16 13, %y.ld.0 - %y.ld.1 = load i16, i16* %y, align 2 + %y.ld.1 = load i16, ptr %y, align 2 %div.1 = udiv i16 13, %y.ld.1 - %y.ld.2 = load i16, i16* %y, align 2 + %y.ld.2 = load i16, ptr %y, align 2 %mod.1 = urem i16 13, %y.ld.2 - %z.ld.0 = load double, double* %z, align 8 + %z.ld.0 = load double, ptr %z, align 8 %fmul.0 = fmul double 9.000000e+00, %z.ld.0 - %z.ld.1 = load double, double* %z, align 8 + %z.ld.1 = load double, ptr %z, align 8 %fdiv.0 = fdiv double 9.000000e+00, %z.ld.1 )RAW_RESULT"); @@ -1011,28 +993,28 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %x, align 8 - store i64 0, i64* %y, align 8 - store i64 0, i64* %s, align 8 - store i32 0, i32* %z, align 4 - %x.ld.0 = load i64, i64* %x, align 8 - %s.ld.0 = load i64, i64* %s, align 8 + store i64 0, ptr %x, align 8 + store i64 0, ptr %y, align 8 + store i64 0, ptr %s, align 8 + store i32 0, ptr %z, align 4 + %x.ld.0 = load i64, ptr %x, align 8 + %s.ld.0 = load i64, ptr %s, align 8 %shl.0 = shl i64 %x.ld.0, %s.ld.0 - %x.ld.1 = load i64, i64* %x, align 8 - %s.ld.1 = load i64, i64* %s, align 8 + %x.ld.1 = load i64, ptr %x, align 8 + %s.ld.1 = load i64, ptr %s, align 8 %shr.0 = ashr i64 %x.ld.1, %s.ld.1 - %y.ld.0 = load i64, i64* %y, align 8 - %s.ld.2 = load i64, i64* %s, align 8 + %y.ld.0 = load i64, ptr %y, align 8 + %s.ld.2 = load i64, ptr %s, align 8 %shl.1 = shl i64 %y.ld.0, %s.ld.2 - %y.ld.1 = load i64, i64* %y, align 8 - %s.ld.3 = load i64, i64* %s, align 8 + %y.ld.1 = load i64, ptr %y, align 8 + %s.ld.3 = load i64, ptr %s, align 8 %shr.1 = lshr i64 %y.ld.1, %s.ld.3 - %x.ld.2 = load i64, i64* %x, align 8 - %z.ld.0 = load i32, i32* %z, align 4 + %x.ld.2 = load i64, ptr %x, align 8 + %z.ld.0 = load i32, ptr %z, align 4 %zext.0 = zext i32 %z.ld.0 to i64 %shl.2 = shl i64 %x.ld.2, %zext.0 - %z.ld.1 = load i32, i32* %z, align 4 - %y.ld.2 = load i64, i64* %y, align 8 + %z.ld.1 = load i32, ptr %z, align 4 + %y.ld.2 = load i64, ptr %y, align 8 %trunc.0 = trunc i64 %y.ld.2 to i32 %shr.2 = lshr i32 %z.ld.1, %trunc.0 )RAW_RESULT"); @@ -1074,7 +1056,7 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { + define void @foo(ptr nest %nest.0) #0 { entry: %tmp.12 = alloca { double, double }, align 8 %tmp.11 = alloca { double, double }, align 8 @@ -1093,134 +1075,105 @@ %y = alloca { double, double }, align 8 %z = alloca { double, double }, align 8 %b = alloca i8, align 1 - %cast.0 = bitcast { double, double }* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ({ double, double }* @const.0 to i8*), i64 16, i1 false) - %cast.1 = bitcast { double, double }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.1, i8* align 8 bitcast ({ double, double }* @const.0 to i8*), i64 16, i1 false) - %cast.2 = bitcast { double, double }* %z to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.2, i8* align 8 bitcast ({ double, double }* @const.0 to i8*), i64 16, i1 false) - store i8 0, i8* %b, align 1 - %cast.3 = bitcast { double, double }* %tmp.0 to i8* - %cast.4 = bitcast { double, double }* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.3, i8* align 8 %cast.4, i64 16, i1 false) - %cast.5 = bitcast { double, double }* %tmp.1 to i8* - %cast.6 = bitcast { double, double }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.5, i8* align 8 %cast.6, i64 16, i1 false) - %field.0 = getelementptr inbounds { double, double }, { double, double }* %tmp.0, i32 0, i32 0 - %.real.ld.0 = load double, double* %field.0, align 8 - %field.1 = getelementptr inbounds { double, double }, { double, double }* %tmp.1, i32 0, i32 0 - %.real.ld.1 = load double, double* %field.1, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 @const.0, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %y, ptr align 8 @const.0, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %z, ptr align 8 @const.0, i64 16, i1 false) + store i8 0, ptr %b, align 1 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.0, ptr align 8 %x, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.1, ptr align 8 %y, i64 16, i1 false) + %field.0 = getelementptr inbounds { double, double }, ptr %tmp.0, i32 0, i32 0 + %.real.ld.0 = load double, ptr %field.0, align 8 + %field.1 = getelementptr inbounds { double, double }, ptr %tmp.1, i32 0, i32 0 + %.real.ld.1 = load double, ptr %field.1, align 8 %fadd.0 = fadd double %.real.ld.0, %.real.ld.1 - %field.2 = getelementptr inbounds { double, double }, { double, double }* %tmp.0, i32 0, i32 1 - %.imag.ld.0 = load double, double* %field.2, align 8 - %field.3 = getelementptr inbounds { double, double }, { double, double }* %tmp.1, i32 0, i32 1 - %.imag.ld.1 = load double, double* %field.3, align 8 + %field.2 = getelementptr inbounds { double, double }, ptr %tmp.0, i32 0, i32 1 + %.imag.ld.0 = load double, ptr %field.2, align 8 + %field.3 = getelementptr inbounds { double, double }, ptr %tmp.1, i32 0, i32 1 + %.imag.ld.1 = load double, ptr %field.3, align 8 %fadd.1 = fadd double %.imag.ld.0, %.imag.ld.1 - %field.4 = getelementptr inbounds { double, double }, { double, double }* %tmp.2, i32 0, i32 0 - store double %fadd.0, double* %field.4, align 8 - %field.5 = getelementptr inbounds { double, double }, { double, double }* %tmp.2, i32 0, i32 1 - store double %fadd.1, double* %field.5, align 8 - %cast.7 = bitcast { double, double }* %z to i8* - %cast.8 = bitcast { double, double }* %tmp.2 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.7, i8* align 8 %cast.8, i64 16, i1 false) - %cast.9 = bitcast { double, double }* %tmp.3 to i8* - %cast.10 = bitcast { double, double }* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.9, i8* align 8 %cast.10, i64 16, i1 false) - %cast.11 = bitcast { double, double }* %tmp.4 to i8* - %cast.12 = bitcast { double, double }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.11, i8* align 8 %cast.12, i64 16, i1 false) - %field.6 = getelementptr inbounds { double, double }, { double, double }* %tmp.3, i32 0, i32 0 - %.real.ld.2 = load double, double* %field.6, align 8 - %field.7 = getelementptr inbounds { double, double }, { double, double }* %tmp.4, i32 0, i32 0 - %.real.ld.3 = load double, double* %field.7, align 8 + %field.4 = getelementptr inbounds { double, double }, ptr %tmp.2, i32 0, i32 0 + store double %fadd.0, ptr %field.4, align 8 + %field.5 = getelementptr inbounds { double, double }, ptr %tmp.2, i32 0, i32 1 + store double %fadd.1, ptr %field.5, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %z, ptr align 8 %tmp.2, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.3, ptr align 8 %x, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.4, ptr align 8 %y, i64 16, i1 false) + %field.6 = getelementptr inbounds { double, double }, ptr %tmp.3, i32 0, i32 0 + %.real.ld.2 = load double, ptr %field.6, align 8 + %field.7 = getelementptr inbounds { double, double }, ptr %tmp.4, i32 0, i32 0 + %.real.ld.3 = load double, ptr %field.7, align 8 %fsub.0 = fsub double %.real.ld.2, %.real.ld.3 - %field.8 = getelementptr inbounds { double, double }, { double, double }* %tmp.3, i32 0, i32 1 - %.imag.ld.2 = load double, double* %field.8, align 8 - %field.9 = getelementptr inbounds { double, double }, { double, double }* %tmp.4, i32 0, i32 1 - %.imag.ld.3 = load double, double* %field.9, align 8 + %field.8 = getelementptr inbounds { double, double }, ptr %tmp.3, i32 0, i32 1 + %.imag.ld.2 = load double, ptr %field.8, align 8 + %field.9 = getelementptr inbounds { double, double }, ptr %tmp.4, i32 0, i32 1 + %.imag.ld.3 = load double, ptr %field.9, align 8 %fsub.1 = fsub double %.imag.ld.2, %.imag.ld.3 - %field.10 = getelementptr inbounds { double, double }, { double, double }* %tmp.5, i32 0, i32 0 - store double %fsub.0, double* %field.10, align 8 - %field.11 = getelementptr inbounds { double, double }, { double, double }* %tmp.5, i32 0, i32 1 - store double %fsub.1, double* %field.11, align 8 - %cast.13 = bitcast { double, double }* %z to i8* - %cast.14 = bitcast { double, double }* %tmp.5 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.13, i8* align 8 %cast.14, i64 16, i1 false) - %cast.15 = bitcast { double, double }* %tmp.6 to i8* - %cast.16 = bitcast { double, double }* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.15, i8* align 8 %cast.16, i64 16, i1 false) - %cast.17 = bitcast { double, double }* %tmp.7 to i8* - %cast.18 = bitcast { double, double }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.17, i8* align 8 %cast.18, i64 16, i1 false) - %field.12 = getelementptr inbounds { double, double }, { double, double }* %tmp.6, i32 0, i32 0 - %.real.ld.4 = load double, double* %field.12, align 8 - %field.13 = getelementptr inbounds { double, double }, { double, double }* %tmp.7, i32 0, i32 0 - %.real.ld.5 = load double, double* %field.13, align 8 + %field.10 = getelementptr inbounds { double, double }, ptr %tmp.5, i32 0, i32 0 + store double %fsub.0, ptr %field.10, align 8 + %field.11 = getelementptr inbounds { double, double }, ptr %tmp.5, i32 0, i32 1 + store double %fsub.1, ptr %field.11, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %z, ptr align 8 %tmp.5, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.6, ptr align 8 %x, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.7, ptr align 8 %y, i64 16, i1 false) + %field.12 = getelementptr inbounds { double, double }, ptr %tmp.6, i32 0, i32 0 + %.real.ld.4 = load double, ptr %field.12, align 8 + %field.13 = getelementptr inbounds { double, double }, ptr %tmp.7, i32 0, i32 0 + %.real.ld.5 = load double, ptr %field.13, align 8 %fmul.0 = fmul double %.real.ld.4, %.real.ld.5 - %field.14 = getelementptr inbounds { double, double }, { double, double }* %tmp.6, i32 0, i32 1 - %.imag.ld.4 = load double, double* %field.14, align 8 - %field.15 = getelementptr inbounds { double, double }, { double, double }* %tmp.7, i32 0, i32 1 - %.imag.ld.5 = load double, double* %field.15, align 8 + %field.14 = getelementptr inbounds { double, double }, ptr %tmp.6, i32 0, i32 1 + %.imag.ld.4 = load double, ptr %field.14, align 8 + %field.15 = getelementptr inbounds { double, double }, ptr %tmp.7, i32 0, i32 1 + %.imag.ld.5 = load double, ptr %field.15, align 8 %fmul.1 = fmul double %.imag.ld.4, %.imag.ld.5 %fsub.2 = fsub double %fmul.0, %fmul.1 - %field.16 = getelementptr inbounds { double, double }, { double, double }* %tmp.6, i32 0, i32 0 - %.field.ld.0 = load double, double* %field.16, align 8 - %field.17 = getelementptr inbounds { double, double }, { double, double }* %tmp.7, i32 0, i32 1 - %.field.ld.1 = load double, double* %field.17, align 8 + %field.16 = getelementptr inbounds { double, double }, ptr %tmp.6, i32 0, i32 0 + %.field.ld.0 = load double, ptr %field.16, align 8 + %field.17 = getelementptr inbounds { double, double }, ptr %tmp.7, i32 0, i32 1 + %.field.ld.1 = load double, ptr %field.17, align 8 %fmul.2 = fmul double %.field.ld.0, %.field.ld.1 - %field.18 = getelementptr inbounds { double, double }, { double, double }* %tmp.6, i32 0, i32 1 - %.field.ld.2 = load double, double* %field.18, align 8 - %field.19 = getelementptr inbounds { double, double }, { double, double }* %tmp.7, i32 0, i32 0 - %.field.ld.3 = load double, double* %field.19, align 8 + %field.18 = getelementptr inbounds { double, double }, ptr %tmp.6, i32 0, i32 1 + %.field.ld.2 = load double, ptr %field.18, align 8 + %field.19 = getelementptr inbounds { double, double }, ptr %tmp.7, i32 0, i32 0 + %.field.ld.3 = load double, ptr %field.19, align 8 %fmul.3 = fmul double %.field.ld.2, %.field.ld.3 %fadd.2 = fadd double %fmul.2, %fmul.3 - %field.20 = getelementptr inbounds { double, double }, { double, double }* %tmp.8, i32 0, i32 0 - store double %fsub.2, double* %field.20, align 8 - %field.21 = getelementptr inbounds { double, double }, { double, double }* %tmp.8, i32 0, i32 1 - store double %fadd.2, double* %field.21, align 8 - %cast.19 = bitcast { double, double }* %z to i8* - %cast.20 = bitcast { double, double }* %tmp.8 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.19, i8* align 8 %cast.20, i64 16, i1 false) - %cast.21 = bitcast { double, double }* %tmp.9 to i8* - %cast.22 = bitcast { double, double }* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.21, i8* align 8 %cast.22, i64 16, i1 false) - %cast.23 = bitcast { double, double }* %tmp.10 to i8* - %cast.24 = bitcast { double, double }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.23, i8* align 8 %cast.24, i64 16, i1 false) - %field.22 = getelementptr inbounds { double, double }, { double, double }* %tmp.9, i32 0, i32 0 - %.real.ld.6 = load double, double* %field.22, align 8 - %field.23 = getelementptr inbounds { double, double }, { double, double }* %tmp.10, i32 0, i32 0 - %.real.ld.7 = load double, double* %field.23, align 8 + %field.20 = getelementptr inbounds { double, double }, ptr %tmp.8, i32 0, i32 0 + store double %fsub.2, ptr %field.20, align 8 + %field.21 = getelementptr inbounds { double, double }, ptr %tmp.8, i32 0, i32 1 + store double %fadd.2, ptr %field.21, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %z, ptr align 8 %tmp.8, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.9, ptr align 8 %x, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.10, ptr align 8 %y, i64 16, i1 false) + %field.22 = getelementptr inbounds { double, double }, ptr %tmp.9, i32 0, i32 0 + %.real.ld.6 = load double, ptr %field.22, align 8 + %field.23 = getelementptr inbounds { double, double }, ptr %tmp.10, i32 0, i32 0 + %.real.ld.7 = load double, ptr %field.23, align 8 %fcmp.0 = fcmp oeq double %.real.ld.6, %.real.ld.7 %zext.0 = zext i1 %fcmp.0 to i8 - %field.24 = getelementptr inbounds { double, double }, { double, double }* %tmp.9, i32 0, i32 1 - %.imag.ld.6 = load double, double* %field.24, align 8 - %field.25 = getelementptr inbounds { double, double }, { double, double }* %tmp.10, i32 0, i32 1 - %.imag.ld.7 = load double, double* %field.25, align 8 + %field.24 = getelementptr inbounds { double, double }, ptr %tmp.9, i32 0, i32 1 + %.imag.ld.6 = load double, ptr %field.24, align 8 + %field.25 = getelementptr inbounds { double, double }, ptr %tmp.10, i32 0, i32 1 + %.imag.ld.7 = load double, ptr %field.25, align 8 %fcmp.1 = fcmp oeq double %.imag.ld.6, %.imag.ld.7 %zext.1 = zext i1 %fcmp.1 to i8 %iand.0 = and i8 %zext.0, %zext.1 - store i8 %iand.0, i8* %b, align 1 - %cast.25 = bitcast { double, double }* %tmp.11 to i8* - %cast.26 = bitcast { double, double }* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.25, i8* align 8 %cast.26, i64 16, i1 false) - %cast.27 = bitcast { double, double }* %tmp.12 to i8* - %cast.28 = bitcast { double, double }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.27, i8* align 8 %cast.28, i64 16, i1 false) - %field.26 = getelementptr inbounds { double, double }, { double, double }* %tmp.11, i32 0, i32 0 - %.real.ld.8 = load double, double* %field.26, align 8 - %field.27 = getelementptr inbounds { double, double }, { double, double }* %tmp.12, i32 0, i32 0 - %.real.ld.9 = load double, double* %field.27, align 8 + store i8 %iand.0, ptr %b, align 1 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.11, ptr align 8 %x, i64 16, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp.12, ptr align 8 %y, i64 16, i1 false) + %field.26 = getelementptr inbounds { double, double }, ptr %tmp.11, i32 0, i32 0 + %.real.ld.8 = load double, ptr %field.26, align 8 + %field.27 = getelementptr inbounds { double, double }, ptr %tmp.12, i32 0, i32 0 + %.real.ld.9 = load double, ptr %field.27, align 8 %fcmp.2 = fcmp une double %.real.ld.8, %.real.ld.9 %zext.2 = zext i1 %fcmp.2 to i8 - %field.28 = getelementptr inbounds { double, double }, { double, double }* %tmp.11, i32 0, i32 1 - %.imag.ld.8 = load double, double* %field.28, align 8 - %field.29 = getelementptr inbounds { double, double }, { double, double }* %tmp.12, i32 0, i32 1 - %.imag.ld.9 = load double, double* %field.29, align 8 + %field.28 = getelementptr inbounds { double, double }, ptr %tmp.11, i32 0, i32 1 + %.imag.ld.8 = load double, ptr %field.28, align 8 + %field.29 = getelementptr inbounds { double, double }, ptr %tmp.12, i32 0, i32 1 + %.imag.ld.9 = load double, ptr %field.29, align 8 %fcmp.3 = fcmp une double %.imag.ld.8, %.imag.ld.9 %zext.3 = zext i1 %fcmp.3 to i8 %ior.0 = or i8 %zext.2, %zext.3 - store i8 %ior.0, i8* %b, align 1 + store i8 %ior.0, ptr %b, align 1 ret void } )RAW_RESULT"); @@ -1266,22 +1219,21 @@ h.mkAssign(xvex3, compex); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store double 0.000000e+00, double* %a, align 8 - store double 0.000000e+00, double* %b, align 8 - %cast.0 = bitcast { double, double }* %x to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ({ double, double }* @const.0 to i8*), i64 16, i1 false) - %field.0 = getelementptr inbounds { double, double }, { double, double }* %x, i32 0, i32 0 - %x.real.ld.0 = load double, double* %field.0, align 8 - store double %x.real.ld.0, double* %a, align 8 - %field.1 = getelementptr inbounds { double, double }, { double, double }* %x, i32 0, i32 1 - %x.imag.ld.0 = load double, double* %field.1, align 8 - store double %x.imag.ld.0, double* %b, align 8 - %b.ld.0 = load double, double* %b, align 8 - %a.ld.0 = load double, double* %a, align 8 - %field.2 = getelementptr inbounds { double, double }, { double, double }* %x, i32 0, i32 0 - store double %b.ld.0, double* %field.2, align 8 - %field.3 = getelementptr inbounds { double, double }, { double, double }* %x, i32 0, i32 1 - store double %a.ld.0, double* %field.3, align 8 + store double 0.000000e+00, ptr %a, align 8 + store double 0.000000e+00, ptr %b, align 8 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 @const.0, i64 16, i1 false) + %field.0 = getelementptr inbounds { double, double }, ptr %x, i32 0, i32 0 + %x.real.ld.0 = load double, ptr %field.0, align 8 + store double %x.real.ld.0, ptr %a, align 8 + %field.1 = getelementptr inbounds { double, double }, ptr %x, i32 0, i32 1 + %x.imag.ld.0 = load double, ptr %field.1, align 8 + store double %x.imag.ld.0, ptr %b, align 8 + %b.ld.0 = load double, ptr %b, align 8 + %a.ld.0 = load double, ptr %a, align 8 + %field.2 = getelementptr inbounds { double, double }, ptr %x, i32 0, i32 0 + store double %b.ld.0, ptr %field.2, align 8 + %field.3 = getelementptr inbounds { double, double }, ptr %x, i32 0, i32 1 + store double %a.ld.0, ptr %field.3, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -1299,7 +1251,7 @@ { Bexpression *snil = be->string_constant_expression(""); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - i8* null + ptr null )RAW_RESULT"); bool isOK = h.expectValue(snil->value(), exp); EXPECT_TRUE(isOK && "Value does not have expected contents"); @@ -1308,7 +1260,7 @@ { Bexpression *sblah = be->string_constant_expression("blah"); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - i8* getelementptr inbounds ([5 x i8], [5 x i8]* @const.0, i32 0, i32 0) + @const.0 = private constant [5 x i8] c"blah\00", align 1 )RAW_RESULT"); bool isOK = h.expectValue(sblah->value(), exp); EXPECT_TRUE(isOK && "Value does not have expected contents"); @@ -1342,28 +1294,28 @@ h.mkExprStmt(condex); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { + define void @foo(ptr nest %nest.0) #0 { entry: %a = alloca i64, align 8 %b = alloca i64, align 8 - store i64 0, i64* %a, align 8 - store i64 0, i64* %b, align 8 - %a.ld.0 = load i64, i64* %a, align 8 - %b.ld.0 = load i64, i64* %b, align 8 + store i64 0, ptr %a, align 8 + store i64 0, ptr %b, align 8 + %a.ld.0 = load i64, ptr %a, align 8 + %b.ld.0 = load i64, ptr %b, align 8 %icmp.0 = icmp slt i64 %a.ld.0, %b.ld.0 %zext.0 = zext i1 %icmp.0 to i8 %trunc.0 = trunc i8 %zext.0 to i1 br i1 %trunc.0, label %then.0, label %else.0 - + then.0: ; preds = %entry - call void @foo(i8* nest undef) + call void @foo(ptr nest undef) br label %fallthrough.0 - + fallthrough.0: ; preds = %else.0, %then.0 ret void - + else.0: ; preds = %entry - call void @foo(i8* nest undef) + call void @foo(ptr nest undef) br label %fallthrough.0 } )RAW_RESULT"); @@ -1399,24 +1351,24 @@ h.mkExprStmt(condex); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { + define void @foo(ptr nest %nest.0) #0 { entry: %a = alloca i64, align 8 %tmpv.0 = alloca i64, align 8 - store i64 0, i64* %a, align 8 + store i64 0, ptr %a, align 8 br i1 true, label %then.0, label %else.0 - + then.0: ; preds = %entry - call void @foo(i8* nest undef) + call void @foo(ptr nest undef) br label %fallthrough.0 - + fallthrough.0: ; preds = %else.0, %then.0 - %tmpv.0.ld.0 = load i64, i64* %tmpv.0, align 8 + %tmpv.0.ld.0 = load i64, ptr %tmpv.0, align 8 ret void - + else.0: ; preds = %entry - %a.ld.0 = load i64, i64* %a, align 8 - store i64 %a.ld.0, i64* %tmpv.0, align 8 + %a.ld.0 = load i64, ptr %a, align 8 + store i64 %a.ld.0, ptr %tmpv.0, align 8 br label %fallthrough.0 } )RAW_RESULT"); @@ -1455,35 +1407,30 @@ h.mkLocal("a", s2t, cond); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo({ [16 x i32], i32 }* sret({ [16 x i32], i32 }) %sret.formal.0, i8* nest %nest.0, { [16 x i32], i32 }* byval({ [16 x i32], i32 }) %p0, i32 %p1) #0 { - entry: - %p1.addr = alloca i32, align 4 - %a = alloca { [16 x i32], i32 }, align 4 - %tmpv.0 = alloca { [16 x i32], i32 }, align 4 - store i32 %p1, i32* %p1.addr, align 4 - %p1.ld.0 = load i32, i32* %p1.addr, align 4 - %icmp.0 = icmp slt i32 %p1.ld.0, 7 - %zext.0 = zext i1 %icmp.0 to i8 - %trunc.0 = trunc i8 %zext.0 to i1 - br i1 %trunc.0, label %then.0, label %else.0 - - then.0: ; preds = %entry - %cast.0 = bitcast { [16 x i32], i32 }* %tmpv.0 to i8* - %cast.1 = bitcast { [16 x i32], i32 }* %p0 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.0, i8* align 4 %cast.1, i64 68, i1 false) - br label %fallthrough.0 - - fallthrough.0: ; preds = %else.0, %then.0 - %cast.3 = bitcast { [16 x i32], i32 }* %a to i8* - %cast.4 = bitcast { [16 x i32], i32 }* %tmpv.0 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.3, i8* align 4 %cast.4, i64 68, i1 false) - ret void - - else.0: ; preds = %entry - %cast.2 = bitcast { [16 x i32], i32 }* %tmpv.0 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.2, i8* align 4 bitcast ({ [16 x i32], i32 }* @const.0 to i8*), i64 68, i1 false) - br label %fallthrough.0 - } + define void @foo(ptr sret({ [16 x i32], i32 }) %sret.formal.0, ptr nest %nest.0, ptr byval({ [16 x i32], i32 }) %p0, i32 %p1) #0 { + entry: + %p1.addr = alloca i32, align 4 + %a = alloca { [16 x i32], i32 }, align 4 + %tmpv.0 = alloca { [16 x i32], i32 }, align 4 + store i32 %p1, ptr %p1.addr, align 4 + %p1.ld.0 = load i32, ptr %p1.addr, align 4 + %icmp.0 = icmp slt i32 %p1.ld.0, 7 + %zext.0 = zext i1 %icmp.0 to i8 + %trunc.0 = trunc i8 %zext.0 to i1 + br i1 %trunc.0, label %then.0, label %else.0 + + then.0: ; preds = %entry + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmpv.0, ptr align 4 %p0, i64 68, i1 false) + br label %fallthrough.0 + + fallthrough.0: ; preds = %else.0, %then.0 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %tmpv.0, i64 68, i1 false) + ret void + + else.0: ; preds = %entry + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmpv.0, ptr align 4 @const.0, i64 68, i1 false) + br label %fallthrough.0 + } )RAW_RESULT"); bool broken = h.finish(StripDebugInfo); @@ -1530,35 +1477,30 @@ h.mkLocal("a", s2t, cond); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo({ [16 x i32], i32 }* sret({ [16 x i32], i32 }) %sret.formal.0, i8* nest %nest.0, { [16 x i32], i32 }* %p0, i32 %p1) #0 { - entry: - %p1.addr = alloca i32, align 4 - %a = alloca { [16 x i32], i32 }, align 4 - %tmpv.0 = alloca { [16 x i32], i32 }, align 4 - store i32 %p1, i32* %p1.addr, align 4 - %p1.ld.0 = load i32, i32* %p1.addr, align 4 - %icmp.0 = icmp slt i32 %p1.ld.0, 7 - %zext.0 = zext i1 %icmp.0 to i8 - %trunc.0 = trunc i8 %zext.0 to i1 - br i1 %trunc.0, label %then.0, label %else.0 - - then.0: ; preds = %entry - %cast.0 = bitcast { [16 x i32], i32 }* %tmpv.0 to i8* - %cast.1 = bitcast { [16 x i32], i32 }* %p0 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.0, i8* align 4 %cast.1, i64 68, i1 false) - br label %fallthrough.0 - - fallthrough.0: ; preds = %else.0, %then.0 - %cast.3 = bitcast { [16 x i32], i32 }* %a to i8* - %cast.4 = bitcast { [16 x i32], i32 }* %tmpv.0 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.3, i8* align 4 %cast.4, i64 68, i1 false) - ret void - - else.0: ; preds = %entry - %cast.2 = bitcast { [16 x i32], i32 }* %tmpv.0 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.2, i8* align 4 bitcast ({ [16 x i32], i32 }* @const.0 to i8*), i64 68, i1 false) - br label %fallthrough.0 - } + define void @foo(ptr sret({ [16 x i32], i32 }) %sret.formal.0, ptr nest %nest.0, ptr %p0, i32 %p1) #0 { + entry: + %p1.addr = alloca i32, align 4 + %a = alloca { [16 x i32], i32 }, align 4 + %tmpv.0 = alloca { [16 x i32], i32 }, align 4 + store i32 %p1, ptr %p1.addr, align 4 + %p1.ld.0 = load i32, ptr %p1.addr, align 4 + %icmp.0 = icmp slt i32 %p1.ld.0, 7 + %zext.0 = zext i1 %icmp.0 to i8 + %trunc.0 = trunc i8 %zext.0 to i1 + br i1 %trunc.0, label %then.0, label %else.0 + + then.0: ; preds = %entry + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmpv.0, ptr align 4 %p0, i64 68, i1 false) + br label %fallthrough.0 + + fallthrough.0: ; preds = %else.0, %then.0 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %tmpv.0, i64 68, i1 false) + ret void + + else.0: ; preds = %entry + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmpv.0, ptr align 4 @const.0, i64 68, i1 false) + br label %fallthrough.0 + } )RAW_RESULT"); bool broken = h.finish(StripDebugInfo); @@ -1589,18 +1531,18 @@ h.addStmt(es); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define i64 @foo(i8* nest %nest.0, i32 %param1, i32 %param2, i64* %param3) #0 { + define i64 @foo(ptr nest %nest.0, i32 %param1, i32 %param2, ptr %param3) #0 { entry: %param1.addr = alloca i32, align 4 %param2.addr = alloca i32, align 4 - %param3.addr = alloca i64*, align 8 + %param3.addr = alloca ptr, align 8 %x = alloca i64, align 8 - store i32 %param1, i32* %param1.addr, align 4 - store i32 %param2, i32* %param2.addr, align 4 - store i64* %param3, i64** %param3.addr, align 8 - store i64 0, i64* %x, align 8 - store i64 5, i64* %x, align 8 - %x.ld.0 = load i64, i64* %x, align 8 + store i32 %param1, ptr %param1.addr, align 4 + store i32 %param2, ptr %param2.addr, align 4 + store ptr %param3, ptr %param3.addr, align 8 + store i64 0, ptr %x, align 8 + store i64 5, ptr %x, align 8 + %x.ld.0 = load i64, ptr %x, align 8 ret i64 0 } )RAW_RESULT"); @@ -1639,30 +1581,27 @@ h.addStmt(st2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define i64 @foo(i8* nest %nest.0, i32 %param1, i32 %param2, i64* %param3) #0 { + define i64 @foo(ptr nest %nest.0, i32 %param1, i32 %param2, ptr %param3) #0 { entry: %tmp.0 = alloca { i64, i64 }, align 8 %param1.addr = alloca i32, align 4 %param2.addr = alloca i32, align 4 - %param3.addr = alloca i64*, align 8 + %param3.addr = alloca ptr, align 8 %x = alloca i64, align 8 %y = alloca { i64, i64 }, align 8 - store i32 %param1, i32* %param1.addr, align 4 - store i32 %param2, i32* %param2.addr, align 4 - store i64* %param3, i64** %param3.addr, align 8 - store i64 0, i64* %x, align 8 - %cast.0 = bitcast { i64, i64 }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ({ i64, i64 }* @const.0 to i8*), i64 16, i1 false) - store i64 5, i64* %x, align 8 - %x.ld.0 = load i64, i64* %x, align 8 - %x.ld.1 = load i64, i64* %x, align 8 - %field.0 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %tmp.0, i32 0, i32 0 - store i64 %x.ld.0, i64* %field.0, align 8 - %field.1 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %tmp.0, i32 0, i32 1 - store i64 %x.ld.1, i64* %field.1, align 8 - %cast.1 = bitcast { i64, i64 }* %y to i8* - %cast.2 = bitcast { i64, i64 }* %tmp.0 to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.1, i8* align 8 %cast.2, i64 16, i1 false) + store i32 %param1, ptr %param1.addr, align 4 + store i32 %param2, ptr %param2.addr, align 4 + store ptr %param3, ptr %param3.addr, align 8 + store i64 0, ptr %x, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %y, ptr align 8 @const.0, i64 16, i1 false) + store i64 5, ptr %x, align 8 + %x.ld.0 = load i64, ptr %x, align 8 + %x.ld.1 = load i64, ptr %x, align 8 + %field.0 = getelementptr inbounds { i64, i64 }, ptr %tmp.0, i32 0, i32 0 + store i64 %x.ld.0, ptr %field.0, align 8 + %field.1 = getelementptr inbounds { i64, i64 }, ptr %tmp.0, i32 0, i32 1 + store i64 %x.ld.1, ptr %field.1, align 8 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %y, ptr align 8 %tmp.0, i64 16, i1 false) ret i64 0 } )RAW_RESULT"); @@ -1701,32 +1640,32 @@ h.mkAssign(dex, mkInt32Const(be, 7)); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0, i32* %p0, i32* %p1) #0 { + define void @foo(ptr nest %nest.0, ptr %p0, ptr %p1) #0 { entry: - %p0.addr = alloca i32*, align 8 - %p1.addr = alloca i32*, align 8 - %tmpv.0 = alloca i32*, align 8 - store i32* %p0, i32** %p0.addr, align 8 - store i32* %p1, i32** %p1.addr, align 8 - %p0.ld.0 = load i32*, i32** %p0.addr, align 8 - %icmp.0 = icmp eq i32* %p0.ld.0, null + %p0.addr = alloca ptr, align 8 + %p1.addr = alloca ptr, align 8 + %tmpv.0 = alloca ptr, align 8 + store ptr %p0, ptr %p0.addr, align 8 + store ptr %p1, ptr %p1.addr, align 8 + %p0.ld.0 = load ptr, ptr %p0.addr, align 8 + %icmp.0 = icmp eq ptr %p0.ld.0, null %zext.0 = zext i1 %icmp.0 to i8 %trunc.0 = trunc i8 %zext.0 to i1 br i1 %trunc.0, label %then.0, label %else.0 - + then.0: ; preds = %entry - %p1.ld.0 = load i32*, i32** %p1.addr, align 8 - store i32* %p1.ld.0, i32** %tmpv.0, align 8 + %p1.ld.0 = load ptr, ptr %p1.addr, align 8 + store ptr %p1.ld.0, ptr %tmpv.0, align 8 br label %fallthrough.0 - + fallthrough.0: ; preds = %else.0, %then.0 - %tmpv.0.ld.0 = load i32*, i32** %tmpv.0, align 8 - store i32 7, i32* %tmpv.0.ld.0, align 4 + %tmpv.0.ld.0 = load ptr, ptr %tmpv.0, align 8 + store i32 7, ptr %tmpv.0.ld.0, align 4 ret void - + else.0: ; preds = %entry - %p0.ld.1 = load i32*, i32** %p0.addr, align 8 - store i32* %p0.ld.1, i32** %tmpv.0, align 8 + %p0.ld.1 = load ptr, ptr %p0.addr, align 8 + store ptr %p0.ld.1, ptr %tmpv.0, align 8 br label %fallthrough.0 } )RAW_RESULT"); @@ -1774,24 +1713,24 @@ h.mkLocal("r", bf64t, be->unary_expression(OPERATOR_MINUS, veq, loc)); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i8 0, i8* %x, align 1 - %x.ld.0 = load i8, i8* %x, align 1 + store i8 0, ptr %x, align 1 + %x.ld.0 = load i8, ptr %x, align 1 %icmp.0 = icmp ne i8 %x.ld.0, 0 %xor.0 = xor i1 %icmp.0, true %zext.0 = zext i1 %xor.0 to i8 - store i8 %zext.0, i8* %y, align 1 - store i32 0, i32* %a, align 4 - %a.ld.0 = load i32, i32* %a, align 4 + store i8 %zext.0, ptr %y, align 1 + store i32 0, ptr %a, align 4 + %a.ld.0 = load i32, ptr %a, align 4 %sub.0 = sub i32 0, %a.ld.0 - store i32 %sub.0, i32* %b, align 4 - store i64 0, i64* %z, align 8 - %z.ld.0 = load i64, i64* %z, align 8 + store i32 %sub.0, ptr %b, align 4 + store i64 0, ptr %z, align 8 + %z.ld.0 = load i64, ptr %z, align 8 %xor.1 = xor i64 %z.ld.0, -1 - store i64 %xor.1, i64* %w, align 8 - store double 0.000000e+00, double* %q, align 8 - %q.ld.0 = load double, double* %q, align 8 + store i64 %xor.1, ptr %w, align 8 + store double 0.000000e+00, ptr %q, align 8 + %q.ld.0 = load double, ptr %q, align 8 %fsub.0 = fsub double -0.000000e+00, %q.ld.0 - store double %fsub.0, double* %r, align 8 + store double %fsub.0, ptr %r, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -1821,7 +1760,7 @@ h.mkExprStmt(call1); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - call addrspace(0) void @foo(i8* nest undef, i8* null, i32* null, i64* null) + call addrspace(0) void @foo(ptr nest undef, ptr null, ptr null, ptr null) )RAW_RESULT"); // Note that this
diff --git a/unittests/BackendCore/BackendFcnTests.cpp b/unittests/BackendCore/BackendFcnTests.cpp index 2af5163..82a0d6f 100644 --- a/unittests/BackendCore/BackendFcnTests.cpp +++ b/unittests/BackendCore/BackendFcnTests.cpp
@@ -298,8 +298,8 @@ h.mkExprStmt(call); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %x, align 8 - %x.ld.0 = load i64, i64* %x, align 8 + store i64 0, ptr %x, align 8 + %x.ld.0 = load i64, ptr %x, align 8 %call.0 = call addrspace(0) i64 @llvm.cttz.i64(i64 %x.ld.0, i1 true) )RAW_RESULT"); @@ -364,17 +364,11 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %x, align 8 - store i64 10101, i64* %y, align 8 - %cast.0 = bitcast i64* %x to i8* - %cast.1 = bitcast i64* %y to i8* - %call.0 = call addrspace(0) i32 @memcmp(i8* %cast.0, i8* %cast.1, i64 8) - %cast.2 = bitcast i64* %x to i8* - %cast.3 = bitcast i64* %y to i8* - call addrspace(0) void @llvm.memmove.p0i8.p0i8.i64(i8* %cast.2, i8* %cast.3, i64 8, i1 false) - %cast.4 = bitcast i64* %y to i8* - %cast.5 = bitcast i64* %x to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.4, i8* %cast.5, i64 8, i1 false) + store i64 0, ptr %x, align 8 + store i64 10101, ptr %y, align 8 + %call.0 = call addrspace(0) i32 @memcmp(ptr %x, ptr %y, i64 8) + call addrspace(0) void @llvm.memmove.p0.p0.i64(ptr %x, ptr %y, i64 8, i1 false) + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr %y, ptr %x, i64 8, i1 false) )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -425,10 +419,10 @@ h.mkLocal("y", bi32t, call32); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %call.0 = call addrspace(0) i64 @syscall(i8* nest undef, i64 64) - store i64 %call.0, i64* %x, align 8 - %call.1 = call addrspace(0) i32 bitcast (i64 (i8*, i64)* @syscall to i32 (i8*, i32)*)(i8* nest undef, i32 32) - store i32 %call.1, i32* %y, align 4 + %call.0 = call addrspace(0) i64 @syscall(ptr nest undef, i64 64) + store i64 %call.0, ptr %x, align 8 + %call.1 = call addrspace(0) i32 @syscall(ptr nest undef, i32 32) + store i32 %call.1, ptr %y, align 4 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -498,14 +492,14 @@ h.mkLocal("y", bps1t, call4); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %call.0 = call addrspace(0) i32 @bar(i8* nest undef) - store i32 %call.0, i32* %a, align 4 - %call.1 = call addrspace(0) i32 @bar(i8* nest undef) - store i32 %call.1, i32* %b, align 4 - %call.2 = call addrspace(0) {}* bitcast ({ i32 }* (i8*)* @baz to {}* (i8*)*)(i8* nest undef) - store {}* %call.2, {}** %x, align 8 - %call.3 = call addrspace(0) { i32 }* @baz(i8* nest undef) - store { i32 }* %call.3, { i32 }** %y, align 8 + %call.0 = call addrspace(0) i32 @bar(ptr nest undef) + store i32 %call.0, ptr %a, align 4 + %call.1 = call addrspace(0) i32 @bar(ptr nest undef) + store i32 %call.1, ptr %b, align 4 + %call.2 = call addrspace(0) ptr @baz(ptr nest undef) + store ptr %call.2, ptr %x, align 8 + %call.3 = call addrspace(0) ptr @baz(ptr nest undef) + store ptr %call.3, ptr %y, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp);
diff --git a/unittests/BackendCore/BackendNodeTests.cpp b/unittests/BackendCore/BackendNodeTests.cpp index 13a3a5a..9a9396c 100644 --- a/unittests/BackendCore/BackendNodeTests.cpp +++ b/unittests/BackendCore/BackendNodeTests.cpp
@@ -92,36 +92,36 @@ EXPECT_EQ(res1, matsub); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - node - pre 18 - pre child + 18 15 - node + pre 15 - pre child const 15 1 + node - pre 17 + pre child + 17 14 + node + pre 14 + pre child const 14 1 node const pre 1 node const post 1 - post child const 15 1 - pre child deref 15 14 - node deref pre 14 - pre child var 14 8 + post child const 14 1 + pre child deref 14 13 + node deref pre 13 + pre child var 13 8 node var pre 8 node var post 8 - post child var 14 8 - node deref post 14 - post child deref 15 14 - node + post 15 - post child + 18 15 - pre child deref 18 17 - node deref pre 17 + post child var 13 8 + node deref post 13 + post child deref 14 13 + node + post 14 + post child + 17 14 pre child deref 17 16 node deref pre 16 - pre child var 16 10 + pre child deref 16 15 + node deref pre 15 + pre child var 15 10 node var pre 10 node var post 10 - post child var 16 10 + post child var 15 10 + node deref post 15 + post child deref 16 15 node deref post 16 post child deref 17 16 - node deref post 17 - post child deref 18 17 - node - post 18 + node - post 17 )RAW_RESULT"); std::string reason; @@ -163,12 +163,12 @@ EXPECT_NE(add, matclone); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %x.ld.0 = load i32, i32* %x, align 4 - %z.ld.0 = load i16, i16* %z, align 2 + %x.ld.0 = load i32, ptr %x, align 4 + %z.ld.0 = load i16, ptr %z, align 2 %sext.0 = sext i16 %z.ld.0 to i32 %add.0 = add i32 %x.ld.0, %sext.0 - %y.ld.0 = load i32*, i32** %y, align 8 - %.ld.0 = load i32, i32* %y.ld.0, align 4 + %y.ld.0 = load ptr, ptr %y, align 8 + %.ld.0 = load i32, ptr %y.ld.0, align 4 %add.1 = add i32 %add.0, %.ld.0 )RAW_RESULT"); @@ -205,14 +205,14 @@ Bexpression *matadd = be->materialize(add); DECLARE_EXPECTED_OUTPUT(exp2, R"RAW_RESULT( - %field.0 = getelementptr inbounds { { i32*, i32 }, { i32*, i32 } }, { { i32*, i32 }, { i32*, i32 } }* %x, i32 0, i32 0 - %field.1 = getelementptr inbounds { i32*, i32 }, { i32*, i32 }* %field.0, i32 0, i32 0 - %x.field.field.ld.0 = load i32*, i32** %field.1, align 8 - %.ld.0 = load i32, i32* %x.field.field.ld.0, align 4 - %field.2 = getelementptr inbounds { { i32*, i32 }, { i32*, i32 } }, { { i32*, i32 }, { i32*, i32 } }* %x, i32 0, i32 0 - %field.3 = getelementptr inbounds { i32*, i32 }, { i32*, i32 }* %field.2, i32 0, i32 0 - %.field.field.ld.0 = load i32*, i32** %field.3, align 8 - %.ld.1 = load i32, i32* %.field.field.ld.0, align 4 + %field.0 = getelementptr inbounds { { ptr, i32 }, { ptr, i32 } }, ptr %x, i32 0, i32 0 + %field.1 = getelementptr inbounds { ptr, i32 }, ptr %field.0, i32 0, i32 0 + %x.field.field.ld.0 = load ptr, ptr %field.1, align 8 + %.ld.0 = load i32, ptr %x.field.field.ld.0, align 4 + %field.2 = getelementptr inbounds { { ptr, i32 }, { ptr, i32 } }, ptr %x, i32 0, i32 0 + %field.3 = getelementptr inbounds { ptr, i32 }, ptr %field.2, i32 0, i32 0 + %.field.field.ld.0 = load ptr, ptr %field.3, align 8 + %.ld.1 = load i32, ptr %.field.field.ld.0, align 4 %add.0 = add i32 %.ld.0, %.ld.1 )RAW_RESULT");
diff --git a/unittests/BackendCore/BackendPointerExprTests.cpp b/unittests/BackendCore/BackendPointerExprTests.cpp index f5882ca..0de8d66 100644 --- a/unittests/BackendCore/BackendPointerExprTests.cpp +++ b/unittests/BackendCore/BackendPointerExprTests.cpp
@@ -72,14 +72,14 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 10, i64* %y, align 8 - store i64* null, i64** %x, align 8 - store i64* %y, i64** %x, align 8 - %x.ld.0 = load i64*, i64** %x, align 8 - %.ld.0 = load i64, i64* %x.ld.0, align 8 - store i64 %.ld.0, i64* %y, align 8 - %x.ld.1 = load i64*, i64** %x, align 8 - store i64 3, i64* %x.ld.1, align 8 + store i64 10, ptr %y, align 8 + store ptr null, ptr %x, align 8 + store ptr %y, ptr %x, align 8 + %x.ld.0 = load ptr, ptr %x, align 8 + %.ld.0 = load i64, ptr %x.ld.0, align 8 + store i64 %.ld.0, ptr %y, align 8 + %x.ld.1 = load ptr, ptr %x, align 8 + store i64 3, ptr %x.ld.1, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -130,16 +130,13 @@ h.mkAssign(vex3, rvex3); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %cast.0 = bitcast { i64 }* %fdloc1 to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %cast.0, i8* align 8 bitcast ({ i64 }* @const.0 to i8*), i64 8, i1 false) - store { i64 }* %fdloc1, { i64 }** %fploc1, align 8 - store { i64 (i8*, i32, i32, i64*)* }* null, { i64 (i8*, i32, i32, i64*)* }** %fploc2, align 8 - %fploc1.ld.0 = load { i64 }*, { i64 }** %fploc1, align 8 - %cast.1 = bitcast { i64 }* %fploc1.ld.0 to { i64 (i8*, i32, i32, i64*)* }* - store { i64 (i8*, i32, i32, i64*)* }* %cast.1, { i64 (i8*, i32, i32, i64*)* }** %fploc2, align 8 - %fploc2.ld.0 = load { i64 (i8*, i32, i32, i64*)* }*, { i64 (i8*, i32, i32, i64*)* }** %fploc2, align 8 - %cast.2 = bitcast { i64 (i8*, i32, i32, i64*)* }* %fploc2.ld.0 to { i64 }* - store { i64 }* %cast.2, { i64 }** %fploc1, align 8 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 8 %fdloc1, ptr align 8 @const.0, i64 8, i1 false) + store ptr %fdloc1, ptr %fploc1, align 8 + store ptr null, ptr %fploc2, align 8 + %fploc1.ld.0 = load ptr, ptr %fploc1, align 8 + store ptr %fploc1.ld.0, ptr %fploc2, align 8 + %fploc2.ld.0 = load ptr, ptr %fploc2, align 8 + store ptr %fploc2.ld.0, ptr %fploc1, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -157,7 +154,7 @@ // Manufacture a nil pointer expression Bexpression *npe = be->nil_pointer_expression(); DECLARE_EXPECTED_OUTPUT(exp1, R"RAW_RESULT( - i64* null + ptr null )RAW_RESULT"); bool isOK = h.expectValue(npe->value(), exp1); EXPECT_TRUE(isOK && "Value does not have expected contents"); @@ -188,16 +185,16 @@ } DECLARE_EXPECTED_OUTPUT(exp2, R"RAW_RESULT( - store i8 0, i8* %b1, align 1 - store i8* null, i8** %pb1, align 8 - %pb1.ld.0 = load i8*, i8** %pb1, align 8 - %icmp.0 = icmp eq i8* %pb1.ld.0, null + store i8 0, ptr %b1, align 1 + store ptr null, ptr %pb1, align 8 + %pb1.ld.0 = load ptr, ptr %pb1, align 8 + %icmp.0 = icmp eq ptr %pb1.ld.0, null %zext.0 = zext i1 %icmp.0 to i8 - store i8 %zext.0, i8* %b1, align 1 - %pb1.ld.1 = load i8*, i8** %pb1, align 8 - %icmp.1 = icmp eq i8* null, %pb1.ld.1 + store i8 %zext.0, ptr %b1, align 1 + %pb1.ld.1 = load ptr, ptr %pb1, align 8 + %icmp.1 = icmp eq ptr null, %pb1.ld.1 %zext.1 = zext i1 %icmp.1 to i8 - store i8 %zext.1, i8* %b1, align 1 + store i8 %zext.1, ptr %b1, align 1 )RAW_RESULT"); bool isOK2 = h.expectBlock(exp2); @@ -225,10 +222,9 @@ h.mkLocal("y", bst, deref2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %deref.ld.0 = load i32, i32* null, align 4 - store i32 %deref.ld.0, i32* %x, align 4 - %cast.2 = bitcast { i32, i32 }* %y to i8* - call addrspace(0) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.2, i8* align 4 null, i64 8, i1 false) + %deref.ld.0 = load i32, ptr null, align 4 + store i32 %deref.ld.0, ptr %x, align 4 + call addrspace(0) void @llvm.memcpy.p0.p0.i64(ptr align 4 %y, ptr align 4 null, i64 8, i1 false) )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -321,38 +317,31 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store %CPT.0* null, %CPT.0** %cpv1, align 8 - store %CPT.0* null, %CPT.0** %cpv2, align 8 - %cast.0 = bitcast %CPT.0** %cpv2 to %CPT.0* - store %CPT.0* %cast.0, %CPT.0** %cpv1, align 8 - %cast.1 = bitcast %CPT.0** %cpv1 to %CPT.0* - store %CPT.0* %cast.1, %CPT.0** %cpv2, align 8 - store i8 0, i8* %b1, align 1 - store i8 0, i8* %b2, align 1 - store i8 0, i8* %b3, align 1 - %cpv1.ld.0 = load %CPT.0*, %CPT.0** %cpv1, align 8 - %cast.2 = bitcast %CPT.0** %cpv2 to %CPT.0*** - %cpv2.ld.0 = load %CPT.0**, %CPT.0*** %cast.2, align 8 - %.ld.0 = load %CPT.0*, %CPT.0** %cpv2.ld.0, align 8 - %icmp.0 = icmp eq %CPT.0* %cpv1.ld.0, %.ld.0 + store ptr null, ptr %cpv1, align 8 + store ptr null, ptr %cpv2, align 8 + store ptr %cpv2, ptr %cpv1, align 8 + store ptr %cpv1, ptr %cpv2, align 8 + store i8 0, ptr %b1, align 1 + store i8 0, ptr %b2, align 1 + store i8 0, ptr %b3, align 1 + %cpv1.ld.0 = load ptr, ptr %cpv1, align 8 + %cpv2.ld.0 = load ptr, ptr %cpv2, align 8 + %.ld.0 = load ptr, ptr %cpv2.ld.0, align 8 + %icmp.0 = icmp eq ptr %cpv1.ld.0, %.ld.0 %zext.0 = zext i1 %icmp.0 to i8 - store i8 %zext.0, i8* %b1, align 1 - %cpv2.ld.1 = load %CPT.0*, %CPT.0** %cpv2, align 8 - %cast.3 = bitcast %CPT.0* %cpv2.ld.1 to %CPT.0** - %icmp.1 = icmp eq %CPT.0** %cpv1, %cast.3 + store i8 %zext.0, ptr %b1, align 1 + %cpv2.ld.1 = load ptr, ptr %cpv2, align 8 + %icmp.1 = icmp eq ptr %cpv1, %cpv2.ld.1 %zext.1 = zext i1 %icmp.1 to i8 - store i8 %zext.1, i8* %b2, align 1 - %cpv1.ld.1 = load %CPT.0*, %CPT.0** %cpv1, align 8 - %cast.4 = bitcast %CPT.0** %cpv2 to %CPT.0*** - %cpv2.ld.2 = load %CPT.0**, %CPT.0*** %cast.4, align 8 - %cast.5 = bitcast %CPT.0** %cpv2.ld.2 to %CPT.0*** - %deref.ld.0 = load %CPT.0**, %CPT.0*** %cast.5, align 8 - %cast.6 = bitcast %CPT.0** %deref.ld.0 to %CPT.0*** - %deref.ld.1 = load %CPT.0**, %CPT.0*** %cast.6, align 8 - %.ld.1 = load %CPT.0*, %CPT.0** %deref.ld.1, align 8 - %icmp.2 = icmp eq %CPT.0* %cpv1.ld.1, %.ld.1 + store i8 %zext.1, ptr %b2, align 1 + %cpv1.ld.1 = load ptr, ptr %cpv1, align 8 + %cpv2.ld.2 = load ptr, ptr %cpv2, align 8 + %deref.ld.0 = load ptr, ptr %cpv2.ld.2, align 8 + %deref.ld.1 = load ptr, ptr %deref.ld.0, align 8 + %.ld.1 = load ptr, ptr %deref.ld.1, align 8 + %icmp.2 = icmp eq ptr %cpv1.ld.1, %.ld.1 %zext.2 = zext i1 %icmp.2 to i8 - store i8 %zext.2, i8* %b3, align 1 + store i8 %zext.2, ptr %b3, align 1 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -422,18 +411,17 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store %CPT.0* null, %CPT.0** %x, align 8 - store %CPT.0** null, %CPT.0*** %y, align 8 - %cast.0 = bitcast %CPT.0*** %y to %CPT.0* - store %CPT.0* %cast.0, %CPT.0** %x, align 8 - store %CPT.0** %x, %CPT.0*** %y, align 8 - store i8 0, i8* %b1, align 1 - %x.ld.0 = load %CPT.0*, %CPT.0** %x, align 8 - %y.ld.0 = load %CPT.0**, %CPT.0*** %y, align 8 - %.ld.0 = load %CPT.0*, %CPT.0** %y.ld.0, align 8 - %icmp.0 = icmp eq %CPT.0* %x.ld.0, %.ld.0 + store ptr null, ptr %x, align 8 + store ptr null, ptr %y, align 8 + store ptr %y, ptr %x, align 8 + store ptr %x, ptr %y, align 8 + store i8 0, ptr %b1, align 1 + %x.ld.0 = load ptr, ptr %x, align 8 + %y.ld.0 = load ptr, ptr %y, align 8 + %.ld.0 = load ptr, ptr %y.ld.0, align 8 + %icmp.0 = icmp eq ptr %x.ld.0, %.ld.0 %zext.0 = zext i1 %icmp.0 to i8 - store i8 %zext.0, i8* %b1, align 1 + store i8 %zext.0, ptr %b1, align 1 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -477,14 +465,14 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %param3.ld.0 = load i64*, i64** %param3.addr, align 8 - %ptroff.0 = getelementptr i64, i64* %param3.ld.0, i32 5 - store i64 9, i64* %ptroff.0, align 8 - %param3.ld.1 = load i64*, i64** %param3.addr, align 8 - %ptroff.1 = getelementptr i64, i64* %param3.ld.1, i32 7 - %.ptroff.ld.0 = load i64, i64* %ptroff.1, align 8 + %param3.ld.0 = load ptr, ptr %param3.addr, align 8 + %ptroff.0 = getelementptr i64, ptr %param3.ld.0, i32 5 + store i64 9, ptr %ptroff.0, align 8 + %param3.ld.1 = load ptr, ptr %param3.addr, align 8 + %ptroff.1 = getelementptr i64, ptr %param3.ld.1, i32 7 + %.ptroff.ld.0 = load i64, ptr %ptroff.1, align 8 %trunc.0 = trunc i64 %.ptroff.ld.0 to i32 - store i32 %trunc.0, i32* %param1.addr, align 4 + store i32 %trunc.0, ptr %param1.addr, align 4 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -516,8 +504,8 @@ h.mkAssign(vexl, ad3); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %x, align 8 - store i64* %x, i64** %param3.addr, align 8 + store i64 0, ptr %x, align 8 + store ptr %x, ptr %param3.addr, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -569,8 +557,8 @@ } DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i32 0, i32* inttoptr (i64 65793 to i32*), align 4 - store i64 2, i64* getelementptr inbounds ({ i64, i64 }, { i64, i64 }* inttoptr (i64 34661 to { i64, i64 }*), i32 0, i32 1), align 8 + store i32 0, ptr inttoptr (i64 65793 to ptr), align 4 + store i64 2, ptr getelementptr inbounds ({ i64, i64 }, ptr inttoptr (i64 34661 to ptr), i32 0, i32 1), align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); @@ -622,9 +610,8 @@ h.mkLocal("y", pbefty2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 (i8*, i64, i64, %CFT.0*, %CFT.1*)* null, i64 (i8*, i64, i64, %CFT.0*, %CFT.1*)** %x, align 8 - store i64 (i8*, i64, i64, %CFT.1*, %CFT.0*)* null, i64 (i8*, i64, i64, %CFT.1*, %CFT.0*)** %y, align 8 - + store ptr null, ptr %x, align 8 + store ptr null, ptr %y, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp);
diff --git a/unittests/BackendCore/BackendStmtTests.cpp b/unittests/BackendCore/BackendStmtTests.cpp index 7e47928..c2661a9 100644 --- a/unittests/BackendCore/BackendStmtTests.cpp +++ b/unittests/BackendCore/BackendStmtTests.cpp
@@ -40,7 +40,7 @@ Bstatement *is = be->init_statement(func, loc1, mkInt64Const(be, 10)); ASSERT_TRUE(is != nullptr); h.addStmt(is); - EXPECT_EQ(repr(is), "store i64 10, i64* %loc1, align 8"); + EXPECT_EQ(repr(is), "store i64 10, ptr %loc1, align 8"); // error handling Bvariable *loc2 = be->local_variable(func, "loc2", bi64t, nullptr, true, loc); @@ -80,11 +80,11 @@ h.addStmt(as2); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - store i64 0, i64* %loc1, align 8 - store i64 123, i64* %loc1, align 8 - store i64 0, i64* %loc2, align 8 - %loc1.ld.0 = load i64, i64* %loc1, align 8 - store i64 %loc1.ld.0, i64* %loc2, align 8 + store i64 0, ptr %loc1, align 8 + store i64 123, ptr %loc1, align 8 + store i64 0, ptr %loc2, align 8 + %loc1.ld.0 = load i64, ptr %loc1, align 8 + store i64 %loc1.ld.0, ptr %loc2, align 8 )RAW_RESULT"); bool isOK = h.expectBlock(exp); EXPECT_TRUE(isOK && "Block does not have expected contents"); @@ -116,7 +116,7 @@ Bstatement *ret = h.mkReturn(ve1); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - %loc1.ld.0 = load i64, i64* %loc1, align 8 + %loc1.ld.0 = load i64, ptr %loc1, align 8 ret i64 %loc1.ld.0 )RAW_RESULT"); std::string reason; @@ -157,19 +157,19 @@ h.mkReturn(addexpr); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define i64 @foo(i8* nest %nest.0, i32 %param1, i32 %param2, i64* %param3) #0 { - entry: - %param1.addr = alloca i32, align 4 - %param2.addr = alloca i32, align 4 - %param3.addr = alloca i64*, align 8 - %x = alloca i64, align 8 - store i32 %param1, i32* %param1.addr, align 4 - store i32 %param2, i32* %param2.addr, align 4 - store i64* %param3, i64** %param3.addr, align 8 - store i64 10, i64* %x, align 8 - %x.ld.0 = load i64, i64* %x, align 8 - ret i64 %x.ld.0 - } + define i64 @foo(ptr nest %nest.0, i32 %param1, i32 %param2, ptr %param3) #0 { + entry: + %param1.addr = alloca i32, align 4 + %param2.addr = alloca i32, align 4 + %param3.addr = alloca ptr, align 8 + %x = alloca i64, align 8 + store i32 %param1, ptr %param1.addr, align 4 + store i32 %param2, ptr %param2.addr, align 4 + store ptr %param3, ptr %param3.addr, align 8 + store i64 10, ptr %x, align 8 + %x.ld.0 = load i64, ptr %x, align 8 + ret i64 %x.ld.0 + } )RAW_RESULT"); bool broken = h.finish(StripDebugInfo); @@ -240,17 +240,17 @@ EXPECT_FALSE(broken && "Module failed to verify."); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { - entry: - %loc1 = alloca i8, align 1 - store i8 0, i8* %loc1, align 1 - call void @bar(i8* nest undef, i8* blockaddress(@foo, %label.0)) - br label %label.0 - - label.0: ; preds = %entry - store i8 0, i8* %loc1, align 1 - ret void - } + define void @foo(ptr nest %nest.0) #0 { + entry: + %loc1 = alloca i8, align 1 + store i8 0, ptr %loc1, align 1 + call void @bar(ptr nest undef, ptr blockaddress(@foo, %label.0)) + br label %label.0 + + label.0: ; preds = %entry + store i8 0, ptr %loc1, align 1 + ret void + } )RAW_RESULT"); bool isOK = h.expectValue(func->function(), exp); @@ -311,41 +311,41 @@ // verify DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define i64 @foo(i8* nest %nest.0, i32 %param1, i32 %param2, i64* %param3) #0 { - entry: - %param1.addr = alloca i32, align 4 - %param2.addr = alloca i32, align 4 - %param3.addr = alloca i64*, align 8 - %loc1 = alloca i64, align 8 - %loc2 = alloca i64, align 8 - store i32 %param1, i32* %param1.addr, align 4 - store i32 %param2, i32* %param2.addr, align 4 - store i64* %param3, i64** %param3.addr, align 8 - store i64 0, i64* %loc1, align 8 - store i64 0, i64* %loc2, align 8 - br i1 true, label %then.0, label %else.0 - - then.0: ; preds = %entry - br i1 true, label %then.1, label %else.1 - - fallthrough.0: ; preds = %else.0, %fallthrough.1 - ret i64 10101 - - else.0: ; preds = %entry - store i64 456, i64* %loc2, align 8 - br label %fallthrough.0 - - then.1: ; preds = %then.0 - store i64 123, i64* %loc1, align 8 - br label %fallthrough.1 - - fallthrough.1: ; preds = %else.1, %then.1 - br label %fallthrough.0 - - else.1: ; preds = %then.0 - store i64 987, i64* %loc1, align 8 - br label %fallthrough.1 - } + define i64 @foo(ptr nest %nest.0, i32 %param1, i32 %param2, ptr %param3) #0 { + entry: + %param1.addr = alloca i32, align 4 + %param2.addr = alloca i32, align 4 + %param3.addr = alloca ptr, align 8 + %loc1 = alloca i64, align 8 + %loc2 = alloca i64, align 8 + store i32 %param1, ptr %param1.addr, align 4 + store i32 %param2, ptr %param2.addr, align 4 + store ptr %param3, ptr %param3.addr, align 8 + store i64 0, ptr %loc1, align 8 + store i64 0, ptr %loc2, align 8 + br i1 true, label %then.0, label %else.0 + + then.0: ; preds = %entry + br i1 true, label %then.1, label %else.1 + + fallthrough.0: ; preds = %else.0, %fallthrough.1 + ret i64 10101 + + else.0: ; preds = %entry + store i64 456, ptr %loc2, align 8 + br label %fallthrough.0 + + then.1: ; preds = %then.0 + store i64 123, ptr %loc1, align 8 + br label %fallthrough.1 + + fallthrough.1: ; preds = %else.1, %then.1 + br label %fallthrough.0 + + else.1: ; preds = %then.0 + store i64 987, ptr %loc1, align 8 + br label %fallthrough.1 + } )RAW_RESULT"); bool isOK = h.expectValue(func->function(), exp); @@ -435,65 +435,65 @@ // verify DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define i64 @foo(i8* nest %nest.0, i32 %param1, i32 %param2, i64* %param3) #0 { - entry: - %param1.addr = alloca i32, align 4 - %param2.addr = alloca i32, align 4 - %param3.addr = alloca i64*, align 8 - %loc1 = alloca i64, align 8 - %tmpv.0 = alloca i64, align 8 - store i32 %param1, i32* %param1.addr, align 4 - store i32 %param2, i32* %param2.addr, align 4 - store i64* %param3, i64** %param3.addr, align 8 - store i64 0, i64* %loc1, align 8 - %loc1.ld.4 = load i64, i64* %loc1, align 8 - switch i64 %loc1.ld.4, label %default.0 [ - i64 1, label %case.0 - i64 2, label %case.0 - i64 3, label %case.1 - i64 4, label %case.1 - i64 5, label %case.2 - ] - - case.0: ; preds = %entry, %entry - %loc1.ld.0 = load i64, i64* %loc1, align 8 - %div.0 = sdiv i64 %loc1.ld.0, 123 - store i64 %div.0, i64* %loc1, align 8 - br label %label.0 - - case.1: ; preds = %entry, %entry - %loc1.ld.1 = load i64, i64* %loc1, align 8 - %icmp.0 = icmp sle i64 %loc1.ld.1, 987 - %zext.0 = zext i1 %icmp.0 to i8 - %trunc.0 = trunc i8 %zext.0 to i1 - br i1 %trunc.0, label %then.0, label %else.0 - - case.2: ; preds = %entry, %fallthrough.0 - br label %default.0 - - default.0: ; preds = %entry, %case.2 - store i64 456, i64* %loc1, align 8 - br label %label.0 - - label.0: ; preds = %default.0, %case.0 - ret i64 10101 - - then.0: ; preds = %case.1 - %loc1.ld.3 = load i64, i64* %loc1, align 8 - store i64 %loc1.ld.3, i64* %tmpv.0, align 8 - br label %fallthrough.0 - - fallthrough.0: ; preds = %else.0, %then.0 - %tmpv.0.ld.0 = load i64, i64* %tmpv.0, align 8 - store i64 %tmpv.0.ld.0, i64* %loc1, align 8 - br label %case.2 - - else.0: ; preds = %case.1 - %loc1.ld.2 = load i64, i64* %loc1, align 8 - %mul.0 = mul i64 987, %loc1.ld.2 - store i64 %mul.0, i64* %tmpv.0, align 8 - br label %fallthrough.0 - } + define i64 @foo(ptr nest %nest.0, i32 %param1, i32 %param2, ptr %param3) #0 { + entry: + %param1.addr = alloca i32, align 4 + %param2.addr = alloca i32, align 4 + %param3.addr = alloca ptr, align 8 + %loc1 = alloca i64, align 8 + %tmpv.0 = alloca i64, align 8 + store i32 %param1, ptr %param1.addr, align 4 + store i32 %param2, ptr %param2.addr, align 4 + store ptr %param3, ptr %param3.addr, align 8 + store i64 0, ptr %loc1, align 8 + %loc1.ld.4 = load i64, ptr %loc1, align 8 + switch i64 %loc1.ld.4, label %default.0 [ + i64 1, label %case.0 + i64 2, label %case.0 + i64 3, label %case.1 + i64 4, label %case.1 + i64 5, label %case.2 + ] + + case.0: ; preds = %entry, %entry + %loc1.ld.0 = load i64, ptr %loc1, align 8 + %div.0 = sdiv i64 %loc1.ld.0, 123 + store i64 %div.0, ptr %loc1, align 8 + br label %label.0 + + case.1: ; preds = %entry, %entry + %loc1.ld.1 = load i64, ptr %loc1, align 8 + %icmp.0 = icmp sle i64 %loc1.ld.1, 987 + %zext.0 = zext i1 %icmp.0 to i8 + %trunc.0 = trunc i8 %zext.0 to i1 + br i1 %trunc.0, label %then.0, label %else.0 + + case.2: ; preds = %entry, %fallthrough.0 + br label %default.0 + + default.0: ; preds = %entry, %case.2 + store i64 456, ptr %loc1, align 8 + br label %label.0 + + label.0: ; preds = %default.0, %case.0 + ret i64 10101 + + then.0: ; preds = %case.1 + %loc1.ld.3 = load i64, ptr %loc1, align 8 + store i64 %loc1.ld.3, ptr %tmpv.0, align 8 + br label %fallthrough.0 + + fallthrough.0: ; preds = %else.0, %then.0 + %tmpv.0.ld.0 = load i64, ptr %tmpv.0, align 8 + store i64 %tmpv.0.ld.0, ptr %loc1, align 8 + br label %case.2 + + else.0: ; preds = %case.1 + %loc1.ld.2 = load i64, ptr %loc1, align 8 + %mul.0 = mul i64 987, %loc1.ld.2 + store i64 %mul.0, ptr %tmpv.0, align 8 + br label %fallthrough.0 + } )RAW_RESULT"); bool isOK = h.expectValue(func->function(), exp); @@ -584,28 +584,28 @@ EXPECT_FALSE(broken && "Module failed to verify."); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 personality i32 (i32, i32, i64, i8*, i8*)* @__gccgo_personality_v0 { - entry: - %x = alloca i8, align 1 - store i8 0, i8* %x, align 1 - br label %finish.0 - - pad.0: ; preds = %finish.0 - %ex.0 = landingpad { i8*, i32 } - catch i8* null - br label %catch.0 - - catch.0: ; preds = %pad.0 - call void @checkdefer(i8* nest undef, i8* %x) - br label %finish.0 - - finish.0: ; preds = %catch.0, %entry - invoke void @deferreturn(i8* nest undef, i8* %x) - to label %cont.0 unwind label %pad.0 - - cont.0: ; preds = %finish.0 - ret void - } + define void @foo(ptr nest %nest.0) #0 personality ptr @__gccgo_personality_v0 { + entry: + %x = alloca i8, align 1 + store i8 0, ptr %x, align 1 + br label %finish.0 + + pad.0: ; preds = %finish.0 + %ex.0 = landingpad { ptr, i32 } + catch ptr null + br label %catch.0 + + catch.0: ; preds = %pad.0 + call void @checkdefer(ptr nest undef, ptr %x) + br label %finish.0 + + finish.0: ; preds = %catch.0, %entry + invoke void @deferreturn(ptr nest undef, ptr %x) + to label %cont.0 unwind label %pad.0 + + cont.0: ; preds = %finish.0 + ret void + } )RAW_RESULT"); bool isOK = h.expectValue(func->function(), exp); @@ -697,94 +697,94 @@ EXPECT_FALSE(broken && "Module failed to verify."); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @baz(i8* nest %nest.0) #0 personality i32 (i32, i32, i64, i8*, i8*)* @__gccgo_personality_v0 { - entry: - %ehtmp.0 = alloca { i8*, i32 }, align 8 - %x = alloca i64, align 8 - %y = alloca i8, align 1 - %sret.actual.0 = alloca { i8, i8 }, align 1 - %sret.actual.1 = alloca { i8, i8 }, align 1 - %finvar.0 = alloca i8, align 1 - store i64 0, i64* %x, align 8 - store i8 0, i8* %y, align 1 - %call.0 = invoke i64 @id(i8* nest undef, i64 99) - to label %cont.1 unwind label %pad.1 - - finok.0: ; preds = %cont.4 - store i8 1, i8* %finvar.0, align 1 - br label %finally.0 - - finally.0: ; preds = %catchpad.0, %finok.0 - br label %finish.0 - - pad.0: ; preds = %fallthrough.0, %finish.0 - %ex.0 = landingpad { i8*, i32 } - catch i8* null - br label %catch.0 - - catch.0: ; preds = %pad.0 - call void @checkdefer(i8* nest undef, i8* %y) - br label %finish.0 - - finish.0: ; preds = %catch.0, %finally.0 - invoke void @deferreturn(i8* nest undef, i8* %y) - to label %cont.0 unwind label %pad.0 - - cont.0: ; preds = %fallthrough.0, %finish.0 - %fload.0 = load i8, i8* %finvar.0, align 1 - %icmp.0 = icmp eq i8 %fload.0, 1 - br i1 %icmp.0, label %finret.0, label %finres.0 - - pad.1: ; preds = %then.0, %cont.1, %entry - %ex.1 = landingpad { i8*, i32 } - catch i8* null - br label %catch.1 - - catch.1: ; preds = %pad.1 - invoke void @plix(i8* nest undef) - to label %cont.4 unwind label %catchpad.0 - - catchpad.0: ; preds = %catch.1 - %ex2.0 = landingpad { i8*, i32 } - cleanup - store { i8*, i32 } %ex2.0, { i8*, i32 }* %ehtmp.0, align 8 - store i8 0, i8* %finvar.0, align 1 - br label %finally.0 - - cont.1: ; preds = %entry - store i64 %call.0, i64* %x, align 8 - invoke void @plark(i8* nest undef) - to label %cont.2 unwind label %pad.1 - - cont.2: ; preds = %cont.1 - br i1 false, label %then.0, label %else.0 - - then.0: ; preds = %cont.2 - %call.1 = invoke i16 @noret(i8* nest undef) - to label %cont.3 unwind label %pad.1 - - fallthrough.0: ; preds = %else.0 - store i64 123, i64* %x, align 8 - store i8 1, i8* %finvar.0, align 1 - invoke void @deferreturn(i8* nest undef, i8* %y) - to label %cont.0 unwind label %pad.0 - - else.0: ; preds = %cont.2 - br label %fallthrough.0 - - cont.3: ; preds = %then.0 - unreachable - - cont.4: ; preds = %catch.1 - br label %finok.0 - - finres.0: ; preds = %cont.0 - %excv.0 = load { i8*, i32 }, { i8*, i32 }* %ehtmp.0, align 8 - resume { i8*, i32 } %excv.0 - - finret.0: ; preds = %cont.0 - ret void - } + define void @baz(ptr nest %nest.0) #0 personality ptr @__gccgo_personality_v0 { + entry: + %ehtmp.0 = alloca { ptr, i32 }, align 8 + %x = alloca i64, align 8 + %y = alloca i8, align 1 + %sret.actual.0 = alloca { i8, i8 }, align 1 + %sret.actual.1 = alloca { i8, i8 }, align 1 + %finvar.0 = alloca i8, align 1 + store i64 0, ptr %x, align 8 + store i8 0, ptr %y, align 1 + %call.0 = invoke i64 @id(ptr nest undef, i64 99) + to label %cont.1 unwind label %pad.1 + + finok.0: ; preds = %cont.4 + store i8 1, ptr %finvar.0, align 1 + br label %finally.0 + + finally.0: ; preds = %catchpad.0, %finok.0 + br label %finish.0 + + pad.0: ; preds = %fallthrough.0, %finish.0 + %ex.0 = landingpad { ptr, i32 } + catch ptr null + br label %catch.0 + + catch.0: ; preds = %pad.0 + call void @checkdefer(ptr nest undef, ptr %y) + br label %finish.0 + + finish.0: ; preds = %catch.0, %finally.0 + invoke void @deferreturn(ptr nest undef, ptr %y) + to label %cont.0 unwind label %pad.0 + + cont.0: ; preds = %fallthrough.0, %finish.0 + %fload.0 = load i8, ptr %finvar.0, align 1 + %icmp.0 = icmp eq i8 %fload.0, 1 + br i1 %icmp.0, label %finret.0, label %finres.0 + + pad.1: ; preds = %then.0, %cont.1, %entry + %ex.1 = landingpad { ptr, i32 } + catch ptr null + br label %catch.1 + + catch.1: ; preds = %pad.1 + invoke void @plix(ptr nest undef) + to label %cont.4 unwind label %catchpad.0 + + catchpad.0: ; preds = %catch.1 + %ex2.0 = landingpad { ptr, i32 } + cleanup + store { ptr, i32 } %ex2.0, ptr %ehtmp.0, align 8 + store i8 0, ptr %finvar.0, align 1 + br label %finally.0 + + cont.1: ; preds = %entry + store i64 %call.0, ptr %x, align 8 + invoke void @plark(ptr nest undef) + to label %cont.2 unwind label %pad.1 + + cont.2: ; preds = %cont.1 + br i1 false, label %then.0, label %else.0 + + then.0: ; preds = %cont.2 + %call.1 = invoke i16 @noret(ptr nest undef) + to label %cont.3 unwind label %pad.1 + + fallthrough.0: ; preds = %else.0 + store i64 123, ptr %x, align 8 + store i8 1, ptr %finvar.0, align 1 + invoke void @deferreturn(ptr nest undef, ptr %y) + to label %cont.0 unwind label %pad.0 + + else.0: ; preds = %cont.2 + br label %fallthrough.0 + + cont.3: ; preds = %then.0 + unreachable + + cont.4: ; preds = %catch.1 + br label %finok.0 + + finres.0: ; preds = %cont.0 + %excv.0 = load { ptr, i32 }, ptr %ehtmp.0, align 8 + resume { ptr, i32 } %excv.0 + + finret.0: ; preds = %cont.0 + ret void + } )RAW_RESULT"); bool isOK = h.expectValue(func->function(), exp); @@ -886,90 +886,91 @@ EXPECT_FALSE(broken && "Module failed to verify."); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define i64 @baz(i8* nest %nest.0, i64 %p0) #0 personality i32 (i32, i32, i64, i8*, i8*)* @__gccgo_personality_v0 { - entry: - %ehtmp.0 = alloca { i8*, i32 }, align 8 - %p0.addr = alloca i64, align 8 - %ret = alloca i64, align 8 - %x = alloca i8, align 1 - %finvar.0 = alloca i8, align 1 - store i64 %p0, i64* %p0.addr, align 8 - store i64 0, i64* %ret, align 8 - store i8 0, i8* %x, align 1 - %call.0 = invoke i64 @splat(i8* nest undef, i64 99) - to label %cont.1 unwind label %pad.1 - - finok.0: ; preds = %cont.2 - store i8 1, i8* %finvar.0, align 1 - br label %finally.0 - - finally.0: ; preds = %catchpad.0, %finok.0 - br label %finish.0 - - pad.0: ; preds = %else.0, %then.0, %finish.0 - %ex.0 = landingpad { i8*, i32 } - catch i8* null - br label %catch.0 - - catch.0: ; preds = %pad.0 - call void @checkdefer(i8* nest undef, i8* %x) - br label %finish.0 - - finish.0: ; preds = %catch.0, %finally.0 - invoke void @deferreturn(i8* nest undef, i8* %x) - to label %cont.0 unwind label %pad.0 - - cont.0: ; preds = %else.0, %then.0, %finish.0 - %fload.0 = load i8, i8* %finvar.0, align 1 - %icmp.1 = icmp eq i8 %fload.0, 1 - br i1 %icmp.1, label %finret.0, label %finres.0 - - pad.1: ; preds = %entry - %ex.1 = landingpad { i8*, i32 } - catch i8* null - br label %catch.1 - - catch.1: ; preds = %pad.1 - %call.1 = invoke i64 @splat(i8* nest undef, i64 13) - to label %cont.2 unwind label %catchpad.0 - - catchpad.0: ; preds = %catch.1 - %ex2.0 = landingpad { i8*, i32 } - cleanup - store { i8*, i32 } %ex2.0, { i8*, i32 }* %ehtmp.0, align 8 - store i8 0, i8* %finvar.0, align 1 - br label %finally.0 - - cont.1: ; preds = %entry - %icmp.0 = icmp eq i64 %call.0, 88 - %zext.0 = zext i1 %icmp.0 to i8 - %trunc.0 = trunc i8 %zext.0 to i1 - br i1 %trunc.0, label %then.0, label %else.0 - - then.0: ; preds = %cont.1 - store i64 22, i64* %ret, align 8 - store i8 1, i8* %finvar.0, align 1 - invoke void @deferreturn(i8* nest undef, i8* %x) - to label %cont.0 unwind label %pad.0 - - else.0: ; preds = %cont.1 - %p0.ld.0 = load i64, i64* %p0.addr, align 8 - store i64 %p0.ld.0, i64* %ret, align 8 - store i8 1, i8* %finvar.0, align 1 - invoke void @deferreturn(i8* nest undef, i8* %x) - to label %cont.0 unwind label %pad.0 - - cont.2: ; preds = %catch.1 - br label %finok.0 - - finres.0: ; preds = %cont.0 - %excv.0 = load { i8*, i32 }, { i8*, i32 }* %ehtmp.0, align 8 - resume { i8*, i32 } %excv.0 - - finret.0: ; preds = %cont.0 - %ret.ld.1 = load i64, i64* %ret, align 8 - ret i64 %ret.ld.1 - } + define i64 @baz(ptr nest %nest.0, i64 %p0) #0 personality ptr @__gccgo_personality_v0 { + entry: + %ehtmp.0 = alloca { ptr, i32 }, align 8 + %p0.addr = alloca i64, align 8 + %ret = alloca i64, align 8 + %x = alloca i8, align 1 + %finvar.0 = alloca i8, align 1 + store i64 %p0, ptr %p0.addr, align 8 + store i64 0, ptr %ret, align 8 + store i8 0, ptr %x, align 1 + %call.0 = invoke i64 @splat(ptr nest undef, i64 99) + to label %cont.1 unwind label %pad.1 + + finok.0: ; preds = %cont.2 + store i8 1, ptr %finvar.0, align 1 + br label %finally.0 + + finally.0: ; preds = %catchpad.0, %finok.0 + br label %finish.0 + + pad.0: ; preds = %else.0, %then.0, %finish.0 + %ex.0 = landingpad { ptr, i32 } + catch ptr null + br label %catch.0 + + catch.0: ; preds = %pad.0 + call void @checkdefer(ptr nest undef, ptr %x) + br label %finish.0 + + finish.0: ; preds = %catch.0, %finally.0 + invoke void @deferreturn(ptr nest undef, ptr %x) + to label %cont.0 unwind label %pad.0 + + cont.0: ; preds = %else.0, %then.0, %finish.0 + %fload.0 = load i8, ptr %finvar.0, align 1 + %icmp.1 = icmp eq i8 %fload.0, 1 + br i1 %icmp.1, label %finret.0, label %finres.0 + + pad.1: ; preds = %entry + %ex.1 = landingpad { ptr, i32 } + catch ptr null + br label %catch.1 + + catch.1: ; preds = %pad.1 + %call.1 = invoke i64 @splat(ptr nest undef, i64 13) + to label %cont.2 unwind label %catchpad.0 + + catchpad.0: ; preds = %catch.1 + %ex2.0 = landingpad { ptr, i32 } + cleanup + store { ptr, i32 } %ex2.0, ptr %ehtmp.0, align 8 + store i8 0, ptr %finvar.0, align 1 + br label %finally.0 + + cont.1: ; preds = %entry + %icmp.0 = icmp eq i64 %call.0, 88 + + %zext.0 = zext i1 %icmp.0 to i8 + %trunc.0 = trunc i8 %zext.0 to i1 + br i1 %trunc.0, label %then.0, label %else.0 + + then.0: ; preds = %cont.1 + store i64 22, ptr %ret, align 8 + store i8 1, ptr %finvar.0, align 1 + invoke void @deferreturn(ptr nest undef, ptr %x) + to label %cont.0 unwind label %pad.0 + + else.0: ; preds = %cont.1 + %p0.ld.0 = load i64, ptr %p0.addr, align 8 + store i64 %p0.ld.0, ptr %ret, align 8 + store i8 1, ptr %finvar.0, align 1 + invoke void @deferreturn(ptr nest undef, ptr %x) + to label %cont.0 unwind label %pad.0 + + cont.2: ; preds = %catch.1 + br label %finok.0 + + finres.0: ; preds = %cont.0 + %excv.0 = load { ptr, i32 }, ptr %ehtmp.0, align 8 + resume { ptr, i32 } %excv.0 + + finret.0: ; preds = %cont.0 + %ret.ld.1 = load i64, ptr %ret, align 8 + ret i64 %ret.ld.1 + } )RAW_RESULT"); bool isOK = h.expectValue(func->function(), exp);
diff --git a/unittests/BackendCore/BackendVarTests.cpp b/unittests/BackendCore/BackendVarTests.cpp index 526cd9d..48da657 100644 --- a/unittests/BackendCore/BackendVarTests.cpp +++ b/unittests/BackendCore/BackendVarTests.cpp
@@ -66,7 +66,7 @@ ASSERT_TRUE(ve2 != nullptr); Bstatement *es = h.mkExprStmt(ve2); EXPECT_EQ(repr(ve2->value()), "%loc1 = alloca i64, align 8"); - EXPECT_EQ(repr(es), "%loc1.ld.0 = load i64, i64* %loc1, align 8"); + EXPECT_EQ(repr(es), "%loc1.ld.0 = load i64, ptr %loc1, align 8"); // Make sure error detection is working Bvariable *loce = be->local_variable(func1, "", be->error_type(), nullptr, @@ -159,7 +159,7 @@ false, loc, &inits); ASSERT_TRUE(tvar != nullptr); ASSERT_TRUE(inits != nullptr); - EXPECT_EQ(repr(inits), "store i64 64, i64* %tmpv.0, align 8"); + EXPECT_EQ(repr(inits), "store i64 64, ptr %tmpv.0, align 8"); h.addStmt(inits); @@ -302,8 +302,7 @@ { DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - @desc = internal constant { i64 } { i64 ptrtoint - (i64 (i8*, i32, i32, i64*)* @foo to i64) } + @desc = internal constant { i64 } { i64 ptrtoint (ptr @foo to i64) } )RAW_RESULT"); bool isOK = h.expectValue(ims->value(), exp); @@ -460,8 +459,7 @@ ASSERT_TRUE(gv != nullptr); EXPECT_TRUE(isa<GlobalVariable>(gv->value())); EXPECT_EQ(repr(gv->value()), "@x = global { i32 } zeroinitializer"); - EXPECT_EQ(repr(gvdecl->value()), - "i32* getelementptr inbounds ({ i32 }, { i32 }* @x, i32 0, i32 0)"); + EXPECT_EQ(repr(gvdecl->value()), "@x = global { i32 } zeroinitializer"); // Create them in the other order: definition first, // then external declaration. @@ -478,8 +476,7 @@ ASSERT_TRUE(gvdecl2 != nullptr); EXPECT_TRUE(isa<GlobalVariable>(gv2->value())); EXPECT_EQ(repr(gv2->value()), "@y = global { i32 } zeroinitializer"); - EXPECT_EQ(repr(gvdecl2->value()), - "i32* getelementptr inbounds ({ i32 }, { i32 }* @y, i32 0, i32 0)"); + EXPECT_EQ(repr(gvdecl2->value()), "@y = global { i32 } zeroinitializer"); bool broken = h.finish(PreserveDebugInfo); EXPECT_FALSE(broken && "Module failed to verify."); @@ -519,26 +516,21 @@ EXPECT_FALSE(broken && "Module failed to verify."); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { - entry: - %x = alloca i32, align 4 - %y = alloca { i32, i32 }, align 4 - %0 = bitcast i32* %x to i8* - call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) - %1 = bitcast { i32, i32 }* %y to i8* - call void @llvm.lifetime.start.p0i8(i64 8, i8* %1) - store i32 0, i32* %x, align 4 - %cast.0 = bitcast { i32, i32 }* %y to i8* - call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %cast.0, i8* align 4 bitcast ({ i32, i32 }* @const.0 to i8*), i64 8, i1 false) - %field.0 = getelementptr inbounds { i32, i32 }, { i32, i32 }* %y, i32 0, i32 1 - %y.field.ld.0 = load i32, i32* %field.0, align 4 - store i32 %y.field.ld.0, i32* %x, align 4 - %2 = bitcast i32* %x to i8* - call void @llvm.lifetime.end.p0i8(i64 4, i8* %2) - %3 = bitcast { i32, i32 }* %y to i8* - call void @llvm.lifetime.end.p0i8(i64 8, i8* %3) - ret void - } + define void @foo(ptr nest %nest.0) #0 { + entry: + %x = alloca i32, align 4 + %y = alloca { i32, i32 }, align 4 + call void @llvm.lifetime.start.p0(i64 4, ptr %x) + call void @llvm.lifetime.start.p0(i64 8, ptr %y) + store i32 0, ptr %x, align 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %y, ptr align 4 @const.0, i64 8, i1 false) + %field.0 = getelementptr inbounds { i32, i32 }, ptr %y, i32 0, i32 1 + %y.field.ld.0 = load i32, ptr %field.0, align 4 + store i32 %y.field.ld.0, ptr %x, align 4 + call void @llvm.lifetime.end.p0(i64 4, ptr %x) + call void @llvm.lifetime.end.p0(i64 8, ptr %y) + ret void + } )RAW_RESULT"); bool isOK = h.expectValue(func->function(), exp); @@ -659,12 +651,12 @@ EXPECT_FALSE(broken && "Module failed to verify."); DECLARE_EXPECTED_OUTPUT(exp, R"RAW_RESULT( - define void @foo(i8* nest %nest.0) #0 { - entry: - %localemptys2f = alloca { {}, {} }, align 1 - %localemptyintar = alloca [0 x i32], align 4 - ret void - } + define void @foo(ptr nest %nest.0) #0 { + entry: + %localemptys2f = alloca { {}, {} }, align 1 + %localemptyintar = alloca [0 x i32], align 4 + ret void + } )RAW_RESULT"); bool isOK = h.expectValue(func->function(), exp); EXPECT_TRUE(isOK && "Value does not have expected contents"); @@ -711,7 +703,7 @@ // Expect to see only one lifetime start, since A) loc1 is at the top // level, and B) loc2 uses loc1 as declVar. - const char *expected = "call void @llvm.lifetime.start.p0i8(i64"; + const char *expected = "call void @llvm.lifetime.start.p0(i64"; EXPECT_EQ(h.countInstancesInModuleDump(expected), 1u); }
diff --git a/unittests/BackendCore/TestUtils.h b/unittests/BackendCore/TestUtils.h index fa6774e..14dc355 100644 --- a/unittests/BackendCore/TestUtils.h +++ b/unittests/BackendCore/TestUtils.h
@@ -10,8 +10,10 @@ #define GOLLVM_UNITTESTS_BACKENDCORE_TESTUTILS_H #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include "llvm/IR/Verifier.h"
diff --git a/unittests/Driver/DriverTests.cpp b/unittests/Driver/DriverTests.cpp index 80ddcc2..93bd287 100644 --- a/unittests/Driver/DriverTests.cpp +++ b/unittests/Driver/DriverTests.cpp
@@ -56,7 +56,7 @@ std::unique_ptr<opt::OptTable> opts = gollvm::options::createGollvmDriverOptTable(); unsigned missingArgIndex, missingArgCount; - ArrayRef<const char *> argvv = makeArrayRef(args_); + ArrayRef<const char *> argvv(args_); opt::InputArgList args = opts->ParseArgs(argvv, missingArgIndex, missingArgCount);
diff --git a/unittests/TestUtils/DiffUtils.cpp b/unittests/TestUtils/DiffUtils.cpp index 98786d7..e4d8a7e 100644 --- a/unittests/TestUtils/DiffUtils.cpp +++ b/unittests/TestUtils/DiffUtils.cpp
@@ -30,9 +30,9 @@ // ending line (20). Which one will matter for the machinery that does // test remastering. static bool macroLineAtStart() { - if (baseline.line == 16) { + if (baseline.line == 17) { return true; - } else if (baseline.line == 20) { + } else if (baseline.line == 21) { return false; } else { assert(false && "macroLineAtStart broken -- source edited?");