diff options
-rw-r--r-- | docs/LangRef.html | 4 | ||||
-rw-r--r-- | include/llvm/Intrinsics.td | 4 | ||||
-rw-r--r-- | test/Feature/intrinsics.ll | 10 | ||||
-rw-r--r-- | utils/TableGen/CodeGenIntrinsics.h | 5 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 3 | ||||
-rw-r--r-- | utils/TableGen/IntrinsicEmitter.cpp | 25 |
6 files changed, 43 insertions, 8 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html index a781992f89..ab0f9e1dca 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -8386,7 +8386,7 @@ LLVM</a>.</p> <h5>Syntax:</h5> <pre> - declare void @llvm.trap() + declare void @llvm.trap() noreturn nounwind </pre> <h5>Overview:</h5> @@ -8411,7 +8411,7 @@ LLVM</a>.</p> <h5>Syntax:</h5> <pre> - declare void @llvm.debugtrap() + declare void @llvm.debugtrap() nounwind </pre> <h5>Overview:</h5> diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 794848c19c..1ebf13b1d8 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -55,6 +55,8 @@ class NoCapture<int argNo> : IntrinsicProperty { int ArgNo = argNo; } +def IntrNoReturn : IntrinsicProperty; + //===----------------------------------------------------------------------===// // Types used by intrinsics. //===----------------------------------------------------------------------===// @@ -400,7 +402,7 @@ def int_invariant_end : Intrinsic<[], // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, GCCBuiltin<"__builtin_flt_rounds">; -def int_trap : Intrinsic<[]>, +def int_trap : Intrinsic<[], [], [IntrNoReturn]>, GCCBuiltin<"__builtin_trap">; def int_debugtrap : Intrinsic<[]>, GCCBuiltin<"__builtin_debugtrap">; diff --git a/test/Feature/intrinsics.ll b/test/Feature/intrinsics.ll index c4e3db6174..9e7dc6d410 100644 --- a/test/Feature/intrinsics.ll +++ b/test/Feature/intrinsics.ll @@ -1,6 +1,7 @@ ; RUN: llvm-as < %s | llvm-dis > %t1.ll ; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll ; RUN: diff %t1.ll %t2.ll +; RUN: FileCheck %s < %t1.ll declare i1 @llvm.isunordered.f32(float, float) @@ -58,3 +59,12 @@ define void @libm() { } ; FIXME: test ALL the intrinsics in this file. + +; rdar://11542750 +; CHECK: declare void @llvm.trap() noreturn nounwind +declare void @llvm.trap() + +define void @trap() { + call void @llvm.trap() + ret void +} diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index 3f6ba61172..6efe952ea2 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -72,7 +72,10 @@ namespace llvm { /// canThrow - True if the intrinsic can throw. bool canThrow; - + + /// isNoReturn - True if the intrinsic is no-return. + bool isNoReturn; + enum ArgAttribute { NoCapture }; diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index cf6793570a..dfa9526cc9 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -387,6 +387,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { isOverloaded = false; isCommutative = false; canThrow = false; + isNoReturn = false; if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") @@ -511,6 +512,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { isCommutative = true; else if (Property->getName() == "Throws") canThrow = true; + else if (Property->getName() == "IntrNoReturn") + isNoReturn = true; else if (Property->isSubClassOf("NoCapture")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 941c0537d6..9e2bb9d87f 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -451,6 +451,9 @@ namespace { if (L->canThrow != R->canThrow) return R->canThrow; + if (L->isNoReturn != R->isNoReturn) + return R->isNoReturn; + // Try to order by readonly/readnone attribute. ModRefKind LK = getModRefKind(*L); ModRefKind RK = getModRefKind(*R); @@ -549,16 +552,30 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { ModRefKind modRef = getModRefKind(intrinsic); - if (!intrinsic.canThrow || modRef) { + if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn) { OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, "; + bool Emitted = false; if (!intrinsic.canThrow) { OS << "Attribute::NoUnwind"; - if (modRef) OS << '|'; + Emitted = true; + } + + if (intrinsic.isNoReturn) { + if (Emitted) OS << '|'; + OS << "Attribute::NoReturn"; + Emitted = true; } + switch (modRef) { case MRK_none: break; - case MRK_readonly: OS << "Attribute::ReadOnly"; break; - case MRK_readnone: OS << "Attribute::ReadNone"; break; + case MRK_readonly: + if (Emitted) OS << '|'; + OS << "Attribute::ReadOnly"; + break; + case MRK_readnone: + if (Emitted) OS << '|'; + OS << "Attribute::ReadNone"; + break; } OS << ");\n"; } |