Permalink
Browse files

Inline IL ASM prototype

  • Loading branch information...
xoofx committed May 24, 2016
1 parent 1b27908 commit d70bdaca3b23c79e4a45bf44afbab968c3d5398c
Showing with 868 additions and 87 deletions.
  1. +2 −76 README.md
  2. +223 −0 src/Compilers/CSharp/Portable/Binder/BinderILEmit.cs
  3. +11 −5 src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
  4. +303 −0 src/Compilers/CSharp/Portable/Binder/ILInstruction.cs
  5. +9 −0 src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs
  6. +5 −0 src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
  7. +15 −0 src/Compilers/CSharp/Portable/BoundTree/Expression.cs
  8. +4 −1 src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj
  9. +9 −0 src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
  10. +4 −1 src/Compilers/CSharp/Portable/CSharpResources.resx
  11. +33 −0 src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
  12. +154 −0 src/Compilers/CSharp/Portable/CodeGen/EmitILEmit.cs
  13. +2 −1 src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs
  14. +5 −0 src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
  15. +32 −0 src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs
  16. +13 −0 src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs
  17. +1 −0 src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs
  18. +3 −0 src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs
  19. +23 −2 src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs
  20. +9 −0 src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbol.cs
  21. +1 −0 src/Compilers/CSharp/Portable/Symbols/Symbol.cs
  22. +1 −0 src/Compilers/Core/Portable/PublicAPI.Shipped.txt
  23. +6 −1 src/Compilers/Core/Portable/Symbols/MethodKind.cs
@@ -1,77 +1,3 @@
## Welcome to the .NET Compiler Platform ("Roslyn")
## Welcome to the .NET Compiler Platform ("Roslyn") - xoofx playground

[//]: # (Begin current test results)

### Windows - Unit Tests
||Debug x86|Debug x64|Release x86|Release x64|Determinism|
|:--:|:--:|:--:|:--:|:--:|:--:|
|**master (1.3)**|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_debug_unit32/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_debug_unit32/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_debug_unit64/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_debug_unit64/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_release_unit32/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_release_unit64/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_release_unit64/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_release_unit64/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_determinism/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/windows_determinism/)|
|**future (2.0 Preview 2)**|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_debug_unit32/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_debug_unit32/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_debug_unit64/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_debug_unit64/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_release_unit32/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_release_unit64/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_release_unit64/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_release_unit64/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_determinism/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/windows_determinism/)|

