blob: 6baa61488ddd9ffc2040b774487e2b5e5aef555e [file] [log] [blame]
; Copyright 2012 Google Inc. All Rights Reserved.
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; This chunk of assembly defines an explicit layout that is intimate with the
; tests in basic_block_decomposer_unittest.cc. Please do not modify one
; without the other.
;
; The code below lays out instructions that should be carved up into 5 basic
; blocks, including one that is created via a pc-relative jump to a non-labeled
; location.
.386
.MODEL FLAT, C
.CODE
EXTERN C func1:PROC
EXTERN C func2:PROC ; non-returning
PUBLIC assembly_func, assembly_func_end
PUBLIC unreachable_label, interrupt_label
PUBLIC jump_table, case_table, case_0, case_1, case_default
; We only declare a single top-level function here, as the linker adds
; indirection to functions under incremental building, which throws off
; our tests.
assembly_start PROC
; Make sure the internal labels aren't synonymous with the proc.
nop
assembly_func LABEL PROC
; This looks like what VC generates for a complex switch statement.
; In this case there are two lookup tables, one from selector value to
; case index, and a jump table to the cases within the function. The function
; also makes like control flow merges into the lookup tables by ending in
; a call to a non-returning function.
; get the first argument
mov eax, [esp + 4]
cmp eax, 0ffh
movzx eax, BYTE PTR[case_table + eax]
jmp DWORD PTR[jump_table + eax * 4]
unreachable_label LABEL PROC
; Some unreachable code lives here.
nop
case_0 LABEL PROC
; Create a short run of instructions.
mov eax, 4
mov esi, esi
sub eax, 1
; Perform a short jump back into the middle of the above instructions
; to break up the basic block.
jnz $-3
ret
case_1 LABEL PROC
; This case falls through to the default.
call func1
case_default LABEL PROC
push 1
; func2 is a non-returning function, and we've seen cases where the optimizer
; generates code that ends in a call to a non-returning function.
; The disassembler should identify the jump table and the lookup table as
; data due to the mov and jmp instructions above that refer to them,
; and not disassemble into the data even though control seemingly flows
; into it.
call func2
interrupt_label LABEL PROC
int 3
; We add some padding so that jump_table ends up being 4-byte aligned.
int 3
int 3
jump_table \
dd case_0
dd case_1
dd case_default
case_table \
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
db 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1
assembly_func_end LABEL PROC
; Place some padding after the end of the function so that the
; assembly_func_end label lies within the block. This allows our decomposer
; to handle this (artificial) code.
int 3
assembly_start ENDP
END