Support initialization of constant array exports.
BUG=5901034
Change-Id: Ibdc74323080518223bbf79caef0c91030c501f17
diff --git a/slang_rs_export_var.cpp b/slang_rs_export_var.cpp
index e5b4b3a..56e256f 100644
--- a/slang_rs_export_var.cpp
+++ b/slang_rs_export_var.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,19 +20,33 @@
#include "llvm/ADT/APSInt.h"
-#include "slang_assert.h"
#include "slang_rs_context.h"
#include "slang_rs_export_type.h"
namespace slang {
+namespace {
+
+static clang::DiagnosticBuilder ReportVarError(RSContext *Context,
+ const clang::SourceLocation Loc,
+ const char *Message) {
+ clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
+ const clang::SourceManager *SM = Context->getSourceManager();
+ return DiagEngine->Report(clang::FullSourceLoc(Loc, *SM),
+ DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message));
+}
+
+} // namespace
+
RSExportVar::RSExportVar(RSContext *Context,
const clang::VarDecl *VD,
const RSExportType *ET)
: RSExportable(Context, RSExportable::EX_VAR),
mName(VD->getName().data(), VD->getName().size()),
mET(ET),
- mIsConst(false) {
+ mIsConst(false),
+ mArraySize(0),
+ mNumInits(0) {
// mInit - Evaluate initializer expression
const clang::Expr *Initializer = VD->getAnyInitializer();
if (Initializer != NULL) {
@@ -43,22 +57,47 @@
break;
}
case RSExportType::ExportClassPointer: {
- if (Initializer->isNullPointerConstant
- (Context->getASTContext(),
- clang::Expr::NPC_ValueDependentIsNotNull)
- )
+ if (Initializer->isNullPointerConstant(Context->getASTContext(),
+ clang::Expr::NPC_ValueDependentIsNotNull)) {
mInit.Val = clang::APValue(llvm::APSInt(1));
- else
- Initializer->EvaluateAsRValue(mInit, Context->getASTContext());
+ } else {
+ if (!Initializer->EvaluateAsRValue(mInit, Context->getASTContext())) {
+ ReportVarError(Context, Initializer->getExprLoc(),
+ "initializer is not an R-value");
+ }
+ }
break;
}
+ case RSExportType::ExportClassConstantArray: {
+ const clang::InitListExpr *IList =
+ static_cast<const clang::InitListExpr*>(Initializer);
+ if (!IList) {
+ ReportVarError(Context, VD->getLocation(),
+ "Unable to find initializer list");
+ break;
+ }
+ const RSExportConstantArrayType *ECAT =
+ static_cast<const RSExportConstantArrayType*>(ET);
+ mArraySize = ECAT->getSize();
+ mNumInits = IList->getNumInits();
+ for (unsigned int i = 0; i < mNumInits; i++) {
+ clang::Expr::EvalResult tempInit;
+ if (!IList->getInit(i)->EvaluateAsRValue(tempInit,
+ Context->getASTContext())) {
+ ReportVarError(Context, IList->getInit(i)->getExprLoc(),
+ "initializer is not an R-value");
+ }
+ mInitArray.push_back(tempInit);
+ }
+ break;
+ }
+ case RSExportType::ExportClassMatrix:
case RSExportType::ExportClassRecord: {
- // No action
- fprintf(stderr, "RSExportVar::RSExportVar : Reflection of initializer "
- "to variable '%s' (of type '%s') is unsupported "
- "currently.\n",
- mName.c_str(),
- ET->getName().c_str());
+ ReportVarError(Context, VD->getLocation(),
+ "Reflection of initializer to variable '%0' (of type "
+ "'%1') is unsupported currently.")
+ << mName
+ << ET->getName();
break;
}
default: {
diff --git a/slang_rs_export_var.h b/slang_rs_export_var.h
index 61d997a..221551f 100644
--- a/slang_rs_export_var.h
+++ b/slang_rs_export_var.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
#include "llvm/ADT/StringRef.h"
+#include "slang_assert.h"
#include "slang_rs_exportable.h"
namespace clang {
@@ -43,6 +44,10 @@
clang::Expr::EvalResult mInit;
+ size_t mArraySize;
+ size_t mNumInits;
+ llvm::SmallVector<clang::Expr::EvalResult, 0> mInitArray;
+
RSExportVar(RSContext *Context,
const clang::VarDecl *VD,
const RSExportType *ET);
@@ -53,6 +58,13 @@
inline bool isConst() const { return mIsConst; }
inline const clang::APValue &getInit() const { return mInit.Val; }
+
+ inline size_t getArraySize() const { return mArraySize; }
+ inline size_t getNumInits() const { return mNumInits; }
+ inline const clang::APValue &getInitArray(unsigned int i) const {
+ slangAssert(i < mNumInits);
+ return mInitArray[i].Val;
+ }
}; // RSExportVar
} // namespace slang
diff --git a/slang_rs_reflection.cpp b/slang_rs_reflection.cpp
index df0906e..a6f897a 100644
--- a/slang_rs_reflection.cpp
+++ b/slang_rs_reflection.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2011, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
#include <cctype>
#include <algorithm>
+#include <sstream>
#include <string>
#include <utility>
@@ -319,7 +320,7 @@
return NULL;
}
-static std::string GetTypeName(const RSExportType *ET) {
+static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) {
switch (ET->getClass()) {
case RSExportType::ExportClassPrimitive: {
return GetPrimitiveTypeName(
@@ -344,7 +345,9 @@
const RSExportConstantArrayType* CAT =
static_cast<const RSExportConstantArrayType*>(ET);
std::string ElementTypeName = GetTypeName(CAT->getElementType());
- ElementTypeName.append("[]");
+ if (Brackets) {
+ ElementTypeName.append("[]");
+ }
return ElementTypeName;
}
case RSExportType::ExportClassRecord: {
@@ -667,8 +670,23 @@
I != E;
I++) {
const RSExportVar *EV = *I;
- if (!EV->getInit().isUninit())
+ if (!EV->getInit().isUninit()) {
genInitExportVariable(C, EV->getType(), EV->getName(), EV->getInit());
+ } else if (EV->getArraySize()) {
+ // Always create an initial zero-init array object.
+ C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = new "
+ << GetTypeName(EV->getType(), false) << "["
+ << EV->getArraySize() << "];" << std::endl;
+ size_t NumInits = EV->getNumInits();
+ const RSExportConstantArrayType *ECAT =
+ static_cast<const RSExportConstantArrayType*>(EV->getType());
+ const RSExportType *ET = ECAT->getElementType();
+ for (size_t i = 0; i < NumInits; i++) {
+ std::stringstream Name;
+ Name << EV->getName() << "[" << i << "]";
+ genInitExportVariable(C, ET, Name.str(), EV->getInitArray(i));
+ }
+ }
}
for (RSContext::const_export_foreach_iterator
diff --git a/tests/F_global_init/global_init.rs b/tests/F_global_init/global_init.rs
new file mode 100644
index 0000000..8d35184
--- /dev/null
+++ b/tests/F_global_init/global_init.rs
@@ -0,0 +1,20 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+int ia[4] = {0, 1};
+int i = 2;
+int2 i2 = {3, 4};
+float fa[4] = {0.0, 1.0, 2.9999};
+char ca[2] = {'a', 7};
+bool ba[2] = {false, true};
+
+const int ic = 99;
+
+int ica[2] = {ic, 1000};
+
+struct s {
+ int i;
+};
+
+struct s myS = {9};
+
diff --git a/tests/F_global_init/stderr.txt.expect b/tests/F_global_init/stderr.txt.expect
new file mode 100644
index 0000000..19360f4
--- /dev/null
+++ b/tests/F_global_init/stderr.txt.expect
@@ -0,0 +1 @@
+global_init.rs:19:10: error: Reflection of initializer to variable 'myS' (of type 's') is unsupported currently.
diff --git a/tests/F_global_init/stdout.txt.expect b/tests/F_global_init/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_global_init/stdout.txt.expect
diff --git a/tests/P_array_init/array_init.rs b/tests/P_array_init/array_init.rs
new file mode 100644
index 0000000..b64e6ea
--- /dev/null
+++ b/tests/P_array_init/array_init.rs
@@ -0,0 +1,16 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+const int ic = 99;
+
+int ica[2] = {ic, 1000};
+
+float fa[4] = {1.0, 9.9999f};
+double da[2] = {7.0, 8.88888};
+char ca[4] = {'a', 7, 'b', 'c'};
+short sa[4] = {1, 1, 2, 3};
+int ia[4] = {5, 8};
+long la[2] = {13, 21};
+long long lla[4] = {34};
+bool ba[3] = {true, false};
+
diff --git a/tests/P_array_init/stderr.txt.expect b/tests/P_array_init/stderr.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_array_init/stderr.txt.expect
diff --git a/tests/P_array_init/stdout.txt.expect b/tests/P_array_init/stdout.txt.expect
new file mode 100644
index 0000000..e306a86
--- /dev/null
+++ b/tests/P_array_init/stdout.txt.expect
@@ -0,0 +1 @@
+Generating ScriptC_array_init.java ...