/// @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);
}
/// @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);
}
// 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)
}
// 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"}