aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2015-08-21 15:52:18 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-08-21 15:52:18 +0000
commit52fbb92e8cedd6fc31eea1d547a33445cdd69c3e (patch)
tree6514ffe65c8f1dac5ba197e299efa383565e2588
parent676f304e57bb71773117c1b7183d30516450e701 (diff)
parent8f341123970bcc4bc28e7f2c9434e72f1d0b0f76 (diff)
downloadclang-52fbb92e8cedd6fc31eea1d547a33445cdd69c3e.tar.gz
am 8f341123: Merge "RenderScript: ensure that struct arguments and return values are always coerced to a type of the same size as the original type."
* commit '8f341123970bcc4bc28e7f2c9434e72f1d0b0f76': RenderScript: ensure that struct arguments and return values are always coerced to a type of the same size as the original type.
-rw-r--r--lib/CodeGen/TargetInfo.cpp38
1 files changed, 38 insertions, 0 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index d6f009e9d9..0f01620cbb 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -30,6 +30,31 @@
using namespace clang;
using namespace CodeGen;
+// Helper for coercing an aggregate argument or return value into an
+// integer array of the same size (including padding).
+//
+// This is needed for RenderScript on ARM targets. The RenderScript
+// compiler assumes that the size of the argument / return value in
+// the IR is the same as the size of the corresponding qualified
+// type. It is necessary to coerce the aggregate type into an
+// array. We cannot pass a struct directly as an argument because
+// clang's struct passing logic breaks up the struct into its
+// constitutent fields.
+//
+// Ty - The argument / return value type
+// Context - The associated ASTContext
+// LLVMContext - The associated LLVMContext
+static ABIArgInfo coerceToIntArray(QualType Ty,
+ ASTContext &Context,
+ llvm::LLVMContext &LLVMContext) {
+ // Alignment and Size are measured in bits.
+ const uint64_t Size = Context.getTypeSize(Ty);
+ const uint64_t Alignment = Context.getTypeAlign(Ty);
+ llvm::Type *IntType = llvm::Type::getIntNTy(LLVMContext, Alignment);
+ const uint64_t NumElements = (Size + Alignment - 1) / Alignment;
+ return ABIArgInfo::getDirect(llvm::ArrayType::get(IntType, NumElements));
+}
+
static void AssignToArrayRange(CodeGen::CGBuilderTy &Builder,
llvm::Value *Array,
llvm::Value *Value,
@@ -4044,6 +4069,9 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
// Aggregates <= 16 bytes are passed directly in registers or on the stack.
uint64_t Size = getContext().getTypeSize(Ty);
if (Size <= 128) {
+ if (getContext().getLangOpts().Renderscript) {
+ return coerceToIntArray(Ty, getContext(), getVMContext());
+ }
unsigned Alignment = getContext().getTypeAlign(Ty);
Size = 64 * ((Size + 63) / 64); // round up to multiple of 8 bytes
@@ -4089,6 +4117,9 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
// Aggregates <= 16 bytes are returned directly in registers or on the stack.
uint64_t Size = getContext().getTypeSize(RetTy);
if (Size <= 128) {
+ if (getContext().getLangOpts().Renderscript) {
+ return coerceToIntArray(RetTy, getContext(), getVMContext());
+ }
unsigned Alignment = getContext().getTypeAlign(RetTy);
Size = 64 * ((Size + 63) / 64); // round up to multiple of 8 bytes
@@ -4743,6 +4774,10 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
/*Realign=*/TyAlign > ABIAlign);
}
+ if (getContext().getLangOpts().Renderscript) {
+ return coerceToIntArray(Ty, getContext(), getVMContext());
+ }
+
// Otherwise, pass by coercing to a structure of the appropriate size.
llvm::Type* ElemTy;
unsigned SizeRegs;
@@ -4913,6 +4948,9 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
// are returned indirectly.
uint64_t Size = getContext().getTypeSize(RetTy);
if (Size <= 32) {
+ if (getContext().getLangOpts().Renderscript) {
+ return coerceToIntArray(RetTy, getContext(), getVMContext());
+ }
if (getDataLayout().isBigEndian())
// Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4)
return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));