mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-23 02:29:18 +00:00
[mips] Properly parse registers that appear in inline-asm constraints.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188336 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
eaa8f5533f
commit
bfb07b1054
@ -34,6 +34,7 @@
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cctype>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -2880,6 +2881,79 @@ MipsTargetLowering::getSingleConstraintMatchWeight(
|
||||
return weight;
|
||||
}
|
||||
|
||||
/// This is a helper function to parse a physical register string and split it
|
||||
/// into non-numeric and numeric parts (Prefix and Reg). The first boolean flag
|
||||
/// that is returned indicates whether parsing was successful. The second flag
|
||||
/// is true if the numeric part exists.
|
||||
static std::pair<bool, bool>
|
||||
parsePhysicalReg(const StringRef &C, std::string &Prefix,
|
||||
unsigned long long &Reg) {
|
||||
if (C.front() != '{' || C.back() != '}')
|
||||
return std::make_pair(false, false);
|
||||
|
||||
// Search for the first numeric character.
|
||||
StringRef::const_iterator I, B = C.begin() + 1, E = C.end() - 1;
|
||||
I = std::find_if(B, E, std::ptr_fun(isdigit));
|
||||
|
||||
Prefix.assign(B, I - B);
|
||||
|
||||
// The second flag is set to false if no numeric characters were found.
|
||||
if (I == E)
|
||||
return std::make_pair(true, false);
|
||||
|
||||
// Parse the numeric characters.
|
||||
return std::make_pair(!getAsUnsignedInteger(StringRef(I, E - I), 10, Reg),
|
||||
true);
|
||||
}
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass *> MipsTargetLowering::
|
||||
parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const {
|
||||
const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo();
|
||||
const TargetRegisterClass *RC;
|
||||
std::string Prefix;
|
||||
unsigned long long Reg;
|
||||
|
||||
std::pair<bool, bool> R = parsePhysicalReg(C, Prefix, Reg);
|
||||
|
||||
if (!R.first)
|
||||
return std::make_pair((unsigned)0, (const TargetRegisterClass*)0);
|
||||
|
||||
if ((Prefix == "hi" || Prefix == "lo")) { // Parse hi/lo.
|
||||
// No numeric characters follow "hi" or "lo".
|
||||
if (R.second)
|
||||
return std::make_pair((unsigned)0, (const TargetRegisterClass*)0);
|
||||
|
||||
RC = TRI->getRegClass(Prefix == "hi" ?
|
||||
Mips::HIRegsRegClassID : Mips::LORegsRegClassID);
|
||||
return std::make_pair(*(RC->begin()), RC);
|
||||
}
|
||||
|
||||
if (!R.second)
|
||||
return std::make_pair((unsigned)0, (const TargetRegisterClass*)0);
|
||||
|
||||
if (Prefix == "$f") { // Parse $f0-$f31.
|
||||
// If the size of FP registers is 64-bit or Reg is an even number, select
|
||||
// the 64-bit register class. Otherwise, select the 32-bit register class.
|
||||
if (VT == MVT::Other)
|
||||
VT = (Subtarget->isFP64bit() || !(Reg % 2)) ? MVT::f64 : MVT::f32;
|
||||
|
||||
RC= getRegClassFor(VT);
|
||||
|
||||
if (RC == &Mips::AFGR64RegClass) {
|
||||
assert(Reg % 2 == 0);
|
||||
Reg >>= 1;
|
||||
}
|
||||
} else if (Prefix == "$fcc") { // Parse $fcc0-$fcc7.
|
||||
RC = TRI->getRegClass(Mips::FCCRegClassID);
|
||||
} else { // Parse $0-$31.
|
||||
assert(Prefix == "$");
|
||||
RC = getRegClassFor((VT == MVT::Other) ? MVT::i32 : VT);
|
||||
}
|
||||
|
||||
assert(Reg < RC->getNumRegs());
|
||||
return std::make_pair(*(RC->begin() + Reg), RC);
|
||||
}
|
||||
|
||||
/// Given a register class constraint, like 'r', if this corresponds directly
|
||||
/// to an LLVM register class, return a register of 0 and the register class
|
||||
/// pointer.
|
||||
@ -2926,6 +3000,13 @@ getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const
|
||||
return std::make_pair(0u, static_cast<const TargetRegisterClass*>(0));
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass *> R;
|
||||
R = parseRegForInlineAsmConstraint(Constraint, VT);
|
||||
|
||||
if (R.second)
|
||||
return R;
|
||||
|
||||
return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
|
||||
}
|
||||
|
||||
|
@ -433,6 +433,11 @@ namespace llvm {
|
||||
ConstraintWeight getSingleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, const char *constraint) const;
|
||||
|
||||
/// This function parses registers that appear in inline-asm constraints.
|
||||
/// It returns pair (0, 0) on failure.
|
||||
std::pair<unsigned, const TargetRegisterClass *>
|
||||
parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const;
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass*>
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT VT) const;
|
||||
|
@ -51,3 +51,21 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check that RA doesn't allocate registers in the clobber list.
|
||||
; CHECK-LABEL: foo4:
|
||||
; CHECK: #APP
|
||||
; CHECK-NOT: ulh $2
|
||||
; CHECK: #NO_APP
|
||||
; CHECK: #APP
|
||||
; CHECK-NOT: $f0
|
||||
; CHECK: #NO_APP
|
||||
|
||||
define void @foo4() {
|
||||
entry:
|
||||
%0 = tail call i32 asm sideeffect "ulh $0,16($$sp)\0A\09", "=r,~{$2}"()
|
||||
store i32 %0, i32* @gi2, align 4
|
||||
%1 = load float* @gf0, align 4
|
||||
%2 = tail call double asm sideeffect "cvt.d.s $0, $1\0A\09", "=f,f,~{$f0}"(float %1)
|
||||
store double %2, double* @gd0, align 8
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user