[X86, inlineasm] Check that the output size is correct for the given constraint.

llvm-svn: 218064
This commit is contained in:
Akira Hatanaka 2014-09-18 18:17:18 +00:00
parent 3e6a0be4c4
commit 974131ea88
6 changed files with 60 additions and 5 deletions

View File

@ -6051,6 +6051,8 @@ let CategoryName = "Inline Assembly Issue" in {
def err_asm_bad_register_type : Error<"bad type for named register variable">;
def err_asm_invalid_input_size : Error<
"invalid input size for constraint '%0'">;
def err_asm_invalid_output_size : Error<
"invalid output size for constraint '%0'">;
def err_invalid_asm_cast_lvalue : Error<
"invalid use of a cast in a inline asm context requiring an l-value: "
"remove the cast or build with -fheinous-gnu-extensions">;

View File

@ -577,6 +577,12 @@ public:
bool validateInputConstraint(ConstraintInfo *OutputConstraints,
unsigned NumOutputs,
ConstraintInfo &info) const;
virtual bool validateOutputSize(StringRef /*Constraint*/,
unsigned /*Size*/) const {
return true;
}
virtual bool validateInputSize(StringRef /*Constraint*/,
unsigned /*Size*/) const {
return true;

View File

@ -1901,8 +1901,12 @@ public:
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
bool validateOutputSize(StringRef Constraint, unsigned Size) const override;
bool validateInputSize(StringRef Constraint, unsigned Size) const override;
virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const;
std::string convertConstraint(const char *&Constraint) const override;
const char *getClobbers() const override {
return "~{dirflag},~{fpsr},~{flags}";
@ -3053,8 +3057,24 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
}
}
bool X86TargetInfo::validateOutputSize(StringRef Constraint,
unsigned Size) const {
// Strip off constraint modifiers.
while (Constraint[0] == '=' ||
Constraint[0] == '+' ||
Constraint[0] == '&')
Constraint = Constraint.substr(1);
return validateOperandSize(Constraint, Size);
}
bool X86TargetInfo::validateInputSize(StringRef Constraint,
unsigned Size) const {
return validateOperandSize(Constraint, Size);
}
bool X86TargetInfo::validateOperandSize(StringRef Constraint,
unsigned Size) const {
switch (Constraint[0]) {
default: break;
case 'y':
@ -3124,8 +3144,8 @@ public:
if (RegNo == 1) return 2;
return -1;
}
bool validateInputSize(StringRef Constraint,
unsigned Size) const override {
bool validateOperandSize(StringRef Constraint,
unsigned Size) const override {
switch (Constraint[0]) {
default: break;
case 'R':
@ -3142,7 +3162,7 @@ public:
return Size <= 64;
}
return X86TargetInfo::validateInputSize(Constraint, Size);
return X86TargetInfo::validateOperandSize(Constraint, Size);
}
};
} // end anonymous namespace

View File

@ -121,6 +121,20 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return StmtError();
OutputConstraintInfos.push_back(Info);
const Type *Ty = OutputExpr->getType().getTypePtr();
// If this is a dependent type, just continue. We don't know the size of a
// dependent type.
if (Ty->isDependentType())
continue;
unsigned Size = Context.getTypeSize(Ty);
if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
Size))
return StmtError(Diag(OutputExpr->getLocStart(),
diag::err_asm_invalid_output_size)
<< Info.getConstraintStr());
}
SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;

View File

@ -5,8 +5,8 @@ vec256 foo(vec256 in) {
vec256 out;
asm("something %0" : : "y"(in)); // expected-error {{invalid input size for constraint 'y'}}
asm("something %0" : "=y"(out));
asm("something %0, %0" : "+y"(out));
asm("something %0" : "=y"(out)); // expected-error {{invalid output size for constraint '=y'}}
asm("something %0, %0" : "+y"(out)); // expected-error {{invalid output size for constraint '+y'}}
return out;
}

View File

@ -43,4 +43,17 @@ int func1() {
__asm__ volatile("foo1 %0" : : "f" (val256)); // expected-error {{invalid input size for constraint 'f'}}
__asm__ volatile("foo1 %0" : : "t" (val256)); // expected-error {{invalid input size for constraint 't'}}
__asm__ volatile("foo1 %0" : : "u" (val256)); // expected-error {{invalid input size for constraint 'u'}}
__asm__ volatile("foo1 %0" : "=R" (val)); // expected-error {{invalid output size for constraint '=R'}}
__asm__ volatile("foo1 %0" : "=q" (val)); // expected-error {{invalid output size for constraint '=q'}}
__asm__ volatile("foo1 %0" : "=Q" (val)); // expected-error {{invalid output size for constraint '=Q'}}
__asm__ volatile("foo1 %0" : "=a" (val)); // expected-error {{invalid output size for constraint '=a'}}
__asm__ volatile("foo1 %0" : "=b" (val)); // expected-error {{invalid output size for constraint '=b'}}
__asm__ volatile("foo1 %0" : "=c" (val)); // expected-error {{invalid output size for constraint '=c'}}
__asm__ volatile("foo1 %0" : "=d" (val)); // expected-error {{invalid output size for constraint '=d'}}
__asm__ volatile("foo1 %0" : "=S" (val)); // expected-error {{invalid output size for constraint '=S'}}
__asm__ volatile("foo1 %0" : "=D" (val)); // expected-error {{invalid output size for constraint '=D'}}
__asm__ volatile("foo1 %0" : "=A" (val128)); // expected-error {{invalid output size for constraint '=A'}}
__asm__ volatile("foo1 %0" : "=t" (val256)); // expected-error {{invalid output size for constraint '=t'}}
__asm__ volatile("foo1 %0" : "=u" (val256)); // expected-error {{invalid output size for constraint '=u'}}
}