[PATCH] SelectionDAG Stack Protector Insertion

Michael Gottesman mgottesman at apple.com
Tue Aug 13 17:28:42 PDT 2013


Hey Jakob!

Attached is a patch which uses the new stack protector check intrinsic to insert a stack protector check in FinishBasicBlock after we have already decided on whether or not to tail call call sites. This prevents the stack protector basic block expansion from disrupting sibling tail calls.

A global outline of the flow of the patch is:

1. I introduce a new StackProtectorDescriptor object following the example of the BitTest/Switch code introducing the CaseBlock/BitTestBlock structure. To satisfy my paranoia I made it a class so I could hide some implementations details related to initialization. The descriptor contains per-BB data which we clear for every BB we process (the success/parent machine basic block) and per-Function data that we clear as we process each function (the failure machine basic block). We do this so we can reuse the failure basic block for each return statement in the function.

2. When we visit the stack protector check intrinsic, we do not attach any actual code to the DAG. Instead we initialize the stack protector descriptor with the information we need to emit the loads/comparisons/new basic blocks, export our one operand from the basic block, and then call getControlRoot() to ensure that our exports are flushed properly. Calling getControlRoot() is necessary since we are going to process the return statement of the basic block which will eliminate the export (from what I understand).

3. In FinishBasicBlock (again following the lead of how we handle BitTests/Switches), if we initialized our stack protector with per-BB state while we were processing the actual basic block, we:
	a. Find the split point right before the first terminator of the parent basic block.
	b. While doing that we copy any physical registers referenced in the terminators of the parent basic block into temporary registers before the split point and back into the correct physical registers after the split point. This allows us to not have to deal with live-ins and let the register allocator do what it does best = ).
	c. We splice all of the parent basic block from the split point to the end of the function into the success basic block.
	d. We then code-gen a new end to the parent basic block which performs the stack protector check and branches to either the success or failure basic block.
	e. Then if the failure MBB has not been code-gened yet, we code-gen it. The failure basic block just calls __stack_chk_fail via makeLibCall. *NOTE* We only do this once since all return statements branch to the same fail BB.
	f. We clear any per-BB state from the stack protector descriptor (which consists of the parent/success basic blocks) and leave the fail basic block state around so we can reuse it.

4. When we finish a specific function, we clear the function specific state as well from the stack protector descriptor (which is just the failure basic block).

Please Review,
Michael

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-stackprotector-Teach-selectiondag-how-to-handle-the-.patch
Type: application/octet-stream
Size: 13286 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130813/5536b797/attachment.obj>
-------------- next part --------------




More information about the llvm-commits mailing list