cynecx updated this revision to Diff 321479. cynecx added a comment. clang-format changes
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D95745/new/ https://reviews.llvm.org/D95745 Files: clang/lib/Basic/TargetInfo.cpp clang/lib/CodeGen/CGStmt.cpp clang/lib/Sema/SemaStmtAsm.cpp llvm/bindings/go/llvm/ir.go llvm/include/llvm-c/Core.h llvm/include/llvm/Bitcode/LLVMBitCodes.h llvm/include/llvm/IR/InlineAsm.h llvm/lib/AsmParser/LLParser.cpp llvm/lib/Bitcode/Reader/BitcodeReader.cpp llvm/lib/Bitcode/Writer/BitcodeWriter.cpp llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h llvm/lib/IR/AsmWriter.cpp llvm/lib/IR/ConstantsContext.h llvm/lib/IR/Core.cpp llvm/lib/IR/InlineAsm.cpp llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp llvm/lib/Transforms/Utils/InlineFunction.cpp
Index: llvm/lib/Transforms/Utils/InlineFunction.cpp =================================================================== --- llvm/lib/Transforms/Utils/InlineFunction.cpp +++ llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -28,7 +28,6 @@ #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/ProfileSummaryInfo.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/VectorUtils.h" #include "llvm/IR/Argument.h" @@ -44,6 +43,7 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" @@ -61,6 +61,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Transforms/Utils/AssumeBundleBuilder.h" #include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/ValueMapper.h" #include <algorithm> #include <cassert> @@ -543,9 +544,16 @@ // instructions require no special handling. CallInst *CI = dyn_cast<CallInst>(I); - if (!CI || CI->doesNotThrow() || CI->isInlineAsm()) + if (!CI || CI->doesNotThrow()) continue; + if (CI->isInlineAsm()) { + InlineAsm *IA = cast<InlineAsm>(CI->getCalledOperand()); + if (!IA->canThrow()) { + continue; + } + } + // We do not need to (and in fact, cannot) convert possibly throwing calls // to @llvm.experimental_deoptimize (resp. @llvm.experimental.guard) into // invokes. The caller's "segment" of the deoptimization continuation Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -39,6 +39,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" @@ -2139,9 +2140,13 @@ } if (isa<InlineAsm>(Callee) && !Call.doesNotThrow()) { - // Inline asm calls cannot throw - mark them 'nounwind'. - Call.setDoesNotThrow(); - Changed = true; + InlineAsm *IA = cast<InlineAsm>(Callee); + if (!IA->canThrow()) { + // Normal inline asm calls cannot throw - mark them + // 'nounwind'. + Call.setDoesNotThrow(); + Changed = true; + } } // Try to optimize the call if possible, we require DataLayout for most of Index: llvm/lib/IR/InlineAsm.cpp =================================================================== --- llvm/lib/IR/InlineAsm.cpp +++ llvm/lib/IR/InlineAsm.cpp @@ -29,11 +29,11 @@ InlineAsm::InlineAsm(FunctionType *FTy, const std::string &asmString, const std::string &constraints, bool hasSideEffects, - bool isAlignStack, AsmDialect asmDialect) + bool isAlignStack, AsmDialect asmDialect, bool canThrow) : Value(PointerType::getUnqual(FTy), Value::InlineAsmVal), AsmString(asmString), Constraints(constraints), FTy(FTy), HasSideEffects(hasSideEffects), IsAlignStack(isAlignStack), - Dialect(asmDialect) { + Dialect(asmDialect), CanThrow(canThrow) { // Do various checks on the constraint string and type. assert(Verify(getFunctionType(), constraints) && "Function type not legal for constraints!"); @@ -41,9 +41,10 @@ InlineAsm *InlineAsm::get(FunctionType *FTy, StringRef AsmString, StringRef Constraints, bool hasSideEffects, - bool isAlignStack, AsmDialect asmDialect) { + bool isAlignStack, AsmDialect asmDialect, + bool canThrow) { InlineAsmKeyType Key(AsmString, Constraints, FTy, hasSideEffects, - isAlignStack, asmDialect); + isAlignStack, asmDialect, canThrow); LLVMContextImpl *pImpl = FTy->getContext().pImpl; return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(FTy), Key); } Index: llvm/lib/IR/Core.cpp =================================================================== --- llvm/lib/IR/Core.cpp +++ llvm/lib/IR/Core.cpp @@ -444,11 +444,11 @@ return Str.c_str(); } -LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, - char *AsmString, size_t AsmStringSize, - char *Constraints, size_t ConstraintsSize, - LLVMBool HasSideEffects, LLVMBool IsAlignStack, - LLVMInlineAsmDialect Dialect) { +LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, char *AsmString, + size_t AsmStringSize, char *Constraints, + size_t ConstraintsSize, LLVMBool HasSideEffects, + LLVMBool IsAlignStack, + LLVMInlineAsmDialect Dialect, LLVMBool CanThrow) { InlineAsm::AsmDialect AD; switch (Dialect) { case LLVMInlineAsmDialectATT: @@ -461,10 +461,9 @@ return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), StringRef(AsmString, AsmStringSize), StringRef(Constraints, ConstraintsSize), - HasSideEffects, IsAlignStack, AD)); + HasSideEffects, IsAlignStack, AD, CanThrow)); } - /*--.. Operations on module contexts ......................................--*/ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M) { return wrap(&unwrap(M)->getContext()); Index: llvm/lib/IR/ConstantsContext.h =================================================================== --- llvm/lib/IR/ConstantsContext.h +++ llvm/lib/IR/ConstantsContext.h @@ -463,24 +463,26 @@ bool HasSideEffects; bool IsAlignStack; InlineAsm::AsmDialect AsmDialect; + bool CanThrow; InlineAsmKeyType(StringRef AsmString, StringRef Constraints, FunctionType *FTy, bool HasSideEffects, bool IsAlignStack, - InlineAsm::AsmDialect AsmDialect) + InlineAsm::AsmDialect AsmDialect, bool canThrow) : AsmString(AsmString), Constraints(Constraints), FTy(FTy), HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack), - AsmDialect(AsmDialect) {} + AsmDialect(AsmDialect), CanThrow(canThrow) {} InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &) : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()), FTy(Asm->getFunctionType()), HasSideEffects(Asm->hasSideEffects()), - IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()) {} + IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()), + CanThrow(Asm->canThrow()) {} bool operator==(const InlineAsmKeyType &X) const { return HasSideEffects == X.HasSideEffects && IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect && AsmString == X.AsmString && Constraints == X.Constraints && - FTy == X.FTy; + FTy == X.FTy && CanThrow == X.CanThrow; } bool operator==(const InlineAsm *Asm) const { @@ -489,12 +491,12 @@ AsmDialect == Asm->getDialect() && AsmString == Asm->getAsmString() && Constraints == Asm->getConstraintString() && - FTy == Asm->getFunctionType(); + FTy == Asm->getFunctionType() && CanThrow == Asm->canThrow(); } unsigned getHash() const { return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack, - AsmDialect, FTy); + AsmDialect, FTy, CanThrow); } using TypeClass = ConstantInfo<InlineAsm>::TypeClass; @@ -502,7 +504,7 @@ InlineAsm *create(TypeClass *Ty) const { assert(PointerType::getUnqual(FTy) == Ty); return new InlineAsm(FTy, std::string(AsmString), std::string(Constraints), - HasSideEffects, IsAlignStack, AsmDialect); + HasSideEffects, IsAlignStack, AsmDialect, CanThrow); } }; Index: llvm/lib/IR/AsmWriter.cpp =================================================================== --- llvm/lib/IR/AsmWriter.cpp +++ llvm/lib/IR/AsmWriter.cpp @@ -2440,6 +2440,8 @@ // We don't emit the AD_ATT dialect as it's the assumed default. if (IA->getDialect() == InlineAsm::AD_Intel) Out << "inteldialect "; + if (IA->canThrow()) + Out << "unwind "; Out << '"'; printEscapedString(IA->getAsmString(), Out); Out << "\", \""; Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -755,7 +755,8 @@ void visitStoreToSwiftError(const StoreInst &I); void visitFreeze(const FreezeInst &I); - void visitInlineAsm(const CallBase &Call); + void visitInlineAsm(const CallBase &Call, + const BasicBlock *EHPadBB = nullptr); void visitIntrinsicCall(const CallInst &I, unsigned Intrinsic); void visitTargetIntrinsic(const CallInst &I, unsigned Intrinsic); void visitConstrainedFPIntrinsic(const ConstrainedFPIntrinsic &FPI); Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2792,7 +2792,7 @@ const Value *Callee(I.getCalledOperand()); const Function *Fn = dyn_cast<Function>(Callee); if (isa<InlineAsm>(Callee)) - visitInlineAsm(I); + visitInlineAsm(I, EHPadBB); else if (Fn && Fn->isIntrinsic()) { switch (Fn->getIntrinsicID()) { default: @@ -8208,7 +8208,8 @@ } // end anonymous namespace /// visitInlineAsm - Handle a call to an InlineAsm object. -void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call) { +void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call, + const BasicBlock *EHPadBB) { const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand()); /// ConstraintOperands - Information about all of the constraints. @@ -8296,19 +8297,46 @@ ExtraInfo.update(T); } - // We won't need to flush pending loads if this asm doesn't touch // memory and is nonvolatile. SDValue Flag, Chain = (HasSideEffect) ? getRoot() : DAG.getRoot(); + bool EmitEHLabels = isa<InvokeInst>(Call) && IA->canThrow(); + if (EmitEHLabels) { + assert(EHPadBB && "InvokeInst must have an EHPadBB"); + } bool IsCallBr = isa<CallBrInst>(Call); - if (IsCallBr) { - // If this is a callbr we need to flush pending exports since inlineasm_br - // is a terminator. We need to do this before nodes are glued to - // the inlineasm_br node. + + if (IsCallBr || EmitEHLabels) { + // If this is a callbr or invoke we need to flush pending exports since + // inlineasm_br and invoke are terminators. + // We need to do this before nodes are glued to the inlineasm_br node. Chain = getControlRoot(); } + MCSymbol *BeginLabel = nullptr; + if (EmitEHLabels) { + MachineFunction &MF = DAG.getMachineFunction(); + MachineModuleInfo &MMI = MF.getMMI(); + + // Insert a label before the invoke call to mark the try range. This can be + // used to detect deletion of the invoke via the MachineModuleInfo. + BeginLabel = MMI.getContext().createTempSymbol(); + + // For SjLj, keep track of which landing pads go with which invokes + // so as to maintain the ordering of pads in the LSDA. + unsigned CallSiteIndex = MMI.getCurrentCallSite(); + if (CallSiteIndex) { + MF.setCallSiteBeginLabel(BeginLabel, CallSiteIndex); + LPadToCallSiteMap[FuncInfo.MBBMap[EHPadBB]].push_back(CallSiteIndex); + + // Now that the call site is handled, stop tracking it. + MMI.setCurrentCallSite(0); + } + + Chain = DAG.getEHLabel(getCurSDLoc(), Chain, BeginLabel); + } + // Second pass over the constraints: compute which constraint option to use. for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) { // If this is an output operand with a matching input operand, look up the @@ -8699,8 +8727,32 @@ if (!OutChains.empty()) Chain = DAG.getNode(ISD::TokenFactor, getCurSDLoc(), MVT::Other, OutChains); + if (EmitEHLabels) { + assert(BeginLabel && "BeginLabel should've been set"); + + MachineFunction &MF = DAG.getMachineFunction(); + MachineModuleInfo &MMI = MF.getMMI(); + + // Insert a label at the end of the invoke call to mark the try range. This + // can be used to detect deletion of the invoke via the MachineModuleInfo. + MCSymbol *EndLabel = MMI.getContext().createTempSymbol(); + Chain = DAG.getEHLabel(getCurSDLoc(), Chain, EndLabel); + + // Inform MachineModuleInfo of range. + auto Pers = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()); + // There is a platform (e.g. wasm) that uses funclet style IR but does not + // actually use outlined funclets and their LSDA info style. + if (MF.hasEHFunclets() && isFuncletEHPersonality(Pers)) { + WinEHFuncInfo *EHInfo = DAG.getMachineFunction().getWinEHFuncInfo(); + EHInfo->addIPToStateRange(cast<InvokeInst>(&Call), BeginLabel, EndLabel); + } else if (!isScopedEHPersonality(Pers)) { + MF.addInvoke(FuncInfo.MBBMap[EHPadBB], BeginLabel, EndLabel); + } + } + // Only Update Root if inline assembly has a memory effect. - if (ResultValues.empty() || HasSideEffect || !OutChains.empty() || IsCallBr) + if (ResultValues.empty() || HasSideEffect || !OutChains.empty() || IsCallBr || + EmitEHLabels) DAG.setRoot(Chain); } Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2422,8 +2422,6 @@ const BasicBlock *EHPadBB = I.getSuccessor(1); const Function *Fn = I.getCalledFunction(); - if (I.isInlineAsm()) - return false; // FIXME: support invoking patchpoint and statepoint intrinsics. if (Fn && Fn->isIntrinsic()) @@ -2441,12 +2439,37 @@ if (!isa<LandingPadInst>(EHPadBB->getFirstNonPHI())) return false; + bool LowerInlineAsm = false; + if (I.isInlineAsm()) { + const InlineAsm *IA = cast<InlineAsm>(I.getCalledOperand()); + if (!IA->canThrow()) { + // Fast path without emitting EH_LABELs. + + if (!translateInlineAsm(I, MIRBuilder)) + return false; + + MachineBasicBlock *InvokeMBB = &MIRBuilder.getMBB(), + *ReturnMBB = &getMBB(*ReturnBB); + + // Update successor info. + addSuccessorWithProb(InvokeMBB, ReturnMBB, BranchProbability::getOne()); + + MIRBuilder.buildBr(*ReturnMBB); + return true; + } else { + LowerInlineAsm = true; + } + } + // Emit the actual call, bracketed by EH_LABELs so that the MF knows about // the region covered by the try. MCSymbol *BeginSymbol = Context.createTempSymbol(); MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(BeginSymbol); - if (!translateCallBase(I, MIRBuilder)) + if (LowerInlineAsm) { + if (!translateInlineAsm(I, MIRBuilder)) + return false; + } else if (!translateCallBase(I, MIRBuilder)) return false; MCSymbol *EndSymbol = Context.createTempSymbol(); Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2414,9 +2414,9 @@ } if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) { - Record.push_back(unsigned(IA->hasSideEffects()) | - unsigned(IA->isAlignStack()) << 1 | - unsigned(IA->getDialect()&1) << 2); + Record.push_back( + unsigned(IA->hasSideEffects()) | unsigned(IA->isAlignStack()) << 1 | + unsigned(IA->getDialect() & 1) << 2 | unsigned(IA->canThrow()) << 3); // Add the asm string. const std::string &AsmStr = IA->getAsmString(); Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2822,7 +2822,7 @@ } // This version adds support for the asm dialect keywords (e.g., // inteldialect). - case bitc::CST_CODE_INLINEASM: { + case bitc::CST_CODE_INLINEASM_OLD2: { if (Record.size() < 2) return error("Invalid record"); std::string AsmStr, ConstrStr; @@ -2847,6 +2847,33 @@ InlineAsm::AsmDialect(AsmDialect)); break; } + // This version adds support for the unwind keyword. + case bitc::CST_CODE_INLINEASM: { + if (Record.size() < 2) + return error("Invalid record"); + std::string AsmStr, ConstrStr; + bool HasSideEffects = Record[0] & 1; + bool IsAlignStack = (Record[0] >> 1) & 1; + unsigned AsmDialect = Record[0] >> 2; + bool CanThrow = (Record[0] >> 3) & 1; + unsigned AsmStrSize = Record[1]; + if (2 + AsmStrSize >= Record.size()) + return error("Invalid record"); + unsigned ConstStrSize = Record[2 + AsmStrSize]; + if (3 + AsmStrSize + ConstStrSize > Record.size()) + return error("Invalid record"); + + for (unsigned i = 0; i != AsmStrSize; ++i) + AsmStr += (char)Record[2 + i]; + for (unsigned i = 0; i != ConstStrSize; ++i) + ConstrStr += (char)Record[3 + AsmStrSize + i]; + UpgradeInlineAsmString(&AsmStr); + V = InlineAsm::get( + cast<FunctionType>(getPointerElementFlatType(CurFullTy)), AsmStr, + ConstrStr, HasSideEffects, IsAlignStack, + InlineAsm::AsmDialect(AsmDialect), CanThrow); + break; + } case bitc::CST_CODE_BLOCKADDRESS:{ if (Record.size() < 3) return error("Invalid record"); Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -3389,18 +3389,19 @@ case lltok::kw_asm: { // ValID ::= 'asm' SideEffect? AlignStack? IntelDialect? STRINGCONSTANT ',' // STRINGCONSTANT - bool HasSideEffect, AlignStack, AsmDialect; + bool HasSideEffect, AlignStack, AsmDialect, CanThrow; Lex.Lex(); if (parseOptionalToken(lltok::kw_sideeffect, HasSideEffect) || parseOptionalToken(lltok::kw_alignstack, AlignStack) || parseOptionalToken(lltok::kw_inteldialect, AsmDialect) || + parseOptionalToken(lltok::kw_unwind, CanThrow) || parseStringConstant(ID.StrVal) || parseToken(lltok::comma, "expected comma in inline asm expression") || parseToken(lltok::StringConstant, "expected constraint string")) return true; ID.StrVal2 = Lex.getStrVal(); - ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack)<<1) | - (unsigned(AsmDialect)<<2); + ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack) << 1) | + (unsigned(AsmDialect) << 2) | (unsigned(CanThrow) << 3); ID.Kind = ValID::t_InlineAsm; return false; } @@ -5465,9 +5466,9 @@ case ValID::t_InlineAsm: { if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2)) return error(ID.Loc, "invalid type for inline asm constraint string"); - V = InlineAsm::get(ID.FTy, ID.StrVal, ID.StrVal2, ID.UIntVal & 1, - (ID.UIntVal >> 1) & 1, - (InlineAsm::AsmDialect(ID.UIntVal >> 2))); + V = InlineAsm::get( + ID.FTy, ID.StrVal, ID.StrVal2, ID.UIntVal & 1, (ID.UIntVal >> 1) & 1, + (InlineAsm::AsmDialect(ID.UIntVal >> 2)), (ID.UIntVal >> 3) & 1); return false; } case ValID::t_GlobalName: Index: llvm/include/llvm/IR/InlineAsm.h =================================================================== --- llvm/include/llvm/IR/InlineAsm.h +++ llvm/include/llvm/IR/InlineAsm.h @@ -44,10 +44,11 @@ bool HasSideEffects; bool IsAlignStack; AsmDialect Dialect; + bool CanThrow; InlineAsm(FunctionType *Ty, const std::string &AsmString, const std::string &Constraints, bool hasSideEffects, - bool isAlignStack, AsmDialect asmDialect); + bool isAlignStack, AsmDialect asmDialect, bool canThrow); /// When the ConstantUniqueMap merges two types and makes two InlineAsms /// identical, it destroys one of them with this method. @@ -62,11 +63,12 @@ static InlineAsm *get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack = false, - AsmDialect asmDialect = AD_ATT); + AsmDialect asmDialect = AD_ATT, bool canThrow = false); bool hasSideEffects() const { return HasSideEffects; } bool isAlignStack() const { return IsAlignStack; } AsmDialect getDialect() const { return Dialect; } + bool canThrow() const { return CanThrow; } /// getType - InlineAsm's are always pointers. /// Index: llvm/include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -372,11 +372,14 @@ CST_CODE_CE_INBOUNDS_GEP = 20, // INBOUNDS_GEP: [n x operands] CST_CODE_BLOCKADDRESS = 21, // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#] CST_CODE_DATA = 22, // DATA: [n x elements] - CST_CODE_INLINEASM = 23, // INLINEASM: [sideeffect|alignstack| + CST_CODE_INLINEASM_OLD2 = 23, // INLINEASM: [sideeffect|alignstack| // asmdialect,asmstr,conststr] CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands] - CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] - CST_CODE_POISON = 26, // POISON + CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] + CST_CODE_POISON = 26, // POISON + CST_CODE_INLINEASM = 27, // INLINEASM: [sideeffect|alignstack| + // asmdialect|unwind, + // asmstr,conststr] }; /// CastOpcodes - These are values used in the bitcode files to encode which Index: llvm/include/llvm-c/Core.h =================================================================== --- llvm/include/llvm-c/Core.h +++ llvm/include/llvm-c/Core.h @@ -860,11 +860,11 @@ * * @see InlineAsm::get() */ -LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, - char *AsmString, size_t AsmStringSize, - char *Constraints, size_t ConstraintsSize, - LLVMBool HasSideEffects, LLVMBool IsAlignStack, - LLVMInlineAsmDialect Dialect); +LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, char *AsmString, + size_t AsmStringSize, char *Constraints, + size_t ConstraintsSize, LLVMBool HasSideEffects, + LLVMBool IsAlignStack, + LLVMInlineAsmDialect Dialect, LLVMBool CanThrow); /** * Obtain the context to which this module is associated. Index: llvm/bindings/go/llvm/ir.go =================================================================== --- llvm/bindings/go/llvm/ir.go +++ llvm/bindings/go/llvm/ir.go @@ -1304,12 +1304,12 @@ } // Operations on inline assembly -func InlineAsm(t Type, asmString, constraints string, hasSideEffects, isAlignStack bool, dialect InlineAsmDialect) (rv Value) { +func InlineAsm(t Type, asmString, constraints string, hasSideEffects, isAlignStack bool, dialect InlineAsmDialect, canThrow bool) (rv Value) { casm := C.CString(asmString) defer C.free(unsafe.Pointer(casm)) cconstraints := C.CString(constraints) defer C.free(unsafe.Pointer(cconstraints)) - rv.C = C.LLVMGetInlineAsm(t.C, casm, C.size_t(len(asmString)), cconstraints, C.size_t(len(constraints)), boolToLLVMBool(hasSideEffects), boolToLLVMBool(isAlignStack), C.LLVMInlineAsmDialect(dialect)) + rv.C = C.LLVMGetInlineAsm(t.C, casm, C.size_t(len(asmString)), cconstraints, C.size_t(len(constraints)), boolToLLVMBool(hasSideEffects), boolToLLVMBool(isAlignStack), C.LLVMInlineAsmDialect(dialect), boolToLLVMBool(canThrow)) return } Index: clang/lib/Sema/SemaStmtAsm.cpp =================================================================== --- clang/lib/Sema/SemaStmtAsm.cpp +++ clang/lib/Sema/SemaStmtAsm.cpp @@ -228,7 +228,7 @@ StringRef Clobber = Clobbers[i]->getString(); // We only check registers, therefore we don't check cc and memory // clobbers - if (Clobber == "cc" || Clobber == "memory") + if (Clobber == "cc" || Clobber == "memory" || Clobber == "unwind") continue; Clobber = Target.getNormalizedGCCRegisterName(Clobber, true); // Go over the output's registers we collected Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -2115,13 +2115,15 @@ } static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, - bool ReadOnly, bool ReadNone, bool NoMerge, - const AsmStmt &S, + bool HasUnwindClobber, bool ReadOnly, + bool ReadNone, bool NoMerge, const AsmStmt &S, const std::vector<llvm::Type *> &ResultRegTypes, CodeGenFunction &CGF, std::vector<llvm::Value *> &RegResults) { - Result.addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); + if (!HasUnwindClobber) + Result.addAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::NoUnwind); + if (NoMerge) Result.addAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoMerge); @@ -2468,13 +2470,18 @@ } Constraints += InOutConstraints; + bool HasUnwindClobber = false; + // Clobbers for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) { StringRef Clobber = S.getClobber(i); if (Clobber == "memory") ReadOnly = ReadNone = false; - else if (Clobber != "cc") { + else if (Clobber == "unwind") { + HasUnwindClobber = true; + continue; + } else if (Clobber != "cc") { Clobber = getTarget().getNormalizedGCCRegisterName(Clobber); if (CGM.getCodeGenOpts().StackClashProtector && getTarget().isSPRegName(Clobber)) { @@ -2508,6 +2515,9 @@ Constraints += '}'; } + assert(!(HasUnwindClobber && IsGCCAsmGoto) && + "unwind clobber can't be used with asm goto"); + // Add machine specific clobbers std::string MachineClobbers = getTarget().getClobbers(); if (!MachineClobbers.empty()) { @@ -2530,23 +2540,28 @@ bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0; llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ? llvm::InlineAsm::AD_Intel : llvm::InlineAsm::AD_ATT; - llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect, - /* IsAlignStack */ false, AsmDialect); + llvm::InlineAsm *IA = llvm::InlineAsm::get( + FTy, AsmString, Constraints, HasSideEffect, + /* IsAlignStack */ false, AsmDialect, HasUnwindClobber); std::vector<llvm::Value*> RegResults; if (IsGCCAsmGoto) { llvm::CallBrInst *Result = Builder.CreateCallBr(IA, Fallthrough, Transfer, Args); EmitBlock(Fallthrough); - UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, ReadOnly, - ReadNone, InNoMergeAttributedStmt, S, ResultRegTypes, - *this, RegResults); + UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, false, + ReadOnly, ReadNone, InNoMergeAttributedStmt, S, + ResultRegTypes, *this, RegResults); + } else if (HasUnwindClobber) { + llvm::CallBase *Result = EmitCallOrInvoke(IA, Args, ""); + UpdateAsmCallInst(*Result, HasSideEffect, true, ReadOnly, ReadNone, + InNoMergeAttributedStmt, S, ResultRegTypes, *this, + RegResults); } else { llvm::CallInst *Result = Builder.CreateCall(IA, Args, getBundlesForFunclet(IA)); - UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, ReadOnly, - ReadNone, InNoMergeAttributedStmt, S, ResultRegTypes, - *this, RegResults); + UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, false, + ReadOnly, ReadNone, InNoMergeAttributedStmt, S, + ResultRegTypes, *this, RegResults); } assert(RegResults.size() == ResultRegTypes.size()); Index: clang/lib/Basic/TargetInfo.cpp =================================================================== --- clang/lib/Basic/TargetInfo.cpp +++ clang/lib/Basic/TargetInfo.cpp @@ -475,8 +475,8 @@ /// a valid clobber in an inline asm statement. This is used by /// Sema. bool TargetInfo::isValidClobber(StringRef Name) const { - return (isValidGCCRegisterName(Name) || - Name == "memory" || Name == "cc"); + return (isValidGCCRegisterName(Name) || Name == "memory" || Name == "cc" || + Name == "unwind"); } /// isValidGCCRegisterName - Returns whether the passed in string
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits