Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5911,6 +5911,7 @@ "%diff{$ matching output with type $|}0,1">; def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">; def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; + 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_invalid_asm_cast_lvalue : Error< Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -1350,12 +1350,22 @@ /// @brief Load of global gamed gegisters are always calls to intrinsics. RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) { - assert(LV.getType()->isIntegerType() && "Bad type for register variable"); + assert((LV.getType()->isIntegerType() || LV.getType()->isPointerType()) && + "Bad type for register variable"); llvm::MDNode *RegName = dyn_cast(LV.getGlobalReg()); assert(RegName && "Register LValue is not metadata"); - llvm::Type *Types[] = { CGM.getTypes().ConvertType(LV.getType()) }; + + // We accept integer and pointer types only + llvm::Type *OrigTy = CGM.getTypes().ConvertType(LV.getType()); + llvm::Type *Ty = OrigTy; + if (OrigTy->isPointerTy()) + Ty = CGM.getTypes().getDataLayout().getIntPtrType(OrigTy); + llvm::Type *Types[] = { Ty }; + llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types); - llvm::Value* Call = Builder.CreateCall(F, RegName); + llvm::Value *Call = Builder.CreateCall(F, RegName); + if (OrigTy->isPointerTy()) + Call = Builder.CreateIntToPtr(Call, OrigTy); return RValue::get(Call); } @@ -1601,12 +1611,22 @@ /// @brief Store of global named registers are always calls to intrinsics. void CodeGenFunction::EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst) { - assert(Dst.getType()->isIntegerType() && "Bad type for register variable"); + assert((Dst.getType()->isIntegerType() || Dst.getType()->isPointerType()) && + "Bad type for register variable"); llvm::MDNode *RegName = dyn_cast(Dst.getGlobalReg()); assert(RegName && "Register LValue is not metadata"); - llvm::Type *Types[] = { CGM.getTypes().ConvertType(Dst.getType()) }; + + // We accept integer and pointer types only + llvm::Type *OrigTy = CGM.getTypes().ConvertType(Dst.getType()); + llvm::Type *Ty = OrigTy; + if (OrigTy->isPointerTy()) + Ty = CGM.getTypes().getDataLayout().getIntPtrType(OrigTy); + llvm::Type *Types[] = { Ty }; + llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types); llvm::Value *Value = Src.getScalarVal(); + if (OrigTy->isPointerTy()) + Value = Builder.CreatePtrToInt(Value, Ty); Builder.CreateCall2(F, RegName, Value); } Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -5445,6 +5445,10 @@ // Global Named register if (!Context.getTargetInfo().isValidGCCRegisterName(Label)) Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; + if (!R->isIntegralType(Context) && !R->isPointerType()) { + Diag(D.getLocStart(), diag::err_asm_bad_register_type); + NewVD->setInvalidDecl(true); + } } NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Index: test/CodeGen/named_reg_global.c =================================================================== --- test/CodeGen/named_reg_global.c +++ test/CodeGen/named_reg_global.c @@ -4,6 +4,13 @@ // CHECK-NOT: @sp = common global register unsigned long current_stack_pointer asm("sp"); +struct p4_Thread { + struct { + int len; + } word; +}; +// Testing pointer types as well +register struct p4_Thread *p4TH asm("sp"); // CHECK: define{{.*}} i[[bits:[0-9]+]] @get_stack_pointer_addr() // CHECK: [[ret:%[0-9]+]] = call i[[bits]] @llvm.read_register.i[[bits]](metadata !0) @@ -22,5 +29,19 @@ } // CHECK: declare{{.*}} void @llvm.write_register.i[[bits]](metadata, i[[bits]]) +// CHECK: define {{.*}}@fn1 +int fn1() { + return (*p4TH).word.len; +} +// CHECK: %[[regr:[0-9]+]] = call i[[bits]] @llvm.read_register.i[[bits]](metadata !0) +// CHECK: inttoptr i[[bits]] %[[regr]] to %struct.p4_Thread* + +// CHECK: define {{.*}}@fn2 +void fn2(struct p4_Thread *val) { + p4TH = val; +} +// CHECK: %[[regw:[0-9]+]] = ptrtoint %struct.p4_Thread* %0 to i[[bits]] +// CHECK: call void @llvm.write_register.i[[bits]](metadata !0, i[[bits]] %[[regw]]) + // CHECK: !llvm.named.register.sp = !{!0} // CHECK: !0 = metadata !{metadata !"sp"}