[MIPS] How can I add a constraint to LLVM/Clang for MIPS BE?

Hi all,

I find clang-mips doesn't support constraint 'R' and I'm trying make
LLVM/Clang support it.
I did a little job, but Clang can not generate right code, it use the
same register in inline asm,
and the binary will segment fault in MIPS environment.

My test case:
/* constraint.c */
#include <stdio.h>

int main(int argc, char* argv)
{
    int a = 4;
    int b = 10;
    int c = 0xffbbccdd;

    int *p = &a;
    int out = 0;

    __asm volatile (
        "lw %0, %1\n\t"
        : "=r"(out)
        : "R"(*p)
        );
    printf("out is %d\n", out);

    p = &b;
    __asm volatile (
        "lw %0, %1\n\t"
        : "=r"(out)
        : "R"(*p)
        );
    printf("out is %d\n", out);

    p = &c;
    __asm volatile (
        "lwl %0, 1 + %1\n\t"
        "lwr %0, 2 + %1\n\t"
        : "=r"(out)
        : "R"(*p)
        );
    printf("out is %x\n", out);

    return 0;
}

LLVM-MIPS-BE diff:
diff --git a/lib/Target/Mips/MipsISelLowering.cpp
b/lib/Target/Mips/MipsISelLowering.cpp
index 36e1a15..4a5d045 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -3880,6 +3880,8 @@ getConstraintType(const std::string &Constraint) const
       case 'l':
       case 'x':
         return C_RegisterClass;
+ case 'R':
+ return C_Memory;
     }
   }
   return TargetLowering::getConstraintType(Constraint);
@@ -3928,6 +3930,9 @@ MipsTargetLowering::getSingleConstraintMatchWeight(
     if (isa<ConstantInt>(CallOperandVal))
       weight = CW_Constant;
     break;
+ case 'R': // An address that can be used in a non-macro load or store
+ weight = CW_Memory;
+ break;
   }
   return weight;
}

Clang-diff:
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 70ea235..26fc663 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -462,6 +462,7 @@ bool
TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
     case 'N':
     case 'O':
     case 'P':
+ case 'R':
       break;
     case 'r': // general register.
       Info.setAllowsRegister();
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 24a69ee..854e12b 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -4393,6 +4393,9 @@ public:
     case 'x': // hilo register pair
       Info.setAllowsRegister();
       return true;
+ case 'R': // An address that can be used in a non-macro load or store
+ Info.setAllowsMemory();
+ return true;
     }
   }

Clang gen asm frag:
  #APP
  lw $2, 0($2)
  #NO_APP

  #APP
  lw $1, 0($1)
  #NO_APP

  #APP
  lwl $1, 1 + 0($1)
  lwr $1, 2 + 0($1)
  #NO_APP

gcc gen asm frag:
#APP
# 12 "constraints.c" 1
  lw $16, 0($2)
# 0 "" 2
#NO_APP

#APP
# 20 "constraints.c" 1
  lw $16, 0($2)
# 0 "" 2
#NO_APP

#APP
# 28 "constraints.c" 1
  lwl $16, 1 + 0($2)
  lwr $16, 2 + 0($2)
# 0 "" 2
#NO_APP

Clang use the same register in inline asm, gcc use different ones, and
gcc way is right, the clang generated code will segment fault on MIPS
environment.
Am I missed something or made something wrong?

Regards,
Jia

clang-mips-constraints.diff (801 Bytes)

constraints.c (601 Bytes)

constraints.clang.s (1.69 KB)

constraints.gcc.s (1.64 KB)

llvm-mips-constraints.diff (755 Bytes)