summaryrefslogtreecommitdiff
path: root/BCT/BytecodeTranslator/WholeProgram.cs
diff options
context:
space:
mode:
authorGravatar Unknown <mbarnett@MIKE-SONY.redmond.corp.microsoft.com>2012-08-23 13:21:43 -0700
committerGravatar Unknown <mbarnett@MIKE-SONY.redmond.corp.microsoft.com>2012-08-23 13:21:43 -0700
commitc487dc14521f9ed8065d08961c9d1aa9eaf27daa (patch)
tree17fe46ef8901e6a355493b760159f517b19b9446 /BCT/BytecodeTranslator/WholeProgram.cs
parentb09fa6df2177538ce43e7606a3f5520acd81c256 (diff)
Fix the whole-program translator so that exception handling is done
correctly for virtual method calls. Changed the whole-program override for VisitMethodCall so that it creates a new CodeModel expression that does not contain virtual method calls and then translate that newly built expression. Treat type equality (and inequality) specially: translate it directly to a type test instead. But do it just for the idiom: "o.GetType == typeof(T)". In that case, turn it into "is#T$T($DynamicType(o))".
Diffstat (limited to 'BCT/BytecodeTranslator/WholeProgram.cs')
-rw-r--r--BCT/BytecodeTranslator/WholeProgram.cs149
1 files changed, 84 insertions, 65 deletions
diff --git a/BCT/BytecodeTranslator/WholeProgram.cs b/BCT/BytecodeTranslator/WholeProgram.cs
index 3570cdd4..783a2b1a 100644
--- a/BCT/BytecodeTranslator/WholeProgram.cs
+++ b/BCT/BytecodeTranslator/WholeProgram.cs
@@ -149,81 +149,100 @@ namespace BytecodeTranslator {
return;
}
- Bpl.IToken token = methodCall.Token();
-
- List<Bpl.Expr> inexpr;
- List<Bpl.IdentifierExpr> outvars;
- Bpl.IdentifierExpr thisExpr;
- Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> toBoxed;
- var proc = TranslateArgumentsAndReturnProcedure(token, methodCall.MethodToCall, resolvedMethod, methodCall.IsStaticCall ? null : methodCall.ThisArgument, methodCall.Arguments, out inexpr, out outvars, out thisExpr, out toBoxed);
-
-
- Bpl.QKeyValue attrib = null;
- foreach (var a in resolvedMethod.Attributes) {
- if (TypeHelper.GetTypeName(a.Type).EndsWith("AsyncAttribute")) {
- attrib = new Bpl.QKeyValue(token, "async", new List<object>(), null);
- break;
- }
- }
-
- var elseBranch = new Bpl.StmtListBuilder();
-
- var methodname = proc.Name;
-
- Bpl.CallCmd call;
- if (attrib != null)
- call = new Bpl.CallCmd(token, methodname, inexpr, outvars, attrib);
- else
- call = new Bpl.CallCmd(token, methodname, inexpr, outvars);
- elseBranch.Add(call);
+ Contract.Assume(1 <= overrides.Count);
- Bpl.IfCmd ifcmd = null;
+ var getType = new Microsoft.Cci.MethodReference(
+ this.sink.host,
+ this.sink.host.PlatformType.SystemObject,
+ CallingConvention.HasThis,
+ this.sink.host.PlatformType.SystemType,
+ this.sink.host.NameTable.GetNameFor("GetType"), 0);
+ var op_Type_Equality = new Microsoft.Cci.MethodReference(
+ this.sink.host,
+ this.sink.host.PlatformType.SystemType,
+ CallingConvention.Default,
+ this.sink.host.PlatformType.SystemBoolean,
+ this.sink.host.NameTable.GetNameFor("op_Equality"),
+ 0,
+ this.sink.host.PlatformType.SystemType,
+ this.sink.host.PlatformType.SystemType);
+
+ // Depending on whether the method is a void method or not
+ // Turn into expression:
+ // (o.GetType() == typeof(T1)) ? ((T1)o).M(...) : ( (o.GetType() == typeof(T2)) ? ((T2)o).M(...) : ...
+ // Or turn into statements:
+ // if (o.GetType() == typeof(T1)) ((T1)o).M(...) else if ...
+ var turnIntoStatements = resolvedMethod.Type.TypeCode == PrimitiveTypeCode.Void;
+ IStatement elseStatement = null;
+
+ IExpression elseValue = new MethodCall() {
+ Arguments = new List<IExpression>(methodCall.Arguments),
+ IsStaticCall = false,
+ IsVirtualCall = false,
+ MethodToCall = methodCall.MethodToCall,
+ ThisArgument = methodCall.ThisArgument,
+ Type = methodCall.Type,
+ };
+ if (turnIntoStatements)
+ elseStatement = new ExpressionStatement() { Expression = elseValue, };
+
+ Conditional ifConditional = null;
+ ConditionalStatement ifStatement = null;
- Contract.Assume(1 <= overrides.Count);
foreach (var typeMethodPair in overrides) {
var t = typeMethodPair.Item1;
var m = typeMethodPair.Item2;
- // guard: is#T($DynamicType(local_variable))
- var typeFunction = this.sink.FindOrDefineType(t.ResolvedType);
- if (typeFunction == null) {
- // BUGBUG!! This just silently skips the branch that would dispatch to t's implementation of the method!
- continue;
+ var cond = new MethodCall() {
+ Arguments = new List<IExpression>(){
+ new MethodCall() {
+ Arguments = new List<IExpression>(),
+ IsStaticCall = false,
+ IsVirtualCall = false,
+ MethodToCall = getType,
+ ThisArgument = methodCall.ThisArgument,
+ },
+ new TypeOf() {
+ TypeToGet = t,
+ },
+ },
+ IsStaticCall = true,
+ IsVirtualCall = false,
+ MethodToCall = op_Type_Equality,
+ Type = this.sink.host.PlatformType.SystemBoolean,
+ };
+ var thenValue = new MethodCall() {
+ Arguments = new List<IExpression>(methodCall.Arguments),
+ IsStaticCall = false,
+ IsVirtualCall = false,
+ MethodToCall = m,
+ ThisArgument = methodCall.ThisArgument,
+ Type = t,
+ };
+ if (turnIntoStatements) {
+ ifStatement = new ConditionalStatement() {
+ Condition = cond,
+ FalseBranch = elseStatement,
+ TrueBranch = new ExpressionStatement() { Expression = thenValue, },
+ };
+ elseStatement = ifStatement;
+ } else {
+ ifConditional = new Conditional() {
+ Condition = cond,
+ ResultIfFalse = elseValue,
+ ResultIfTrue = thenValue,
+ };
+ elseValue = ifConditional;
}
- var funcName = String.Format("is#{0}", typeFunction.Name);
- var identExpr = Bpl.Expr.Ident(new Bpl.LocalVariable(token, new Bpl.TypedIdent(token, funcName, Bpl.Type.Bool)));
- var funcCall = new Bpl.FunctionCall(identExpr);
- var exprs = new Bpl.ExprSeq(this.sink.Heap.DynamicType(inexpr[0]));
- var guard = new Bpl.NAryExpr(token, funcCall, exprs);
-
- var thenBranch = new Bpl.StmtListBuilder();
- methodname = TranslationHelper.CreateUniqueMethodName(m); // REVIEW: Shouldn't this be call to FindOrCreateProcedure?
- if (attrib != null)
- call = new Bpl.CallCmd(token, methodname, inexpr, outvars, attrib);
- else
- call = new Bpl.CallCmd(token, methodname, inexpr, outvars);
- thenBranch.Add(call);
-
- ifcmd = new Bpl.IfCmd(token,
- guard,
- thenBranch.Collect(token),
- null,
- elseBranch.Collect(token)
- );
- elseBranch = new Bpl.StmtListBuilder();
- elseBranch.Add(ifcmd);
}
-
- if (ifcmd == null) {
- // BUGBUG: then no override made it into the if-statement.
- // currently that happens when all types are generic.
- // Should be able to remove this when that is fixed.
- base.Traverse(methodCall);
- return;
+ if (turnIntoStatements) {
+ Contract.Assume(ifStatement != null);
+ this.StmtTraverser.Traverse(ifStatement);
+ } else {
+ Contract.Assume(ifConditional != null);
+ base.Traverse(ifConditional);
}
- this.StmtTraverser.StmtBuilder.Add(ifcmd);
-
return;
}