Index: lib/Basic/Targets/ARM.h =================================================================== --- lib/Basic/Targets/ARM.h +++ lib/Basic/Targets/ARM.h @@ -150,6 +150,22 @@ ArrayRef getGCCRegNames() const override; ArrayRef getGCCRegAliases() const override; + bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize, + bool &HasSizeMismatch) const override { + if (RegName.equals("r4") || + RegName.equals("r5") || + RegName.equals("r6") || + RegName.equals("r7") || + RegName.equals("r8") || + RegName.equals("r9") || + RegName.equals("r10") || + RegName.equals("r11") || + RegName.equals("sp")) { + HasSizeMismatch = false; + return true; + } + return false; + } bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override; std::string convertConstraint(const char *&Constraint) const override; Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -2238,6 +2238,17 @@ } else { const auto *VD = cast(Global); assert(VD->isFileVarDecl() && "Cannot emit local var decl as global."); + + // reserve Global Named registers access via module flags + if(VD->getStorageClass() == SC_Register && + !VD->isLocalVarDecl() && + VD->hasAttr()){ + AsmLabelAttr *Asm = VD->getAttr(); + llvm::MDString *Val = llvm::MDString::get(getLLVMContext(), Asm->getLabel()); + std::string Name = "fixed_reg." + VD->getName().str(); + getModule().addModuleFlag(llvm::Module::Error, Name, Val); + } + // We need to emit device-side global CUDA variables even if a // variable does not have a definition -- we still need to define // host-side shadow for it. Index: test/CodeGen/named_reg_global.c =================================================================== --- test/CodeGen/named_reg_global.c +++ test/CodeGen/named_reg_global.c @@ -23,16 +23,16 @@ #endif // CHECK: define{{.*}} i[[bits:[0-9]+]] @get_stack_pointer_addr() -// CHECK: [[ret:%[0-9]+]] = call i[[bits]] @llvm.read_register.i[[bits]](metadata !0) +// CHECK: [[ret:%[0-9]+]] = call i[[bits]] @llvm.read_register.i[[bits]](metadata !{{.*}}) // CHECK: ret i[[bits]] [[ret]] unsigned long get_stack_pointer_addr() { return current_stack_pointer; } // CHECK: declare{{.*}} i[[bits]] @llvm.read_register.i[[bits]](metadata) -// CHECK: define{{.*}} void @set_stack_pointer_addr(i[[bits]] %addr) #0 { +// CHECK: define{{.*}} void @set_stack_pointer_addr(i[[bits]] %addr) #{{.*}} { // CHECK: [[sto:%[0-9]+]] = load i[[bits]], i[[bits]]* % -// CHECK: call void @llvm.write_register.i[[bits]](metadata !0, i[[bits]] [[sto]]) +// CHECK: call void @llvm.write_register.i[[bits]](metadata !{{.*}}, i[[bits]] [[sto]]) // CHECK: ret void void set_stack_pointer_addr(unsigned long addr) { current_stack_pointer = addr; @@ -43,7 +43,7 @@ int fn1() { return (*p4TH).word.len; } -// CHECK: %[[regr:[0-9]+]] = call i[[bits]] @llvm.read_register.i[[bits]](metadata !0) +// CHECK: %[[regr:[0-9]+]] = call i[[bits]] @llvm.read_register.i[[bits]](metadata !{{.*}}) // CHECK: inttoptr i[[bits]] %[[regr]] to %struct.p4_Thread* // CHECK: define {{.*}}@fn2 @@ -51,9 +51,14 @@ p4TH = val; } // CHECK: %[[regw:[0-9]+]] = ptrtoint %struct.p4_Thread* %{{.*}} to i[[bits]] -// CHECK: call void @llvm.write_register.i[[bits]](metadata !0, i[[bits]] %[[regw]]) +// CHECK: call void @llvm.write_register.i[[bits]](metadata !{{.*}}, i[[bits]] %[[regw]]) -// CHECK-X86-64: !llvm.named.register.rsp = !{!0} -// CHECK-X86-64: !0 = !{!"rsp"} -// CHECK-ARM: !llvm.named.register.sp = !{!0} -// CHECK-ARM: !0 = !{!"sp"} +// CHECK-X86-64: !llvm.named.register.rsp = !{!{{.*}}} +// CHECK-X86-64: !{{.*}} = !{i32 1, !"fixed_reg.current_stack_pointer", !"rsp"} +// CHECK-X86-64: !{{.*}} = !{i32 1, !"fixed_reg.p4TH", !"rsp"} +// CHECK-X86-64: !{{.*}} = !{!"rsp"} + +// CHECK-ARM: !llvm.named.register.sp = !{!{{.*}}} +// CHECK-ARM: !{{.*}} = !{i32 1, !"fixed_reg.current_stack_pointer", !"sp"} +// CHECK-ARM: !{{.*}} = !{i32 1, !"fixed_reg.p4TH", !"sp"} +// CHECK-ARM: !{{.*}} = !{!"sp"}