Peter Collingbourne
2014-Apr-01 01:58 UTC
[LLVMdev] Proposal: Loads/stores with deterministic trap/unwind behavior
Hi, I wanted to propose an IR extension that would allow us to support zero-cost exception handling for non-call operations that may trap. I wanted to start with loads and stores through a null pointer, and later we might extend this to div/rem/mod zero. This feature is obviously useful for implementing languages such as Java and Go which deterministically translate such operations into exceptions which may be caught by the user. There are a couple of somewhat orthogonal features that this would entail: 1) Deterministic handling for loads and stores through a null pointer. 2) Ability to unwind a load/store to a specific basic block, like invoke. At the moment, we do not exactly have 1), as the optimizer considers non-volatile loads/stores through a null pointer to have undefined behavior. Volatile loads/stores are closer, but they come with their own set of baggage that can inhibit optimization. (For example, if we can prove that a load would always succeed, 'volatile' prevents us from reordering the load or deleting it if it is dead.) So I propose to add an attribute to 'load' and 'store', which we can call, say, 'nullcheck', with the following additional semantics: - If the memory address is between zero and a target-defined value (i.e. the size of the zero page) the instruction is guaranteed to trap in a target-defined manner. - The optimizer may only delete or reorder nullcheck instructions if the program cannot observe such a transformation by installing a signal handler for the trap. Therefore, the optimizer would be able to drop the attribute if it can prove that the address will always be non-null. To support 2), I propose a couple of new instructions. I haven't come up with great names for these instructions, but: - 'iload' is to 'load' as 'invoke' is to 'call'. That is, the instruction is a terminator and has normal and unwind destinations. e.g. %v = iload i8* %ptr to label %try.cont unwind label %lpad - Similarly, 'istore' is to 'store' as 'invoke' is to 'call'. istore i8 %v, i8* %ptr to label %try.cont unwind label %lpad These instructions always have 'nullcheck' semantics, plus: - If the instruction traps and the program has installed a signal handler for the trap which unwinds, the unwind is guaranteed to land at the landing pad. I've been working on an implementation of 'iload' and 'istore' which are in the attached patches, if you are interested. (They aren't ready to go in yet.) I have asm parsing/printing for both, and code generation for 'iload'. Would be interested in getting feedback on code generation as this is my first serious foray into the backend -- I haven't tried running the generated code yet and the DAG builder is a mashup of the DAG builders for 'invoke' and 'load', but I've eyeballed the asm it generates (e.g. llc produces iload-exception.s for the attached iload-exception.ll) and it looks reasonable. Thanks, -- Peter -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-Create-UnwindPoint-as-a-base-class-of-InvokeInst.patch Type: text/x-diff Size: 12876 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140331/913072b5/attachment.patch> -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-Add-ILoadInst-and-IStoreInst-classes.patch Type: text/x-diff Size: 29753 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140331/913072b5/attachment-0001.patch> -------------- next part -------------- A non-text attachment was scrubbed... Name: 0003-Add-SelectionDAG-support-for-iload.patch Type: text/x-diff Size: 4737 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140331/913072b5/attachment-0002.patch> -------------- next part -------------- ; RUN: llvm-as < %s | llvm-dis > %t1.ll ; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll ; RUN: diff %t1.ll %t2.ll @_ZTIc = external constant i8* @_ZTId = external constant i8* @_ZTIPKc = external constant i8* define i8 @_Z3barv(i8* %ptr) uwtable optsize ssp { entry: %v = iload i8* %ptr to label %try.cont unwind label %lpad try.cont: ; preds = %entry, %invoke.cont4 ret i8 %v lpad: ; preds = %entry %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 cleanup catch i8** @_ZTIc filter [2 x i8**] [i8** @_ZTIPKc, i8** @_ZTId] resume { i8*, i32 } %exn } declare i32 @__gxx_personality_v0(...) -------------- next part -------------- .text .file "../llvm/test/Feature/iload-exception.ll" .globl _Z3barv .type _Z3barv, at function _Z3barv: # @_Z3barv .cfi_startproc .cfi_personality 3, __gxx_personality_v0 .Leh_func_begin0: .cfi_lsda 3, .Lexception0 # BB#0: # %entry pushq %rax .Ltmp3: .cfi_def_cfa_offset 16 .Ltmp0: movb (%rdi), %al .Ltmp1: # BB#1: # %try.cont popq %rdx retq .LBB0_2: # %lpad .Ltmp2: movq %rax, %rdi callq _Unwind_Resume .Ltmp4: .size _Z3barv, .Ltmp4-_Z3barv .cfi_endproc .Leh_func_end0: .section .gcc_except_table,"a", at progbits .align 4 GCC_except_table0: .Lexception0: .byte 255 # @LPStart Encoding = omit .byte 3 # @TType Encoding = udata4 .asciz "\256\200\200" # @TType base offset .byte 3 # Call site Encoding = udata4 .byte 26 # Call site table length .Lset0 = .Ltmp0-.Leh_func_begin0 # >> Call Site 1 << .long .Lset0 .Lset1 = .Ltmp1-.Ltmp0 # Call between .Ltmp0 and .Ltmp1 .long .Lset1 .Lset2 = .Ltmp2-.Leh_func_begin0 # jumps to .Ltmp2 .long .Lset2 .byte 5 # On action: 3 .Lset3 = .Ltmp1-.Leh_func_begin0 # >> Call Site 2 << .long .Lset3 .Lset4 = .Leh_func_end0-.Ltmp1 # Call between .Ltmp1 and .Leh_func_end0 .long .Lset4 .long 0 # has no landing pad .byte 0 # On action: cleanup .byte 0 # >> Action Record 1 << # Cleanup .byte 0 # No further actions .byte 127 # >> Action Record 2 << # Filter TypeInfo -1 .byte 125 # Continue to action 1 .byte 3 # >> Action Record 3 << # Catch TypeInfo 3 .byte 125 # Continue to action 2 # >> Catch TypeInfos << .long _ZTIc # TypeInfo 3 .long _ZTId # TypeInfo 2 .long _ZTIPKc # TypeInfo 1 # >> Filter TypeInfos << .byte 1 # FilterInfo -1 .byte 2 # FilterInfo -2 .byte 0 .align 4 .section ".note.GNU-stack","", at progbits
Rafael Espíndola
2014-Apr-01 16:16 UTC
[LLVMdev] Proposal: Loads/stores with deterministic trap/unwind behavior
> - If the memory address is between zero and a target-defined value (i.e. the > size of the zero page) the instruction is guaranteed to trap in a > target-defined manner. > > - The optimizer may only delete or reorder nullcheck instructions if the > program cannot observe such a transformation by installing a signal handler > for the trap. Therefore, the optimizer would be able to drop the attribute > if it can prove that the address will always be non-null.We should probably say this at an IR level. For example, * A painter to the the stack is assumed non trapping. * A pointer returned by malloc (calloc, strdup, etc) is assumed non trapping. * All geps of such pointers are assumed non trapping. * null is required to trap. * it is target dependent if a ptrtoint of a non zero constant traps or not.> To support 2), I propose a couple of new instructions. I haven't come up with > great names for these instructions, but: > > - 'iload' is to 'load' as 'invoke' is to 'call'. That is, the instruction is > a terminator and has normal and unwind destinations. e.g. > > %v = iload i8* %ptr to label %try.cont unwind label %lpad > > - Similarly, 'istore' is to 'store' as 'invoke' is to 'call'. > > istore i8 %v, i8* %ptr to label %try.cont unwind label %lpad > > These instructions always have 'nullcheck' semantics, plus: > > - If the instruction traps and the program has installed a signal handler > for the trap which unwinds, the unwind is guaranteed to land at the > landing pad. > > I've been working on an implementation of 'iload' and 'istore' which are > in the attached patches, if you are interested. (They aren't ready to go > in yet.) I have asm parsing/printing for both, and code generation for > 'iload'. Would be interested in getting feedback on code generation as this > is my first serious foray into the backend -- I haven't tried running the > generated code yet and the DAG builder is a mashup of the DAG builders for > 'invoke' and 'load', but I've eyeballed the asm it generates (e.g. llc produces > iload-exception.s for the attached iload-exception.ll) and it looks reasonable.It basically assumes that runtime environment of a language using iload and istore has a signal handler that converts the segmentation fault to a null pointer exception that is propagated using the c++ abi? Sounds reasonable overall. Cheers, Rafael
Krzysztof Parzyszek
2014-Apr-01 16:35 UTC
[LLVMdev] Proposal: Loads/stores with deterministic trap/unwind behavior
How do you plan to actually create the exception? You cannot simply throw an exception (via "throw" statement) from a signal handler because the unwinding won't happen properly. To make it work you'll need a runtime support to indicate the origin of the exception (i.e. the address of the offending load/store). Alternatively, you could insert runtime checks at the loads/stores, but then it won't be "zero-cost". -Krzysztof On 3/31/2014 8:58 PM, Peter Collingbourne wrote:> Hi, > > I wanted to propose an IR extension that would allow us to support zero-cost > exception handling for non-call operations that may trap. I wanted to start > with loads and stores through a null pointer, and later we might extend this to > div/rem/mod zero. This feature is obviously useful for implementing languages > such as Java and Go which deterministically translate such operations into > exceptions which may be caught by the user. > > There are a couple of somewhat orthogonal features that this would entail: > > 1) Deterministic handling for loads and stores through a null pointer. > 2) Ability to unwind a load/store to a specific basic block, like invoke. > > At the moment, we do not exactly have 1), as the optimizer considers > non-volatile loads/stores through a null pointer to have undefined > behavior. Volatile loads/stores are closer, but they come with their own > set of baggage that can inhibit optimization. (For example, if we can prove > that a load would always succeed, 'volatile' prevents us from reordering > the load or deleting it if it is dead.) So I propose to add an attribute to > 'load' and 'store', which we can call, say, 'nullcheck', with the following > additional semantics: > > - If the memory address is between zero and a target-defined value (i.e. the > size of the zero page) the instruction is guaranteed to trap in a > target-defined manner. > > - The optimizer may only delete or reorder nullcheck instructions if the > program cannot observe such a transformation by installing a signal handler > for the trap. Therefore, the optimizer would be able to drop the attribute > if it can prove that the address will always be non-null. > > To support 2), I propose a couple of new instructions. I haven't come up with > great names for these instructions, but: > > - 'iload' is to 'load' as 'invoke' is to 'call'. That is, the instruction is > a terminator and has normal and unwind destinations. e.g. > > %v = iload i8* %ptr to label %try.cont unwind label %lpad > > - Similarly, 'istore' is to 'store' as 'invoke' is to 'call'. > > istore i8 %v, i8* %ptr to label %try.cont unwind label %lpad > > These instructions always have 'nullcheck' semantics, plus: > > - If the instruction traps and the program has installed a signal handler > for the trap which unwinds, the unwind is guaranteed to land at the > landing pad. > > I've been working on an implementation of 'iload' and 'istore' which are > in the attached patches, if you are interested. (They aren't ready to go > in yet.) I have asm parsing/printing for both, and code generation for > 'iload'. Would be interested in getting feedback on code generation as this > is my first serious foray into the backend -- I haven't tried running the > generated code yet and the DAG builder is a mashup of the DAG builders for > 'invoke' and 'load', but I've eyeballed the asm it generates (e.g. llc produces > iload-exception.s for the attached iload-exception.ll) and it looks reasonable. > > Thanks, > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Peter Collingbourne
2014-Apr-01 18:38 UTC
[LLVMdev] Proposal: Loads/stores with deterministic trap/unwind behavior
On Tue, Apr 01, 2014 at 11:35:16AM -0500, Krzysztof Parzyszek wrote:> How do you plan to actually create the exception?The runtime library can invoke the unwinder directly (i.e. using _Unwind_RaiseException).> You cannot simply > throw an exception (via "throw" statement) from a signal handler because > the unwinding won't happen properly. To make it work you'll need a > runtime support to indicate the origin of the exception (i.e. the > address of the offending load/store). Alternatively, you could insert > runtime checks at the loads/stores, but then it won't be "zero-cost".I'm pretty sure that it is possible to unwind through signal handlers. This is, for example, how gccgo implements some run-time panics. Thanks, -- Peter
Peter Collingbourne
2014-Apr-01 18:48 UTC
[LLVMdev] Proposal: Loads/stores with deterministic trap/unwind behavior
On Tue, Apr 01, 2014 at 12:16:37PM -0400, Rafael Espíndola wrote:> > - If the memory address is between zero and a target-defined value (i.e. the > > size of the zero page) the instruction is guaranteed to trap in a > > target-defined manner. > > > > - The optimizer may only delete or reorder nullcheck instructions if the > > program cannot observe such a transformation by installing a signal handler > > for the trap. Therefore, the optimizer would be able to drop the attribute > > if it can prove that the address will always be non-null. > > We should probably say this at an IR level. For example, > > * A painter to the the stack is assumed non trapping. > * A pointer returned by malloc (calloc, strdup, etc) is assumed non trapping. > * All geps of such pointers are assumed non trapping. > * null is required to trap. > * it is target dependent if a ptrtoint of a non zero constant traps or not.That sounds about right. I would also add for the last point that it is target dependent whether geps of a null pointer constant trap.> > To support 2), I propose a couple of new instructions. I haven't come up with > > great names for these instructions, but: > > > > - 'iload' is to 'load' as 'invoke' is to 'call'. That is, the instruction is > > a terminator and has normal and unwind destinations. e.g. > > > > %v = iload i8* %ptr to label %try.cont unwind label %lpad > > > > - Similarly, 'istore' is to 'store' as 'invoke' is to 'call'. > > > > istore i8 %v, i8* %ptr to label %try.cont unwind label %lpad > > > > These instructions always have 'nullcheck' semantics, plus: > > > > - If the instruction traps and the program has installed a signal handler > > for the trap which unwinds, the unwind is guaranteed to land at the > > landing pad. > > > > I've been working on an implementation of 'iload' and 'istore' which are > > in the attached patches, if you are interested. (They aren't ready to go > > in yet.) I have asm parsing/printing for both, and code generation for > > 'iload'. Would be interested in getting feedback on code generation as this > > is my first serious foray into the backend -- I haven't tried running the > > generated code yet and the DAG builder is a mashup of the DAG builders for > > 'invoke' and 'load', but I've eyeballed the asm it generates (e.g. llc produces > > iload-exception.s for the attached iload-exception.ll) and it looks reasonable. > > It basically assumes that runtime environment of a language using > iload and istore has a signal handler that converts the segmentation > fault to a null pointer exception that is propagated using the c++ > abi?Exactly. Thanks, -- Peter
Andrew Trick
2014-Apr-05 07:21 UTC
[LLVMdev] Proposal: Loads/stores with deterministic trap/unwind behavior
On Mar 31, 2014, at 6:58 PM, Peter Collingbourne <peter at pcc.me.uk> wrote:> Hi, > > I wanted to propose an IR extension that would allow us to support zero-cost > exception handling for non-call operations that may trap. I wanted to start > with loads and stores through a null pointer, and later we might extend this to > div/rem/mod zero. This feature is obviously useful for implementing languages > such as Java and Go which deterministically translate such operations into > exceptions which may be caught by the user. > > There are a couple of somewhat orthogonal features that this would entail: > > 1) Deterministic handling for loads and stores through a null pointer. > 2) Ability to unwind a load/store to a specific basic block, like invoke. > > At the moment, we do not exactly have 1), as the optimizer considers > non-volatile loads/stores through a null pointer to have undefined > behavior. Volatile loads/stores are closer, but they come with their own > set of baggage that can inhibit optimization. (For example, if we can prove > that a load would always succeed, 'volatile' prevents us from reordering > the load or deleting it if it is dead.) So I propose to add an attribute to > 'load' and 'store', which we can call, say, 'nullcheck', with the following > additional semantics: > > - If the memory address is between zero and a target-defined value (i.e. the > size of the zero page) the instruction is guaranteed to trap in a > target-defined manner. > > - The optimizer may only delete or reorder nullcheck instructions if the > program cannot observe such a transformation by installing a signal handler > for the trap. Therefore, the optimizer would be able to drop the attribute > if it can prove that the address will always be non-null. > > To support 2), I propose a couple of new instructions. I haven't come up with > great names for these instructions, but: > > - 'iload' is to 'load' as 'invoke' is to 'call'. That is, the instruction is > a terminator and has normal and unwind destinations. e.g. > > %v = iload i8* %ptr to label %try.cont unwind label %lpad > > - Similarly, 'istore' is to 'store' as 'invoke' is to 'call'. > > istore i8 %v, i8* %ptr to label %try.cont unwind label %lpad > > These instructions always have 'nullcheck' semantics, plus: > > - If the instruction traps and the program has installed a signal handler > for the trap which unwinds, the unwind is guaranteed to land at the > landing pad. > > I've been working on an implementation of 'iload' and 'istore' which are > in the attached patches, if you are interested. (They aren't ready to go > in yet.) I have asm parsing/printing for both, and code generation for > 'iload'. Would be interested in getting feedback on code generation as this > is my first serious foray into the backend -- I haven't tried running the > generated code yet and the DAG builder is a mashup of the DAG builders for > 'invoke' and 'load', but I've eyeballed the asm it generates (e.g. llc produces > iload-exception.s for the attached iload-exception.ll) and it looks reasonable.Hi Peter. All due respect, I don’t think it’s right to introduce new load/store instructions with equivalent semantics to and+icmp+br+load/store. ‘invoke’ is different. It is needed because there is no way for the caller to explicitly check for an exception. We do introduce intrinsics that encapsulate things like overflow checks. This is done to eliminate control flow edges that tend to inhibit LLVM’s optimizer and instruction selection. But you’re not removing the control flow, so this technique does not apply. Null checks should actually be exposed in IR so general optimizations can remove redundant checks. Ideally this would just be a machine code pass that can hoist a load/store above a branch and nuke the compare. However, I can see how it’s easier to relate the compare operand to the address arithmetic at IR level. To do this at IR level, you could introduce a pre-CodeGen pass that converts cmp+br+load/store into a checked load intrinsic. Since this intrinsic only exists for instruction selection, the optimizer doesn’t need to know about it. The intrinsic would need to be lowered to an MI pseudo-instruction that feels like a load/store to the backend, but is a terminator. During code emission you could grab the address of that pseudo load/store and its resulting branch target to inform the runtime. I can envision having a front end generate an intrinsic for explicit null checks so that an optimization pass can do something special with these, like reorder null checks and let the runtime recover. But I would not include the load/store semantics in the check. And this is entirely independent from the codegen issue of whether to use trapping loads and stores. -Andy> > Thanks, > -- > Peter > <0001-Create-UnwindPoint-as-a-base-class-of-InvokeInst.patch><0002-Add-ILoadInst-and-IStoreInst-classes.patch><0003-Add-SelectionDAG-support-for-iload.patch><iload-exception.ll><iload-exception.s>_______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Peter Collingbourne
2014-Apr-07 03:52 UTC
[LLVMdev] Proposal: Loads/stores with deterministic trap/unwind behavior
On Sat, Apr 05, 2014 at 12:21:17AM -0700, Andrew Trick wrote:> > On Mar 31, 2014, at 6:58 PM, Peter Collingbourne <peter at pcc.me.uk> wrote: > > > Hi, > > > > I wanted to propose an IR extension that would allow us to support zero-cost > > exception handling for non-call operations that may trap. I wanted to start > > with loads and stores through a null pointer, and later we might extend this to > > div/rem/mod zero. This feature is obviously useful for implementing languages > > such as Java and Go which deterministically translate such operations into > > exceptions which may be caught by the user. > > > > There are a couple of somewhat orthogonal features that this would entail: > > > > 1) Deterministic handling for loads and stores through a null pointer. > > 2) Ability to unwind a load/store to a specific basic block, like invoke. > > > > At the moment, we do not exactly have 1), as the optimizer considers > > non-volatile loads/stores through a null pointer to have undefined > > behavior. Volatile loads/stores are closer, but they come with their own > > set of baggage that can inhibit optimization. (For example, if we can prove > > that a load would always succeed, 'volatile' prevents us from reordering > > the load or deleting it if it is dead.) So I propose to add an attribute to > > 'load' and 'store', which we can call, say, 'nullcheck', with the following > > additional semantics: > > > > - If the memory address is between zero and a target-defined value (i.e. the > > size of the zero page) the instruction is guaranteed to trap in a > > target-defined manner. > > > > - The optimizer may only delete or reorder nullcheck instructions if the > > program cannot observe such a transformation by installing a signal handler > > for the trap. Therefore, the optimizer would be able to drop the attribute > > if it can prove that the address will always be non-null. > > > > To support 2), I propose a couple of new instructions. I haven't come up with > > great names for these instructions, but: > > > > - 'iload' is to 'load' as 'invoke' is to 'call'. That is, the instruction is > > a terminator and has normal and unwind destinations. e.g. > > > > %v = iload i8* %ptr to label %try.cont unwind label %lpad > > > > - Similarly, 'istore' is to 'store' as 'invoke' is to 'call'. > > > > istore i8 %v, i8* %ptr to label %try.cont unwind label %lpad > > > > These instructions always have 'nullcheck' semantics, plus: > > > > - If the instruction traps and the program has installed a signal handler > > for the trap which unwinds, the unwind is guaranteed to land at the > > landing pad. > > > > I've been working on an implementation of 'iload' and 'istore' which are > > in the attached patches, if you are interested. (They aren't ready to go > > in yet.) I have asm parsing/printing for both, and code generation for > > 'iload'. Would be interested in getting feedback on code generation as this > > is my first serious foray into the backend -- I haven't tried running the > > generated code yet and the DAG builder is a mashup of the DAG builders for > > 'invoke' and 'load', but I've eyeballed the asm it generates (e.g. llc produces > > iload-exception.s for the attached iload-exception.ll) and it looks reasonable. > > Hi Peter. All due respect, I don’t think it’s right to introduce new load/store instructions with equivalent semantics to and+icmp+br+load/store.I don't think the new instructions have equivalent semantics. If the null check fails with the iload/istore instructions, we need to throw the appropriate language-specific exception and evaluate it against the landing pad. There may also need to be an active exception that can be resumed. As far as I can tell, the frontend would need to emit IR that calls the language runtime to manually throw the exception. This IR would need to be recognized by the IR optimization that converts the icmp+br+load/store to a checked load/store. It seems to me that it would be simpler to just start with the checked load/store.> ‘invoke’ is different. It is needed because there is no way for the caller to explicitly check for an exception. > > We do introduce intrinsics that encapsulate things like overflow checks. This is done to eliminate control flow edges that tend to inhibit LLVM’s optimizer and instruction selection. But you’re not removing the control flow, so this technique does not apply. Null checks should actually be exposed in IR so general optimizations can remove redundant checks.My idea for removing redundant checks is to teach the IR optimizer to treat iloads/istores as if they were null checks. Is there any reason why this wouldn't work?> Ideally this would just be a machine code pass that can hoist a load/store above a branch and nuke the compare. However, I can see how it’s easier to relate the compare operand to the address arithmetic at IR level. > > To do this at IR level, you could introduce a pre-CodeGen pass that converts cmp+br+load/store into a checked load intrinsic. Since this intrinsic only exists for instruction selection, the optimizer doesn’t need to know about it.I did initially consider implementing the checked load/store as an intrinsic. But there are relatively boring reasons why this won't work at present. For example, there is no current way to represent a struct load using an intrinsic, as there is no mangling for struct types. Also, named structs would need a mangling that is resistant to renames. Rather than solve these problems, I decided to avoid intrinsics entirely.> The intrinsic would need to be lowered to an MI pseudo-instruction that feels like a load/store to the backend, but is a terminator. During code emission you could grab the address of that pseudo load/store and its resulting branch target to inform the runtime.As far as I know, a load can lower to multiple machine instructions. This will definitely be the case for the Go frontend that I'm working with, as its IR tends to use struct loads/stores quite frequently. So I'm not sure if this will work. I think it needs to look a lot like how the lowering for invokes currently looks, with a pair of EH_LABELs around a set of ordinary load/store MIs -- which is how I implemented it. Thanks, -- Peter
Maybe Matching Threads
- [LLVMdev] Proposal: Loads/stores with deterministic trap/unwind behavior
- [LLVMdev] RFC: How to represent SEH (__try / __except) in LLVM IR
- [LLVMdev] Possible miscompilation?
- [LLVMdev] RFC: How to represent SEH (__try / __except) in LLVM IR
- [LLVMdev] [cfe-dev] Code generation for noexcept functions