From: Renato Golin Date: Thu, 5 Jun 2014 16:45:22 +0000 (+0000) Subject: Add pointer types to global named register X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6649699a62886e564642cf5cb0cd067a89f5ca42;p=clang Add pointer types to global named register This patch adds support for pointer types in global named registers variables. It'll be lowered as a pair of read/write_register and inttoptr/ptrtoint calls. Also adds some early checks on types on SemaDecl to avoid the assert. Tests changed accordingly. (PR19837) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210274 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a15a6e36dc..41c2100f79 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5924,6 +5924,7 @@ let CategoryName = "Inline Assembly Issue" in { "%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< diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index e77c4b048a..a43093e553 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1350,12 +1350,22 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) { /// @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 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src, /// @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); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9bd51b9f19..ed7431ae3e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5458,6 +5458,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // 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), diff --git a/test/CodeGen/named_reg_global.c b/test/CodeGen/named_reg_global.c index 53f304ddfb..6137177b6d 100644 --- a/test/CodeGen/named_reg_global.c +++ b/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 @@ void set_stack_pointer_addr(unsigned long addr) { } // 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"} diff --git a/test/Sema/asm.c b/test/Sema/asm.c index 4d84afce76..22b74974ce 100644 --- a/test/Sema/asm.c +++ b/test/Sema/asm.c @@ -1,5 +1,7 @@ // RUN: %clang_cc1 %s -Wno-private-extern -triple i386-pc-linux-gnu -verify -fsyntax-only + + void f() { int i; @@ -147,3 +149,11 @@ double test15() { __asm("0.0":"=g"(ret)); // no-error return ret; } + +// PR19837 +struct foo { + int a; + char b; +}; +register struct foo bar asm("sp"); // expected-error {{bad type for named register variable}} +register float baz asm("sp"); // expected-error {{bad type for named register variable}}