Commit 6c17dd8c by Karl Schimpf

Fixes case where terminator instruction is missing at end of function.

If the bitcode parser detects that the last block in the function is missing a terminator, generate an error message and insert a terminator instruction. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4214 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1210013005.
parent e0df91fe
...@@ -78,6 +78,10 @@ def main(): ...@@ -78,6 +78,10 @@ def main():
argparser.add_argument('--echo-cmd', required=False, argparser.add_argument('--echo-cmd', required=False,
action='store_true', action='store_true',
help='Trace command that generates ICE instructions') help='Trace command that generates ICE instructions')
argparser.add_argument('--tbc', required=False, action='store_true',
help='Input is textual bitcode (not .ll)')
argparser.add_argument('--expect-fail', required=False, action='store_true',
help='Negate success of run by using LLVM not')
argparser.add_argument('--args', '-a', nargs=argparse.REMAINDER, argparser.add_argument('--args', '-a', nargs=argparse.REMAINDER,
default=[], default=[],
help='Remaining arguments are passed to pnacl-sz') help='Remaining arguments are passed to pnacl-sz')
...@@ -93,13 +97,24 @@ def main(): ...@@ -93,13 +97,24 @@ def main():
raise RuntimeError("Can't specify both '--llvm-source' and " + raise RuntimeError("Can't specify both '--llvm-source' and " +
"'--no-local-syms'") "'--no-local-syms'")
if args.llvm_source and args.tbc:
raise RuntimeError("Can't specify both '--tbc' and '--llvm-source'")
if args.llvm and args.tbc:
raise RuntimeError("Can't specify both '--tbc' and '--llvm'")
cmd = [] cmd = []
if not args.llvm_source: if args.tbc:
cmd = [os.path.join(pnacl_bin_path, 'pnacl-bcfuzz'), llfile,
'-bitcode-as-text', '-output', '-', '|']
elif not args.llvm_source:
cmd = [os.path.join(pnacl_bin_path, 'llvm-as'), llfile, '-o', '-', '|', cmd = [os.path.join(pnacl_bin_path, 'llvm-as'), llfile, '-o', '-', '|',
os.path.join(pnacl_bin_path, 'pnacl-freeze')] os.path.join(pnacl_bin_path, 'pnacl-freeze')]
if not args.no_local_syms: if not args.no_local_syms:
cmd += ['--allow-local-symbol-tables'] cmd += ['--allow-local-symbol-tables']
cmd += ['|'] cmd += ['|']
if args.expect_fail:
cmd += [os.path.join(pnacl_bin_path, 'not')]
cmd += [args.pnacl_sz] cmd += [args.pnacl_sz]
cmd += ['--target', args.target] cmd += ['--target', args.target]
if args.insts: if args.insts:
......
...@@ -1961,9 +1961,16 @@ private: ...@@ -1961,9 +1961,16 @@ private:
}; };
void FunctionParser::ExitBlock() { void FunctionParser::ExitBlock() {
if (isIRGenerationDisabled()) { // Check if the last instruction in the function was terminating.
return; if (!InstIsTerminating) {
Error("Last instruction in function not terminator");
if (isIRGenerationDisabled())
return;
// Recover by inserting an unreachable instruction.
CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get()));
} }
if (isIRGenerationDisabled())
return;
// Before translating, check for blocks without instructions, and // Before translating, check for blocks without instructions, and
// insert unreachable. This shouldn't happen, but be safe. // insert unreachable. This shouldn't happen, but be safe.
size_t Index = 0; size_t Index = 0;
...@@ -2256,6 +2263,7 @@ void FunctionParser::ProcessRecord() { ...@@ -2256,6 +2263,7 @@ void FunctionParser::ProcessRecord() {
} }
case naclbitc::FUNC_CODE_INST_RET: { case naclbitc::FUNC_CODE_INST_RET: {
// RET: [opval?] // RET: [opval?]
InstIsTerminating = true;
if (!isValidRecordSizeInRange(0, 1, "return")) if (!isValidRecordSizeInRange(0, 1, "return"))
return; return;
if (Values.empty()) { if (Values.empty()) {
...@@ -2270,10 +2278,10 @@ void FunctionParser::ProcessRecord() { ...@@ -2270,10 +2278,10 @@ void FunctionParser::ProcessRecord() {
} }
CurrentNode->appendInst(Ice::InstRet::create(Func.get(), RetVal)); CurrentNode->appendInst(Ice::InstRet::create(Func.get(), RetVal));
} }
InstIsTerminating = true;
return; return;
} }
case naclbitc::FUNC_CODE_INST_BR: { case naclbitc::FUNC_CODE_INST_BR: {
InstIsTerminating = true;
if (Values.size() == 1) { if (Values.size() == 1) {
// BR: [bb#] // BR: [bb#]
if (isIRGenerationDisabled()) if (isIRGenerationDisabled())
...@@ -2306,7 +2314,6 @@ void FunctionParser::ProcessRecord() { ...@@ -2306,7 +2314,6 @@ void FunctionParser::ProcessRecord() {
CurrentNode->appendInst( CurrentNode->appendInst(
Ice::InstBr::create(Func.get(), Cond, ThenBlock, ElseBlock)); Ice::InstBr::create(Func.get(), Cond, ThenBlock, ElseBlock));
} }
InstIsTerminating = true;
return; return;
} }
case naclbitc::FUNC_CODE_INST_SWITCH: { case naclbitc::FUNC_CODE_INST_SWITCH: {
...@@ -2318,6 +2325,7 @@ void FunctionParser::ProcessRecord() { ...@@ -2318,6 +2325,7 @@ void FunctionParser::ProcessRecord() {
// unnecesary data fields (i.e. constants 1). These were not // unnecesary data fields (i.e. constants 1). These were not
// cleaned up in PNaCl bitcode because the bitcode format was // cleaned up in PNaCl bitcode because the bitcode format was
// already frozen when the problem was noticed. // already frozen when the problem was noticed.
InstIsTerminating = true;
if (!isValidRecordSizeAtLeast(4, "switch")) if (!isValidRecordSizeAtLeast(4, "switch"))
return; return;
...@@ -2383,17 +2391,16 @@ void FunctionParser::ProcessRecord() { ...@@ -2383,17 +2391,16 @@ void FunctionParser::ProcessRecord() {
if (isIRGenDisabled) if (isIRGenDisabled)
return; return;
CurrentNode->appendInst(Switch); CurrentNode->appendInst(Switch);
InstIsTerminating = true;
return; return;
} }
case naclbitc::FUNC_CODE_INST_UNREACHABLE: { case naclbitc::FUNC_CODE_INST_UNREACHABLE: {
// UNREACHABLE: [] // UNREACHABLE: []
InstIsTerminating = true;
if (!isValidRecordSize(0, "unreachable")) if (!isValidRecordSize(0, "unreachable"))
return; return;
if (isIRGenerationDisabled()) if (isIRGenerationDisabled())
return; return;
CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get()));
InstIsTerminating = true;
return; return;
} }
case naclbitc::FUNC_CODE_INST_PHI: { case naclbitc::FUNC_CODE_INST_PHI: {
......
...@@ -48,7 +48,7 @@ config.name = 'subzero' ...@@ -48,7 +48,7 @@ config.name = 'subzero'
config.test_format = lit.formats.ShTest() config.test_format = lit.formats.ShTest()
# suffixes: A list of file extensions to treat as test files. # suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.ll'] config.suffixes = ['.ll', '.test']
# test_source_root: The root path where tests are located. # test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(__file__) config.test_source_root = os.path.dirname(__file__)
...@@ -106,14 +106,16 @@ config.substitutions.append(('%lc2i', ' '.join(iflc2i_atts_cmd + pnacl_sz_cmd ...@@ -106,14 +106,16 @@ config.substitutions.append(('%lc2i', ' '.join(iflc2i_atts_cmd + pnacl_sz_cmd
config.substitutions.append(('%pnacl_sz', pnacl_sz_tool)) config.substitutions.append(('%pnacl_sz', pnacl_sz_tool))
pnaclbintools = [r"\bFileCheck\b", pnaclbintools = [r'\b' + x + r'\b' for x in
r"\ble32-nacl-objdump\b", ['FileCheck',
r"\bllvm-as\b", 'le32-nacl-objdump',
r"\bllvm-mc\b", 'llvm-as',
r"\bllvm-readobj\b", 'llvm-mc',
r"\bnot\b", 'llvm-readobj',
r"\bpnacl-freeze\b", 'not',
r"\bpnacl-bcdis\b"] 'pnacl-bcdis',
'pnacl-bcfuzz',
'pnacl-freeze']]
for tool in pnaclbintools: for tool in pnaclbintools:
# The re.sub() line is adapted from one of LLVM's lit.cfg files. # The re.sub() line is adapted from one of LLVM's lit.cfg files.
......
65535,8,2;
1,1;
65535,17,2;
1,4;
7,32;
2;
21,0,0,0;
7,1;
65534;
8,2,0,0,0;
65535,19,2;
5,0;
65534;
65535,14,2;
1,0,102,105,98;
65534;
65535,12,2;
1,3;
65535,11,2;
1,0;
4,2;
65534;
28,2,1,36;
11,1,2,1;
10,2;
2,3,2,1;
34,0,5,0;
2,1,5,0;
65534;
5534;
65534;
; Test that we handle functions that don't end with a terminator instruction.
; See issue: https://code.google.com/p/nativeclient/issues/detail?id=4214
RUN: %p2i --expect-fail --tbc -i %p/Input/no-terminator-inst.tbc --insts \
RUN: | FileCheck --check-prefix=NO-TERM-INST %s
; NO-TERM-INST: Last instruction in function not terminator
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment