Commit bba77687 by Karl Schimpf

Fix bitcode parser to check type signatures of functions.

Before, type signatures of functions were only checked when called. This CL fixes this by checking all function signatures. BUG=None R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1579203002 .
parent 56958cb3
...@@ -880,6 +880,8 @@ void Converter::installGlobalDeclarations(Module *Mod) { ...@@ -880,6 +880,8 @@ void Converter::installGlobalDeclarations(Module *Mod) {
StrBuf << "\n Use flag -allow-externally-defined-symbols to override"; StrBuf << "\n Use flag -allow-externally-defined-symbols to override";
report_fatal_error(StrBuf.str()); report_fatal_error(StrBuf.str());
} }
if (!IceFunc->validateTypeSignature(Ctx))
report_fatal_error(IceFunc->getTypeSignatureError(Ctx));
GlobalDeclarationMap[&Func] = IceFunc; GlobalDeclarationMap[&Func] = IceFunc;
} }
// Install global variable declarations. // Install global variable declarations.
......
...@@ -60,6 +60,56 @@ void dumpCallingConv(Ice::Ostream &, llvm::CallingConv::ID CallingConv) { ...@@ -60,6 +60,56 @@ void dumpCallingConv(Ice::Ostream &, llvm::CallingConv::ID CallingConv) {
namespace Ice { namespace Ice {
const Intrinsics::FullIntrinsicInfo *
FunctionDeclaration::getIntrinsicInfo(const GlobalContext *Ctx,
bool *IsIntrinsic) const {
*IsIntrinsic = false;
if (!hasName())
return nullptr;
bool BadIntrinsic;
const Intrinsics::FullIntrinsicInfo *Info =
Ctx->getIntrinsicsInfo().find(getName(), BadIntrinsic);
*IsIntrinsic = Info || BadIntrinsic;
return Info;
}
bool FunctionDeclaration::validateRegularTypeSignature() const {
for (SizeT i = 0; i < Signature.getNumArgs(); ++i) {
if (!isCallParameterType(Signature.getArgType(i)))
return false;
}
return isCallReturnType(Signature.getReturnType());
}
bool FunctionDeclaration::validateIntrinsicTypeSignature(
const Intrinsics::FullIntrinsicInfo *Info) const {
if (Signature.getNumArgs() != Info->getNumArgs())
return false;
for (SizeT i = 0; i < Signature.getNumArgs(); ++i) {
if (Signature.getArgType(i) != Info->getArgType(i))
return false;
}
return Signature.getReturnType() == Info->getReturnType();
}
IceString FunctionDeclaration::getTypeSignatureError(const GlobalContext *Ctx) {
std::string Buffer;
llvm::raw_string_ostream StrBuf(Buffer);
StrBuf << "Invalid";
bool IsIntrinsic;
const Intrinsics::FullIntrinsicInfo *Info =
getIntrinsicInfo(Ctx, &IsIntrinsic);
if (IsIntrinsic && Info == nullptr) {
StrBuf << " intrinsic name: " << getName();
return StrBuf.str();
}
StrBuf << " type signature for";
if (IsIntrinsic)
StrBuf << " intrinsic";
StrBuf << " " << getName() << ": " << getSignature();
return StrBuf.str();
}
void FunctionDeclaration::dumpType(Ostream &Stream) const { void FunctionDeclaration::dumpType(Ostream &Stream) const {
if (!Ice::BuildDefs::dump()) if (!Ice::BuildDefs::dump())
return; return;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "IceDefs.h" #include "IceDefs.h"
#include "IceGlobalContext.h" #include "IceGlobalContext.h"
#include "IceIntrinsics.h"
#include "IceTypes.h" #include "IceTypes.h"
#ifdef __clang__ #ifdef __clang__
...@@ -156,6 +157,32 @@ public: ...@@ -156,6 +157,32 @@ public:
return verifyLinkageDefault(Ctx); return verifyLinkageDefault(Ctx);
} }
/// Validates that the type signature of the function is correct. Returns true
/// if valid.
bool validateTypeSignature(const GlobalContext *Ctx) const {
bool IsIntrinsic;
if (const Intrinsics::FullIntrinsicInfo *Info =
getIntrinsicInfo(Ctx, &IsIntrinsic))
return validateIntrinsicTypeSignature(Info);
return !IsIntrinsic && validateRegularTypeSignature();
}
/// Generates an error message describing why validateTypeSignature returns
/// false.
IceString getTypeSignatureError(const GlobalContext *Ctx);
/// Returns corresponding PNaCl intrisic information.
const Intrinsics::FullIntrinsicInfo *
getIntrinsicInfo(const GlobalContext *Ctx) const {
bool BadIntrinsic;
return getIntrinsicInfo(Ctx, &BadIntrinsic);
}
/// Same as above, except IsIntrinsic is true if the function is intrinsic
/// (even if not a PNaCl intrinsic).
const Intrinsics::FullIntrinsicInfo *
getIntrinsicInfo(const GlobalContext *Ctx, bool *IsIntrinsic) const;
private: private:
const Ice::FuncSigType Signature; const Ice::FuncSigType Signature;
llvm::CallingConv::ID CallingConv; llvm::CallingConv::ID CallingConv;
...@@ -173,12 +200,15 @@ private: ...@@ -173,12 +200,15 @@ private:
} }
bool isIntrinsicName(const GlobalContext *Ctx) const { bool isIntrinsicName(const GlobalContext *Ctx) const {
if (!hasName()) bool IsIntrinsic;
return false; getIntrinsicInfo(Ctx, &IsIntrinsic);
bool BadIntrinsic; return IsIntrinsic;
return Ctx->getIntrinsicsInfo().find(getName(), BadIntrinsic) &&
!BadIntrinsic;
} }
bool validateRegularTypeSignature() const;
bool validateIntrinsicTypeSignature(
const Intrinsics::FullIntrinsicInfo *Info) const;
}; };
/// Models a global variable declaration, and its initializers. /// Models a global variable declaration, and its initializers.
......
...@@ -338,6 +338,8 @@ public: ...@@ -338,6 +338,8 @@ public:
installFunctionNames(); installFunctionNames();
} }
void verifyFunctionTypeSignatures();
void createValueIDs() { void createValueIDs() {
assert(VariableDeclarations); assert(VariableDeclarations);
ValueIDConstants.reserve(VariableDeclarations->size() + ValueIDConstants.reserve(VariableDeclarations->size() +
...@@ -637,6 +639,14 @@ Ice::Type TopLevelParser::convertToIceTypeError(Type *LLVMTy) { ...@@ -637,6 +639,14 @@ Ice::Type TopLevelParser::convertToIceTypeError(Type *LLVMTy) {
return Ice::IceType_void; return Ice::IceType_void;
} }
void TopLevelParser::verifyFunctionTypeSignatures() {
const Ice::GlobalContext *Ctx = getTranslator().getContext();
for (Ice::FunctionDeclaration *FuncDecl : FunctionDeclarations) {
if (!FuncDecl->validateTypeSignature(Ctx))
Error(FuncDecl->getTypeSignatureError(Ctx));
}
}
// Base class for parsing blocks within the bitcode file. Note: Because this is // Base class for parsing blocks within the bitcode file. Note: Because this is
// the base class of block parsers, we generate error messages if ParseBlock or // the base class of block parsers, we generate error messages if ParseBlock or
// ParseRecord is not overridden in derived classes. // ParseRecord is not overridden in derived classes.
...@@ -2648,16 +2658,7 @@ void FunctionParser::ProcessRecord() { ...@@ -2648,16 +2658,7 @@ void FunctionParser::ProcessRecord() {
} }
// Check if this direct call is to an Intrinsic (starts with "llvm.") // Check if this direct call is to an Intrinsic (starts with "llvm.")
bool BadIntrinsic; IntrinsicInfo = Fcn->getIntrinsicInfo(getTranslator().getContext());
IntrinsicInfo = getTranslator().getContext()->getIntrinsicsInfo().find(
Fcn->getName(), BadIntrinsic);
if (BadIntrinsic) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Invalid PNaCl intrinsic call to " << Fcn->getName();
Error(StrBuf.str());
IntrinsicInfo = nullptr;
}
if (IntrinsicInfo && IntrinsicInfo->getNumArgs() != NumParams) { if (IntrinsicInfo && IntrinsicInfo->getNumArgs() != NumParams) {
std::string Buffer; std::string Buffer;
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
...@@ -2712,16 +2713,14 @@ void FunctionParser::ProcessRecord() { ...@@ -2712,16 +2713,14 @@ void FunctionParser::ProcessRecord() {
if (Signature) if (Signature)
verifyCallArgTypeMatches(Fcn, Index, OpType, verifyCallArgTypeMatches(Fcn, Index, OpType,
Signature->getArgType(Index)); Signature->getArgType(Index));
if (IntrinsicInfo) { else if (!isCallParameterType(OpType)) {
verifyCallArgTypeMatches(Fcn, Index, OpType,
IntrinsicInfo->getArgType(Index));
} else if (!isCallParameterType(OpType)) {
std::string Buffer; std::string Buffer;
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
StrBuf << "Argument " << *Op << " of " << printName(Fcn) StrBuf << "Argument " << *Op << " of " << printName(Fcn)
<< " has invalid type: " << Op->getType(); << " has invalid type: " << Op->getType();
Error(StrBuf.str()); Error(StrBuf.str());
appendErrorInstruction(ReturnType); appendErrorInstruction(ReturnType);
return;
} }
} }
...@@ -3007,6 +3006,7 @@ private: ...@@ -3007,6 +3006,7 @@ private:
if (!GlobalDeclarationNamesAndInitializersInstalled) { if (!GlobalDeclarationNamesAndInitializersInstalled) {
Context->installGlobalNames(); Context->installGlobalNames();
Context->createValueIDs(); Context->createValueIDs();
Context->verifyFunctionTypeSignatures();
std::unique_ptr<Ice::VariableDeclarationList> Globals = std::unique_ptr<Ice::VariableDeclarationList> Globals =
Context->getGlobalVariables(); Context->getGlobalVariables();
if (Globals) if (Globals)
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 | FileCheck %s ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 | FileCheck %s
; RUN: %p2i --filetype=obj --disassemble -i %s --args -Om1 | FileCheck %s ; RUN: %p2i --filetype=obj --disassemble -i %s --args -Om1 | FileCheck %s
define internal i32 @Sdiv_const8_b(i8 %a) { define internal i32 @Sdiv_const8_b(i32 %a32) {
; CHECK-LABEL: Sdiv_const8_b ; CHECK-LABEL: Sdiv_const8_b
entry: entry:
%a = trunc i32 %a32 to i8
%div = sdiv i8 %a, 12 %div = sdiv i8 %a, 12
; CHECK: mov {{.*}},0xc ; CHECK: mov {{.*}},0xc
; CHECK-NOT: idiv 0xc ; CHECK-NOT: idiv 0xc
...@@ -14,9 +15,10 @@ entry: ...@@ -14,9 +15,10 @@ entry:
ret i32 %div_ext ret i32 %div_ext
} }
define internal i32 @Sdiv_const16_b(i16 %a) { define internal i32 @Sdiv_const16_b(i32 %a32) {
; CHECK-LABEL: Sdiv_const16_b ; CHECK-LABEL: Sdiv_const16_b
entry: entry:
%a = trunc i32 %a32 to i16
%div = sdiv i16 %a, 1234 %div = sdiv i16 %a, 1234
; CHECK: mov {{.*}},0x4d2 ; CHECK: mov {{.*}},0x4d2
; CHECK-NOT: idiv 0x4d2 ; CHECK-NOT: idiv 0x4d2
......
...@@ -40,8 +40,9 @@ entry: ...@@ -40,8 +40,9 @@ entry:
; CHECK-LABEL: no_rmw_add_i32_var ; CHECK-LABEL: no_rmw_add_i32_var
; CHECK: add e{{ax|bx|cx|dx|bp|di|si}},DWORD PTR [e{{ax|bx|cx|dx|bp|di|si}}] ; CHECK: add e{{ax|bx|cx|dx|bp|di|si}},DWORD PTR [e{{ax|bx|cx|dx|bp|di|si}}]
define internal void @rmw_add_i16_var(i32 %addr_arg, i16 %var) { define internal void @rmw_add_i16_var(i32 %addr_arg, i32 %var32) {
entry: entry:
%var = trunc i32 %var32 to i16
%addr = inttoptr i32 %addr_arg to i16* %addr = inttoptr i32 %addr_arg to i16*
%val = load i16, i16* %addr, align 1 %val = load i16, i16* %addr, align 1
%rmw = add i16 %val, %var %rmw = add i16 %val, %var
...@@ -64,8 +65,9 @@ entry: ...@@ -64,8 +65,9 @@ entry:
; CHECK-LABEL: rmw_add_i16_imm ; CHECK-LABEL: rmw_add_i16_imm
; CHECK: add WORD PTR [e{{ax|bx|cx|dx|bp|di|si}}],0x13 ; CHECK: add WORD PTR [e{{ax|bx|cx|dx|bp|di|si}}],0x13
define internal void @rmw_add_i8_var(i32 %addr_arg, i8 %var) { define internal void @rmw_add_i8_var(i32 %addr_arg, i32 %var32) {
entry: entry:
%var = trunc i32 %var32 to i8
%addr = inttoptr i32 %addr_arg to i8* %addr = inttoptr i32 %addr_arg to i8*
%val = load i8, i8* %addr, align 1 %val = load i8, i8* %addr, align 1
%rmw = add i8 %val, %var %rmw = add i8 %val, %var
......
65535,8,2;
1,1;
65535,17,2;
1,5;
2;
7,32;
7,8;
21,0,0,1;
21,0,0;
65534;
8,3,0,1,0;
8,4,0,0,0;
65535,19,2;
5,0;
65534;
65535,14,2;
1,1,84,101,115,116;
1,0,102;
65534;
65535,12,2;
1,1;
65535,11,2;
1,1;
4,2;
1,2;
4,2;
65534;
2,1,1,0;
34,0,5,2;
10;
65534;
65534;
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
; RUN: -allow-externally-defined-symbols 2>&1 \ ; RUN: -allow-externally-defined-symbols 2>&1 \
; RUN: | FileCheck %s ; RUN: | FileCheck %s
; CHECK: Argument 1 of llvm.nacl.setjmp expects i32. Found: double ; CHECK: Invalid type signature for intrinsic llvm.nacl.setjmp: i32 (double)
; RUN: pnacl-bcfuzz -bitcode-as-text \ ; RUN: pnacl-bcfuzz -bitcode-as-text \
; RUN: %p/Inputs/bad-intrinsic-arg.tbc -output - \ ; RUN: %p/Inputs/bad-intrinsic-arg.tbc -output - \
......
; Test that even if a call parameter matches its declaration, it must still ; Test that a function parameter must be a legal parameter type (unless
; be a legal call parameter type (unless declaration is intrinsic). ; declaration is intrinsic).
; REQUIRES: no_minimal_build ; REQUIRES: no_minimal_build
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
; RUN: -allow-externally-defined-symbols | FileCheck %s ; RUN: -allow-externally-defined-symbols | FileCheck %s
declare void @f(i8); declare void @f(i8);
; CHECK: Invalid type signature for f: void (i8)
define void @Test() { define void @Test() {
entry: entry:
call void @f(i8 1) call void @f(i8 1)
; CHECK: Argument 1 of f has invalid type: i8
ret void ret void
} }
; Show that we check parameter types of a function call against paramter types
; of called function.
; REQUIRES: no_minimal_build
; RUN: not %pnacl_sz -bitcode-as-text %p/Inputs/call-fcn-bad-param-type.tbc \
; RUN: -bitcode-format=pnacl -notranslate -build-on-read \
; RUN: -allow-externally-defined-symbols 2>&1 \
; RUN: | FileCheck %s
; RUN: pnacl-bcfuzz -bitcode-as-text -output - \
; RUN: %p/Inputs/call-fcn-bad-param-type.tbc \
; RUN: | not pnacl-bcdis -no-records | FileCheck %s --check-prefix=DIS
; DIS: module { // BlockID = 8
; DIS-NEXT: version 1;
; DIS-NEXT: types { // BlockID = 17
; DIS-NEXT: count 5;
; DIS-NEXT: @t0 = void;
; DIS-NEXT: @t1 = i32;
; DIS-NEXT: @t2 = i8;
; DIS-NEXT: @t3 = void (i32);
; DIS-NEXT: @t4 = void ();
; DIS-NEXT: }
; DIS-NEXT: declare external void @f0(i32);
; DIS-NEXT: define external void @f1();
; DIS-NEXT: globals { // BlockID = 19
; DIS-NEXT: count 0;
; DIS-NEXT: }
; DIS-NEXT: valuesymtab { // BlockID = 14
; DIS-NEXT: @f1 : "Test";
; DIS-NEXT: @f0 : "f";
; DIS-NEXT: }
; DIS-NEXT: function void @f1() { // BlockID = 12
; DIS-NEXT: blocks 1;
; DIS-NEXT: constants { // BlockID = 11
; DIS-NEXT: i32:
; DIS-NEXT: %c0 = i32 1;
; DIS-NEXT: i8:
; DIS-NEXT: %c1 = i8 1;
; DIS-NEXT: }
; DIS-NEXT: %b0:
; DIS-NEXT: %v0 = add i8 %c1, %c1;
; DIS-NEXT: call void @f0(i8 %c1);
; DIS-NEXT: Error({{.*}}): Parameter 1 mismatch: i8 and i32
; CHECK: Argument 1 of f expects i32. Found: i8
; DIS-NEXT: ret void;
; DIS-NEXT: }
; DIS-NEXT: }
...@@ -6,12 +6,15 @@ ...@@ -6,12 +6,15 @@
; RUN: %p2i --expect-fail -i %s --insts --args \ ; RUN: %p2i --expect-fail -i %s --insts --args \
; RUN: -allow-externally-defined-symbols | FileCheck %s ; RUN: -allow-externally-defined-symbols | FileCheck %s
declare i1 @f(); declare i32 @f();
define void @Test() { declare i64 @g();
define void @Test(i32 %ifcn) {
entry: entry:
%v = call i1 @f() %fcn = inttoptr i32 %ifcn to i1()*
; CHECK: Return type of f is invalid: i1 %v = call i1 %fcn()
; CHECK: Return type of function is invalid: i1
ret void ret void
} }
; Test that even if a call parameter matches its declaration, it must still
; be a legal call parameter type (unless declaration is intrinsic).
; REQUIRES: no_minimal_build
; RUN: %p2i --expect-fail -i %s --insts --args \
; RUN: -allow-externally-defined-symbols | FileCheck %s
declare void @f(i8);
; CHECK: Invalid type signature for f: void (i8)
define void @Test() {
entry:
call void @f(i8 1)
ret void
}
; Tests that we don't get fooled by a fake NaCl intrinsic. ; Tests that we don't get fooled by a fake NaCl intrinsic.
; TODO(kschimpf) Find way to run this through p2i. Note: Can't do this ; REQUIRES: allow_dump
; currently because run-pnacl-sz.py raises exception on error,
; and output is lost.
; RUN: %if --need=allow_dump --command llvm-as < %s \
; RUN: | %if --need=allow_dump --command pnacl-freeze \
; RUN -allow-local-symbol-tables \
; RUN: | %if --need=allow_dump --command not %pnacl_sz -notranslate \
; RUN: -verbose=inst -build-on-read \
; RUN: -allow-pnacl-reader-error-recovery \
; RUN: -allow-local-symbol-tables \
; RUN: -filetype=obj -o /dev/null \
; RUN: | %if --need=allow_dump --command FileCheck %s
; RUN: %if --need=no_dump --command llvm-as < %s \ ; RUN: %p2i --expect-fail -i %s --insts --args \
; RUN: | %if --need=no_dump --command pnacl-freeze \ ; RUN: -verbose=inst -allow-externally-defined-symbols \
; RUN -allow-local-symbol-tables \ ; RUN: | FileCheck %s
; RUN: | %if --need=no_dump --command not %pnacl_sz -notranslate \
; RUN: -verbose=inst -build-on-read \
; RUN: -allow-pnacl-reader-error-recovery \
; RUN: -allow-local-symbol-tables \
; RUN: -filetype=obj -o /dev/null \
; RUN: | %if --need=no_dump --command FileCheck %s --check-prefix=MIN
declare i32 @llvm.fake.i32(i32) declare i32 @llvm.fake.i32(i32)
define i32 @testFake(i32 %v) { ; CHECK: Error({{.*}}): Invalid intrinsic name: llvm.fake.i32
%r = call i32 @llvm.fake.i32(i32 %v)
ret i32 %r
}
; CHECK: Error({{.*}}): Invalid PNaCl intrinsic call to llvm.fake.i32
; MIN: Error({{.*}}): Invalid function record: <34 0 3 1>
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
; RUN: %p2i -i %s --args -notranslate -timing | \ ; RUN: %p2i -i %s --args -notranslate -timing | \
; RUN: FileCheck --check-prefix=NOIR %s ; RUN: FileCheck --check-prefix=NOIR %s
define internal i1 @IcmpI1(i32 %p1, i32 %p2) { define internal void @IcmpI1(i32 %p1, i32 %p2) {
entry: entry:
%a1 = trunc i32 %p1 to i1 %a1 = trunc i32 %p1 to i1
%a2 = trunc i32 %p2 to i1 %a2 = trunc i32 %p2 to i1
...@@ -18,10 +18,10 @@ entry: ...@@ -18,10 +18,10 @@ entry:
%vsge = icmp sge i1 %a1, %a2 %vsge = icmp sge i1 %a1, %a2
%vslt = icmp slt i1 %a1, %a2 %vslt = icmp slt i1 %a1, %a2
%vsle = icmp sle i1 %a1, %a2 %vsle = icmp sle i1 %a1, %a2
ret i1 %veq ret void
} }
; CHECK: define internal i1 @IcmpI1(i32 %p1, i32 %p2) { ; CHECK: define internal void @IcmpI1(i32 %p1, i32 %p2) {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: %a1 = trunc i32 %p1 to i1 ; CHECK-NEXT: %a1 = trunc i32 %p1 to i1
; CHECK-NEXT: %a2 = trunc i32 %p2 to i1 ; CHECK-NEXT: %a2 = trunc i32 %p2 to i1
...@@ -35,10 +35,10 @@ entry: ...@@ -35,10 +35,10 @@ entry:
; CHECK-NEXT: %vsge = icmp sge i1 %a1, %a2 ; CHECK-NEXT: %vsge = icmp sge i1 %a1, %a2
; CHECK-NEXT: %vslt = icmp slt i1 %a1, %a2 ; CHECK-NEXT: %vslt = icmp slt i1 %a1, %a2
; CHECK-NEXT: %vsle = icmp sle i1 %a1, %a2 ; CHECK-NEXT: %vsle = icmp sle i1 %a1, %a2
; CHECK-NEXT: ret i1 %veq ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
define internal i1 @IcmpI8(i32 %p1, i32 %p2) { define internal void @IcmpI8(i32 %p1, i32 %p2) {
entry: entry:
%a1 = trunc i32 %p1 to i8 %a1 = trunc i32 %p1 to i8
%a2 = trunc i32 %p2 to i8 %a2 = trunc i32 %p2 to i8
...@@ -52,10 +52,10 @@ entry: ...@@ -52,10 +52,10 @@ entry:
%vsge = icmp sge i8 %a1, %a2 %vsge = icmp sge i8 %a1, %a2
%vslt = icmp slt i8 %a1, %a2 %vslt = icmp slt i8 %a1, %a2
%vsle = icmp sle i8 %a1, %a2 %vsle = icmp sle i8 %a1, %a2
ret i1 %veq ret void
} }
; CHECK-NEXT: define internal i1 @IcmpI8(i32 %p1, i32 %p2) { ; CHECK-NEXT: define internal void @IcmpI8(i32 %p1, i32 %p2) {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: %a1 = trunc i32 %p1 to i8 ; CHECK-NEXT: %a1 = trunc i32 %p1 to i8
; CHECK-NEXT: %a2 = trunc i32 %p2 to i8 ; CHECK-NEXT: %a2 = trunc i32 %p2 to i8
...@@ -69,10 +69,10 @@ entry: ...@@ -69,10 +69,10 @@ entry:
; CHECK-NEXT: %vsge = icmp sge i8 %a1, %a2 ; CHECK-NEXT: %vsge = icmp sge i8 %a1, %a2
; CHECK-NEXT: %vslt = icmp slt i8 %a1, %a2 ; CHECK-NEXT: %vslt = icmp slt i8 %a1, %a2
; CHECK-NEXT: %vsle = icmp sle i8 %a1, %a2 ; CHECK-NEXT: %vsle = icmp sle i8 %a1, %a2
; CHECK-NEXT: ret i1 %veq ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
define internal i1 @IcmpI16(i32 %p1, i32 %p2) { define internal void @IcmpI16(i32 %p1, i32 %p2) {
entry: entry:
%a1 = trunc i32 %p1 to i16 %a1 = trunc i32 %p1 to i16
%a2 = trunc i32 %p2 to i16 %a2 = trunc i32 %p2 to i16
...@@ -86,10 +86,10 @@ entry: ...@@ -86,10 +86,10 @@ entry:
%vsge = icmp sge i16 %a1, %a2 %vsge = icmp sge i16 %a1, %a2
%vslt = icmp slt i16 %a1, %a2 %vslt = icmp slt i16 %a1, %a2
%vsle = icmp sle i16 %a1, %a2 %vsle = icmp sle i16 %a1, %a2
ret i1 %veq ret void
} }
; CHECK-NEXT: define internal i1 @IcmpI16(i32 %p1, i32 %p2) { ; CHECK-NEXT: define internal void @IcmpI16(i32 %p1, i32 %p2) {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: %a1 = trunc i32 %p1 to i16 ; CHECK-NEXT: %a1 = trunc i32 %p1 to i16
; CHECK-NEXT: %a2 = trunc i32 %p2 to i16 ; CHECK-NEXT: %a2 = trunc i32 %p2 to i16
...@@ -103,10 +103,10 @@ entry: ...@@ -103,10 +103,10 @@ entry:
; CHECK-NEXT: %vsge = icmp sge i16 %a1, %a2 ; CHECK-NEXT: %vsge = icmp sge i16 %a1, %a2
; CHECK-NEXT: %vslt = icmp slt i16 %a1, %a2 ; CHECK-NEXT: %vslt = icmp slt i16 %a1, %a2
; CHECK-NEXT: %vsle = icmp sle i16 %a1, %a2 ; CHECK-NEXT: %vsle = icmp sle i16 %a1, %a2
; CHECK-NEXT: ret i1 %veq ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
define internal i1 @IcmpI32(i32 %a1, i32 %a2) { define internal void @IcmpI32(i32 %a1, i32 %a2) {
entry: entry:
%veq = icmp eq i32 %a1, %a2 %veq = icmp eq i32 %a1, %a2
%vne = icmp ne i32 %a1, %a2 %vne = icmp ne i32 %a1, %a2
...@@ -118,10 +118,10 @@ entry: ...@@ -118,10 +118,10 @@ entry:
%vsge = icmp sge i32 %a1, %a2 %vsge = icmp sge i32 %a1, %a2
%vslt = icmp slt i32 %a1, %a2 %vslt = icmp slt i32 %a1, %a2
%vsle = icmp sle i32 %a1, %a2 %vsle = icmp sle i32 %a1, %a2
ret i1 %veq ret void
} }
; CHECK-NEXT: define internal i1 @IcmpI32(i32 %a1, i32 %a2) { ; CHECK-NEXT: define internal void @IcmpI32(i32 %a1, i32 %a2) {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: %veq = icmp eq i32 %a1, %a2 ; CHECK-NEXT: %veq = icmp eq i32 %a1, %a2
; CHECK-NEXT: %vne = icmp ne i32 %a1, %a2 ; CHECK-NEXT: %vne = icmp ne i32 %a1, %a2
...@@ -133,10 +133,10 @@ entry: ...@@ -133,10 +133,10 @@ entry:
; CHECK-NEXT: %vsge = icmp sge i32 %a1, %a2 ; CHECK-NEXT: %vsge = icmp sge i32 %a1, %a2
; CHECK-NEXT: %vslt = icmp slt i32 %a1, %a2 ; CHECK-NEXT: %vslt = icmp slt i32 %a1, %a2
; CHECK-NEXT: %vsle = icmp sle i32 %a1, %a2 ; CHECK-NEXT: %vsle = icmp sle i32 %a1, %a2
; CHECK-NEXT: ret i1 %veq ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
define internal i1 @IcmpI64(i64 %a1, i64 %a2) { define internal void @IcmpI64(i64 %a1, i64 %a2) {
entry: entry:
%veq = icmp eq i64 %a1, %a2 %veq = icmp eq i64 %a1, %a2
%vne = icmp ne i64 %a1, %a2 %vne = icmp ne i64 %a1, %a2
...@@ -148,10 +148,10 @@ entry: ...@@ -148,10 +148,10 @@ entry:
%vsge = icmp sge i64 %a1, %a2 %vsge = icmp sge i64 %a1, %a2
%vslt = icmp slt i64 %a1, %a2 %vslt = icmp slt i64 %a1, %a2
%vsle = icmp sle i64 %a1, %a2 %vsle = icmp sle i64 %a1, %a2
ret i1 %veq ret void
} }
; CHECK-NEXT: define internal i1 @IcmpI64(i64 %a1, i64 %a2) { ; CHECK-NEXT: define internal void @IcmpI64(i64 %a1, i64 %a2) {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: %veq = icmp eq i64 %a1, %a2 ; CHECK-NEXT: %veq = icmp eq i64 %a1, %a2
; CHECK-NEXT: %vne = icmp ne i64 %a1, %a2 ; CHECK-NEXT: %vne = icmp ne i64 %a1, %a2
...@@ -163,7 +163,7 @@ entry: ...@@ -163,7 +163,7 @@ entry:
; CHECK-NEXT: %vsge = icmp sge i64 %a1, %a2 ; CHECK-NEXT: %vsge = icmp sge i64 %a1, %a2
; CHECK-NEXT: %vslt = icmp slt i64 %a1, %a2 ; CHECK-NEXT: %vslt = icmp slt i64 %a1, %a2
; CHECK-NEXT: %vsle = icmp sle i64 %a1, %a2 ; CHECK-NEXT: %vsle = icmp sle i64 %a1, %a2
; CHECK-NEXT: ret i1 %veq ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
define internal <4 x i1> @IcmpV4xI1(<4 x i1> %a1, <4 x i1> %a2) { define internal <4 x i1> @IcmpV4xI1(<4 x i1> %a1, <4 x i1> %a2) {
...@@ -346,7 +346,7 @@ entry: ...@@ -346,7 +346,7 @@ entry:
; CHECK-NEXT: ret <4 x i1> %veq ; CHECK-NEXT: ret <4 x i1> %veq
; CHECK-NEXT: } ; CHECK-NEXT: }
define internal i1 @FcmpFloat(float %a1, float %a2) { define internal void @FcmpFloat(float %a1, float %a2) {
entry: entry:
%vfalse = fcmp false float %a1, %a2 %vfalse = fcmp false float %a1, %a2
%voeq = fcmp oeq float %a1, %a2 %voeq = fcmp oeq float %a1, %a2
...@@ -364,10 +364,10 @@ entry: ...@@ -364,10 +364,10 @@ entry:
%vune = fcmp une float %a1, %a2 %vune = fcmp une float %a1, %a2
%vuno = fcmp uno float %a1, %a2 %vuno = fcmp uno float %a1, %a2
%vtrue = fcmp true float %a1, %a2 %vtrue = fcmp true float %a1, %a2
ret i1 %voeq ret void
} }
; CHECK-NEXT: define internal i1 @FcmpFloat(float %a1, float %a2) { ; CHECK-NEXT: define internal void @FcmpFloat(float %a1, float %a2) {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: %vfalse = fcmp false float %a1, %a2 ; CHECK-NEXT: %vfalse = fcmp false float %a1, %a2
; CHECK-NEXT: %voeq = fcmp oeq float %a1, %a2 ; CHECK-NEXT: %voeq = fcmp oeq float %a1, %a2
...@@ -385,10 +385,10 @@ entry: ...@@ -385,10 +385,10 @@ entry:
; CHECK-NEXT: %vune = fcmp une float %a1, %a2 ; CHECK-NEXT: %vune = fcmp une float %a1, %a2
; CHECK-NEXT: %vuno = fcmp uno float %a1, %a2 ; CHECK-NEXT: %vuno = fcmp uno float %a1, %a2
; CHECK-NEXT: %vtrue = fcmp true float %a1, %a2 ; CHECK-NEXT: %vtrue = fcmp true float %a1, %a2
; CHECK-NEXT: ret i1 %voeq ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
define internal i1 @FcmpDouble(double %a1, double %a2) { define internal void @FcmpDouble(double %a1, double %a2) {
entry: entry:
%vfalse = fcmp false double %a1, %a2 %vfalse = fcmp false double %a1, %a2
%voeq = fcmp oeq double %a1, %a2 %voeq = fcmp oeq double %a1, %a2
...@@ -406,10 +406,10 @@ entry: ...@@ -406,10 +406,10 @@ entry:
%vune = fcmp une double %a1, %a2 %vune = fcmp une double %a1, %a2
%vuno = fcmp uno double %a1, %a2 %vuno = fcmp uno double %a1, %a2
%vtrue = fcmp true double %a1, %a2 %vtrue = fcmp true double %a1, %a2
ret i1 %voeq ret void
} }
; CHECK-NEXT: define internal i1 @FcmpDouble(double %a1, double %a2) { ; CHECK-NEXT: define internal void @FcmpDouble(double %a1, double %a2) {
; CHECK-NEXT: entry: ; CHECK-NEXT: entry:
; CHECK-NEXT: %vfalse = fcmp false double %a1, %a2 ; CHECK-NEXT: %vfalse = fcmp false double %a1, %a2
; CHECK-NEXT: %voeq = fcmp oeq double %a1, %a2 ; CHECK-NEXT: %voeq = fcmp oeq double %a1, %a2
...@@ -427,7 +427,7 @@ entry: ...@@ -427,7 +427,7 @@ entry:
; CHECK-NEXT: %vune = fcmp une double %a1, %a2 ; CHECK-NEXT: %vune = fcmp une double %a1, %a2
; CHECK-NEXT: %vuno = fcmp uno double %a1, %a2 ; CHECK-NEXT: %vuno = fcmp uno double %a1, %a2
; CHECK-NEXT: %vtrue = fcmp true double %a1, %a2 ; CHECK-NEXT: %vtrue = fcmp true double %a1, %a2
; CHECK-NEXT: ret i1 %voeq ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
define internal <4 x i1> @FcmpV4xFloat(<4 x float> %a1, <4 x float> %a2) { define internal <4 x i1> @FcmpV4xFloat(<4 x float> %a1, <4 x float> %a2) {
......
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