### Linux/Mac - Unit Tests
||Linux|Mac OSX|
|:--:|:--:|:--:|
|**master (1.3)**|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/linux_debug/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/linux_debug/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/mac_debug/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/master/job/mac_debug/)|
|**future (2.0 Preview 2)**|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/linux_debug/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/linux_debug/)|[![Build Status](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/mac_debug/badge/icon)](http://dotnet-ci.cloudapp.net/job/dotnet_roslyn/job/future/job/mac_debug/)|

[//]: # (End current test results)

[![Join the chat at https://gitter.im/dotnet/roslyn](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dotnet/roslyn?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)


Roslyn provides open-source C# and Visual Basic compilers with rich code analysis APIs. It enables building code analysis tools with the same APIs that are used by Visual Studio.

### Download C# and Visual Basic

Want to start developing in C# and Visual Basic? Download [Visual Studio 2015](https://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs.aspx),
which has the latest features built-in. There are also [prebuilt Azure VM images](https://azure.microsoft.com/en-us/marketplace/virtual-machines/all/?term=Visual+Studio+2015) available with VS 2015 already installed.

To install the latest release without Visual Studio, run one of the following [nuget](https://dist.nuget.org/index.html) command lines:

```
nuget install Microsoft.Net.Compilers # Install C# and VB compilers
nuget install Microsoft.CodeAnalysis # Install Language APIs and Services
```

To get the latest "preview" drop, published about once per month, add the `-pre` switch to the nuget commands.

### Source code

* Clone the sources: `git clone https://github.com/dotnet/roslyn.git`
* [Enhanced source view](http://source.roslyn.io/), powered by Roslyn
* [Building, testing and debugging the sources](https://github.com/dotnet/roslyn/wiki/Building%20Testing%20and%20Debugging)

### Get started

* Tutorial articles by Alex Turner in MSDN Magazine
- [Use Roslyn to Write a Live Code Analyzer for Your API](https://msdn.microsoft.com/en-us/magazine/dn879356)
- [Adding a Code Fix to your Roslyn Analyzer](https://msdn.microsoft.com/en-us/magazine/dn904670.aspx)
* [Roslyn Overview](https://github.com/dotnet/roslyn/wiki/Roslyn%20Overview)
* [API Changes between CTP 6 and RC](https://github.com/dotnet/roslyn/wiki/VS-2015-RC-API-Changes)
* [Samples and Walkthroughs](https://github.com/dotnet/roslyn/wiki/Samples-and-Walkthroughs)
* [Documentation](https://github.com/dotnet/roslyn/tree/master/docs)
* [Analyzer documentation](https://github.com/dotnet/roslyn/tree/master/docs/analyzers)
* [Syntax Visualizer Tool](https://github.com/dotnet/roslyn/wiki/Syntax%20Visualizer)
* [Syntax Quoter Tool](http://roslynquoter.azurewebsites.net)
* [Roadmap](https://github.com/dotnet/roslyn/wiki/Roadmap)
* [Language Feature Status](https://github.com/dotnet/roslyn/wiki/Languages-features-in-C%23-6-and-VB-14)
* [Language Design Notes](https://github.com/dotnet/roslyn/issues?q=label%3A%22Design+Notes%22+)
* [FAQ](https://github.com/dotnet/roslyn/wiki/FAQ)
* Also take a look at our [Wiki](https://github.com/dotnet/roslyn/wiki) for more information on how to contribute, what the labels on issue mean, etc.

### Contribute!

Some of the best ways to contribute are to try things out, file bugs, and join in design conversations.

* [How to Contribute](https://github.com/dotnet/roslyn/wiki/Contributing-Code)
* [Pull requests](https://github.com/dotnet/roslyn/pulls): [Open](https://github.com/dotnet/roslyn/pulls?q=is%3Aopen+is%3Apr)/[Closed](https://github.com/dotnet/roslyn/pulls?q=is%3Apr+is%3Aclosed)

Looking for something to work on? The list of [up for grabs issues](https://github.com/dotnet/roslyn/issues?q=is%3Aopen+is%3Aissue+label%3A%22Up+for+Grabs%22) is a great place to start.

This project has adopted a code of conduct adapted from the [Contributor Covenant](http://contributor-covenant.org/) to clarify expected behavior in our community. This code of conduct has been [adopted by many other projects](http://contributor-covenant.org/adopters/). For more information see the [Code of conduct](http://www.dotnetfoundation.org/code-of-conduct).


### .NET Foundation

This project is part of the [.NET Foundation](http://www.dotnetfoundation.org/projects) along with other
projects like [the class libraries for .NET Core](https://github.com/dotnet/corefx/).
This is a fork of Roslyn to prototype inline IL ASM instruction directly from C#
@@ -0,0 +1,223 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.

using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Microsoft.CodeAnalysis.CSharp
{
internal partial class Binder
{
private bool TryCompilerIntrinsic(InvocationExpressionSyntax node, BoundExpression methodCall, DiagnosticBag diagnostics, out BoundExpression result)
{
result = null;
// We expect only a BoundCall
var call = methodCall as BoundMethodGroup;
if (call == null)
{
return false;
}

MethodSymbol method = null;

var generic = node.Expression as GenericNameSyntax;
if (generic != null && generic.TypeArgumentList.Arguments.Count != 1)
{
return false;
}

foreach (var checkMethod in call.Methods)
{
var sourceMethodSymbol = checkMethod as SourceMethodSymbol;
// Check that the method signature of the epecting method:
// [CompilerIntrinsic]
// extern void xxxx(string arg);
if (sourceMethodSymbol != null && sourceMethodSymbol.IsCompilerIntrinsic && (checkMethod.ReturnsVoid || (generic != null && checkMethod.TypeArguments.Length == 1 && checkMethod.ReturnType == checkMethod.TypeArguments[0])))
{
method = checkMethod;
break;
}
}

if (method == null)
{
return false;
}

if (node.ArgumentList.Arguments.Count < 1)
{
diagnostics.Add(ErrorCode.ERR_BadArgCount, node.Expression.Location);
return false;
}

var arg0 = node.ArgumentList.Arguments[0];
var ilName = arg0.ToString().TrimStart('@'); // remove @ for keyword arguments

// Get IL instruction
var inst = ILInstruction.Get(ilName);
if (inst == null)
{
diagnostics.Add(ErrorCode.ERR_ILInvalidInstruction, arg0.Location);
return false;
}

var expectedArgCount = inst.Argument == OpCodeArg.None ? 1 : 2;
// Add more checks
if (node.ArgumentList.Arguments.Count != expectedArgCount)
{
diagnostics.Add(ErrorCode.ERR_BadArgCount, node.Expression.Location);
return false;
}

BoundExpression bound = null;
// Check argument
if (inst.Argument != OpCodeArg.None)
{
var arg1 = node.ArgumentList.Arguments[1];

var errCode = ErrorCode.ERR_ArgsInvalid;

// Perform various checks here
switch (inst.Argument)
{
case OpCodeArg.Target32:
bound = this.BindLabel(arg1.Expression, diagnostics) as BoundLabel;
if (bound == null)
{
errCode = ErrorCode.ERR_LabelNotFound;
}
break;
case OpCodeArg.Target8:
bound = this.BindLabel(arg1.Expression, diagnostics) as BoundLabel;
if (bound == null)
{
errCode = ErrorCode.ERR_LabelNotFound;
}
break;
case OpCodeArg.Method:
case OpCodeArg.CallSite:
{
var methodBound = this.BindExpression(arg1.Expression, diagnostics);
if (methodBound == null || (!(methodBound is BoundCall) && !(methodBound is BoundMethodGroup)))
{
// TODO: log proper error
errCode = ErrorCode.ERR_MethodNameExpected;
}
else
{
bound = methodBound;
}
break;
}

case OpCodeArg.ElementType:
case OpCodeArg.TypeToken:
case OpCodeArg.Class:
bound = this.BindExpression(arg1.Expression, diagnostics) as BoundTypeExpression;
if (bound == null)
{
errCode = ErrorCode.ERR_TypeExpected;
}
break;

case OpCodeArg.Field:
bound = BindExpression(arg1.Expression, diagnostics) as BoundFieldAccess;
if (bound == null)
{
// TODO: log proper error
errCode = ErrorCode.ERR_BadAccess;
}
break;
case OpCodeArg.String:
bound = BindExpression(arg1.Expression, diagnostics) as BoundLiteral;
if (bound == null || !bound.ConstantValue.IsString)
{
// TODO: log proper error
bound = null;
errCode = ErrorCode.ERR_ExpectedVerbatimLiteral;
}
break;
case OpCodeArg.Token:
var tokenExpression = BindExpression(arg1.Expression, diagnostics);

if (tokenExpression is BoundTypeExpression || tokenExpression is BoundFieldAccess || tokenExpression is BoundCall || (tokenExpression is BoundMethodGroup && ((BoundMethodGroup)tokenExpression).Methods.Length == 1))
{
bound = tokenExpression;
}
else
{
// TODO: log proper error
errCode = ErrorCode.ERR_ArgsInvalid;
}
break;
case OpCodeArg.Constructor:
bound = BindExpression(arg1.Expression, diagnostics) as BoundObjectCreationExpression;
if (bound == null)
{
// TODO: log proper error
errCode = ErrorCode.ERR_ArgsInvalid;
}
break;
case OpCodeArg.ArgumentVar:
bound = BindExpression(arg1.Expression, diagnostics) as BoundParameter;
if (bound == null)
{
// TODO: log proper error
errCode = ErrorCode.ERR_ArgsInvalid;
}
break;
case OpCodeArg.LocalVar:
bound = BindExpression(arg1.Expression, diagnostics) as BoundLocal;
if (bound == null)
{
// TODO: log proper error
errCode = ErrorCode.ERR_ArgsInvalid;
}
break;
case OpCodeArg.Int8:
case OpCodeArg.UInt8:
case OpCodeArg.UInt16:
case OpCodeArg.Int32:
case OpCodeArg.UInt32:
case OpCodeArg.Int64:
case OpCodeArg.UInt64:
case OpCodeArg.Float32:
case OpCodeArg.Float64:
// TODO: Handle correctly arguments
bound = BindExpression(arg1.Expression, diagnostics) as BoundLiteral;
if (bound == null || (!bound.ConstantValue.IsNumeric && !bound.ConstantValue.IsFloating))
{
// TODO: log proper error
bound = null;
errCode = ErrorCode.ERR_ArgsInvalid;
}
break;
}

// If we have not been able to bind anything, we have an error
if (bound == null)
{
diagnostics.Add(errCode, arg1.Location);
return false;
}
}
// Emit BoundILEmit here
TypeSymbol emitType = Compilation.GetSpecialType(SpecialType.System_Void);
var genericType = generic != null ? generic.TypeArgumentList.Arguments[0] : null;

if (genericType != null)
{
emitType = BindType(genericType, diagnostics);
}

result = new BoundILEmit(call.Syntax, emitType)
{
ILInstruction = inst,
Bound = bound
};
return true;
}
}
}
@@ -151,18 +151,24 @@ private static ImmutableArray<MethodSymbol> GetOriginalMethods(OverloadResolutio
// M(__arglist()) is legal, but M(__arglist(__arglist()) is not!
bool isArglist = node.Expression.Kind() == SyntaxKind.ArgListExpression;
AnalyzedArguments analyzedArguments = AnalyzedArguments.GetInstance();
BindArgumentsAndNames(node.ArgumentList, diagnostics, analyzedArguments, allowArglist: !isArglist);

if (isArglist)
{
BindArgumentsAndNames(node.ArgumentList, diagnostics, analyzedArguments);
result = BindArgListOperator(node, diagnostics, analyzedArguments);
}
else
{
BoundExpression boundExpression = BindMethodGroup(node.Expression, invoked: true, indexed: false, diagnostics: diagnostics);
boundExpression = CheckValue(boundExpression, BindValueKind.RValueOrMethodGroup, diagnostics);
string name = boundExpression.Kind == BoundKind.MethodGroup ? GetName(node.Expression) : null;
result = BindInvocationExpression(node, node.Expression, name, boundExpression, analyzedArguments, diagnostics);
var boundExpression = BindMethodGroup(node.Expression, invoked: true, indexed: false, diagnostics: diagnostics);

// Try to replace compiler intrinsic on BoundCall
if (!TryCompilerIntrinsic(node, boundExpression, diagnostics, out result))
{
BindArgumentsAndNames(node.ArgumentList, diagnostics, analyzedArguments, true);
boundExpression = CheckValue(boundExpression, BindValueKind.RValueOrMethodGroup, diagnostics);
string name = boundExpression.Kind == BoundKind.MethodGroup ? GetName(node.Expression) : null;
result = BindInvocationExpression(node, node.Expression, name, boundExpression, analyzedArguments, diagnostics);
}
}

analyzedArguments.Free();
Oops, something went wrong.

0 comments on commit d70bdac

Please sign in to comment.