summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main
diff options
context:
space:
mode:
authorRichard Lin2018-03-23 13:17:40 -0700
committerGitHub2018-03-23 13:17:40 -0700
commita86e38889302662db14b932e4e0d862290c01308 (patch)
tree9358bb719c7331b5e9a8bd4ec85b423a8f976b59 /chiselFrontend/src/main
parentf3a39aff35879f1959786b1178ec2ffe96164a35 (diff)
Fallback null insertion for autoclonetype (#801)
If autoclonetype is unable to determine an outer class, this attempts to insert a null (and give a deprecation warning), preserving old behavior (in some cases) where the new behavior doesn't work. This doesn't provide full compatibility with old autoclonetype: this does not attempt null insertion in the general first argument (if it's not an outer class reference). Reasoning is that inserting a null for an explicit argument is probably not the right thing to do, and will likely cause a difficult-to-debug NullPointerException (whereas that would be unlikely for an outer class, which is not always referenced in Bundle subclass code).
Diffstat (limited to 'chiselFrontend/src/main')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala24
1 files changed, 19 insertions, 5 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
index f0c23e52..18ab8dc2 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
@@ -589,6 +589,10 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
case (outerClass, _) => Some(outerClass)
}
+ // For compatibility with pre-3.1, where null is tried as an argument to the constructor.
+ // This stores potential error messages which may be used later.
+ var outerClassError: Option[String] = None
+
// Check if this is an inner class, and if so, try to get the outer instance
val outerClassInstance = enclosingClassOption.map { outerClass =>
def canAssignOuterClass(x: Object) = outerClass.isAssignableFrom(x.getClass)
@@ -612,10 +616,14 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
case outer :: Nil =>
_outerInst = Some(outer) // record the guess for future use
outer
- case Nil => autoClonetypeError(s"Unable to determine instance of outer class $outerClass," +
- s" no candidates assignable to outer class types; examined $allOuterCandidates")
- case candidates => autoClonetypeError(s"Unable to determine instance of outer class $outerClass," +
- s" multiple possible candidates $candidates assignable to outer class type")
+ case Nil => // TODO: replace with fatal autoClonetypeError once compatibility period is dropped
+ outerClassError = Some(s"Unable to determine instance of outer class $outerClass," +
+ s" no candidates assignable to outer class types; examined $allOuterCandidates")
+ null
+ case candidates => // TODO: replace with fatal autoClonetypeError once compatibility period is dropped
+ outerClassError = Some(s"Unable to determine instance of outer class $outerClass," +
+ s" multiple possible candidates $candidates assignable to outer class type")
+ null
}
}
}
@@ -635,7 +643,12 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
case (Nil, None) => // no arguments, no outer class, invoke constructor directly
Some(ctor.newInstance().asInstanceOf[this.type])
case (argType :: Nil, Some((_, outerInstance))) =>
- if (argType isAssignableFrom outerInstance.getClass) {
+ if (outerInstance == null) {
+ Builder.deprecated(s"chisel3.1 autoclonetype failed, falling back to 3.0 behavior using null as the outer instance." +
+ s" Autoclonetype failure reason: ${outerClassError.get}",
+ Some(s"$clazz"))
+ Some(ctor.newInstance(outerInstance).asInstanceOf[this.type])
+ } else if (argType isAssignableFrom outerInstance.getClass) {
Some(ctor.newInstance(outerInstance).asInstanceOf[this.type])
} else {
None
@@ -738,6 +751,7 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
// Invoke ctor
val classMirror = outerClassInstance match {
+ case Some((_, null)) => autoClonetypeError(outerClassError.get) // deals with the null hack for 3.0 compatibility
case Some((_, outerInstance)) => mirror.reflect(outerInstance).reflectClass(classSymbol)
case _ => mirror.reflectClass(classSymbol)
}