r210274 - Add pointer types to global named register
Renato Golin
renato.golin at linaro.org
Thu Jun 5 09:45:22 PDT 2014
Author: rengolin
Date: Thu Jun 5 11:45:22 2014
New Revision: 210274
URL: http://llvm.org/viewvc/llvm-project?rev=210274&view=rev
Log:
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)
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/CodeGen/named_reg_global.c
cfe/trunk/test/Sema/asm.c
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=210274&r1=210273&r2=210274&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jun 5 11:45:22 2014
@@ -5924,6 +5924,7 @@ let CategoryName = "Inline Assembly Issu
"%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<
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=210274&r1=210273&r2=210274&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Jun 5 11:45:22 2014
@@ -1350,12 +1350,22 @@ RValue CodeGenFunction::EmitLoadOfExtVec
/// @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<llvm::MDNode>(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::EmitStoreThroughEx
/// @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<llvm::MDNode>(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);
}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=210274&r1=210273&r2=210274&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jun 5 11:45:22 2014
@@ -5458,6 +5458,10 @@ Sema::ActOnVariableDeclarator(Scope *S,
// 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),
Modified: cfe/trunk/test/CodeGen/named_reg_global.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/named_reg_global.c?rev=210274&r1=210273&r2=210274&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/named_reg_global.c (original)
+++ cfe/trunk/test/CodeGen/named_reg_global.c Thu Jun 5 11:45:22 2014
@@ -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 lon
}
// 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"}
Modified: cfe/trunk/test/Sema/asm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/asm.c?rev=210274&r1=210273&r2=210274&view=diff
==============================================================================
--- cfe/trunk/test/Sema/asm.c (original)
+++ cfe/trunk/test/Sema/asm.c Thu Jun 5 11:45:22 2014
@@ -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}}
More information about the cfe-commits
mailing list