Skip to content

Commit

Permalink
Work on pointers. Fix a bug. Add a optimizations.
Browse files Browse the repository at this point in the history
  • Loading branch information
VladD2 committed Aug 23, 2012
1 parent 8d5983e commit 930184e
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 59 deletions.
95 changes: 51 additions & 44 deletions ncc/generation/ILEmitter.n
Expand Up @@ -516,8 +516,8 @@ namespace Nemerle.Compiler
log (EMIT, $"{ emit: $expr"); log (EMIT, $"{ emit: $expr");
Util.cassert (expr != null); Util.cassert (expr != null);
Util.locate (expr.Location, Util.locate (expr.Location,
match (expr) { match (expr)

{
/* -- SEQUENCING --------------------------------------------------- */ /* -- SEQUENCING --------------------------------------------------- */


/* emits a sequence of expressions */ /* emits a sequence of expressions */
Expand Down Expand Up @@ -979,11 +979,7 @@ namespace Nemerle.Compiler


emit_tuple_function_conversion (expr.FixedType(), t, field); emit_tuple_function_conversion (expr.FixedType(), t, field);


| PointerIndexer(ptr, index) => | PointerIndexer(ptr, index) => emit_ptr_indexing(expr.NeedAddress, ptr, index);
//assert2(false);
emit(ptr);
emit_ptr_indexing(ptr.Type, index);

// load an array element // load an array element
| ArrayIndexer (array_obj, [index]) => | ArrayIndexer (array_obj, [index]) =>
emit_exprs ([array_obj, index]); emit_exprs ([array_obj, index]);
Expand Down Expand Up @@ -2265,31 +2261,45 @@ namespace Nemerle.Compiler
| _ => assert(false); | _ => assert(false);
} }


private emit_ptr_indexing(type : TypeVar, index : TExpr) : void private emit_ptr_indexing(needAddress : bool, ptr : TExpr, index : TExpr) : void
{ {
def type = ptr.Type;

assert(type.IsPointer); assert(type.IsPointer);

emit(ptr);
emit(index);


def size = get_elem_size(type); def size = get_elem_size(type);


_ilg.Emit(OpCodes.Conv_I); match (index)

{
emit_index_multiplier(size); | TExpr.Literal(Literal.Integer(0, _, _)) => ()
| TExpr.Literal(Literal.Integer(val, is_negative, _treat_as)) =>
def byteOffset = (size / 8) * (val :> int) * if (is_negative) -1 else 1;

_ilg.Emit(OpCodes.Conv_I);
emit_i4(byteOffset);
_ilg.Emit(OpCodes.Add);

| _ =>
emit(index);
_ilg.Emit(OpCodes.Conv_I);
emit_index_multiplier(size);


when (size > 8) when (size > 8)
_ilg.Emit(OpCodes.Mul); _ilg.Emit(OpCodes.Mul);


_ilg.Emit(OpCodes.Add); _ilg.Emit(OpCodes.Add);

}
match (size)
{ unless (needAddress)
| 8 => _ilg.Emit(OpCodes.Ldind_U1); match (size)
| 16 => _ilg.Emit(OpCodes.Ldind_U2); {
| 32 => _ilg.Emit(OpCodes.Ldind_U4); | 8 => _ilg.Emit(OpCodes.Ldind_U1);
| 64 => _ilg.Emit(OpCodes.Ldind_I8); | 16 => _ilg.Emit(OpCodes.Ldind_U2);
| _ => assert(false); | 32 => _ilg.Emit(OpCodes.Ldind_U4);
} | 64 => _ilg.Emit(OpCodes.Ldind_I8);
| _ => assert(false);
}
} }


/** /**
Expand Down Expand Up @@ -2356,28 +2366,25 @@ namespace Nemerle.Compiler
} }
} }


emit_i4(x : int) : void
{
| -1 => _ilg.Emit (OpCodes.Ldc_I4_M1)
| 0 => _ilg.Emit (OpCodes.Ldc_I4_0)
| 1 => _ilg.Emit (OpCodes.Ldc_I4_1)
| 2 => _ilg.Emit (OpCodes.Ldc_I4_2)
| 3 => _ilg.Emit (OpCodes.Ldc_I4_3)
| 4 => _ilg.Emit (OpCodes.Ldc_I4_4)
| 5 => _ilg.Emit (OpCodes.Ldc_I4_5)
| 6 => _ilg.Emit (OpCodes.Ldc_I4_6)
| 7 => _ilg.Emit (OpCodes.Ldc_I4_7)
| 8 => _ilg.Emit (OpCodes.Ldc_I4_8)
| k when (k >= -128 && k <= 127) => _ilg.Emit (OpCodes.Ldc_I4_S, k :> sbyte)
| k => _ilg.Emit (OpCodes.Ldc_I4, k)
}


/** /// Emits a literal
* Emits a literal
*/
private emit_literal (l : Literal) : void private emit_literal (l : Literal) : void
{ {
def emit_i4 (x) {
| -1 => _ilg.Emit (OpCodes.Ldc_I4_M1)
| 0 => _ilg.Emit (OpCodes.Ldc_I4_0)
| 1 => _ilg.Emit (OpCodes.Ldc_I4_1)
| 2 => _ilg.Emit (OpCodes.Ldc_I4_2)
| 3 => _ilg.Emit (OpCodes.Ldc_I4_3)
| 4 => _ilg.Emit (OpCodes.Ldc_I4_4)
| 5 => _ilg.Emit (OpCodes.Ldc_I4_5)
| 6 => _ilg.Emit (OpCodes.Ldc_I4_6)
| 7 => _ilg.Emit (OpCodes.Ldc_I4_7)
| 8 => _ilg.Emit (OpCodes.Ldc_I4_8)
| k when (k >= -128 && k <= 127) =>
_ilg.Emit (OpCodes.Ldc_I4_S, k :> sbyte)
| k => _ilg.Emit (OpCodes.Ldc_I4, k)
}

match (l) { match (l) {
| Literal.Void => () | Literal.Void => ()
| Literal.Null => _ilg.Emit (OpCodes.Ldnull) | Literal.Null => _ilg.Emit (OpCodes.Ldnull)
Expand Down
57 changes: 50 additions & 7 deletions ncc/testsuite/positive/Issue-git-0397.n
Expand Up @@ -9,21 +9,23 @@ using Nemerle.Unsafe;


module Program module Program
{ {
mutable i = 0;

ary = array[42, 2, 3];
str = "abc";
mutable _ptr : char*;

Test1() : void Test1() : void
{ {
pinned (p1 = str) pinned (p1 = str)
{ {
WriteLine(p1[1].ToString());
WriteLine((p1[3] : int).ToString());
WriteLine(p1[0]); WriteLine(p1[0]);
UnsafeMethod(p1); UnsafeMethod(p1);
} }
} }


mutable i = 0;

ary = array[42, 2, 3];
str = "abc";
mutable _ptr : char*;

TupleTest1(_tup : int * string) : void TupleTest1(_tup : int * string) : void
{ {
} }
Expand Down Expand Up @@ -71,15 +73,44 @@ module Program
} }
} }


Test3(ptrIn : int*) : void
{
WriteLine("Test3()");
WriteLine(*ptrIn);
mutable ptr = ptrIn;
ptr += 10000;
WriteLine(ptr[-10000]);
ptr = ptrIn + 100;
WriteLine(ptr[-100]);
ptr = ptrIn + 3;
WriteLine(ptr[-2]);
ptr = ptrIn + 3;
WriteLine(ptr[-1]);
ptr = ptrIn;
WriteLine(ptr[1 - 1]);
WriteLine(ptr[0]);
WriteLine(ptr[1]);
WriteLine(ptr[2]);
ptr = ptrIn + -6;
WriteLine(ptr[8]);
ptr = ptrIn + -10000;
WriteLine(ptr[10000]);
}


Main() : void Main() : void
{ {
Test1(); Test1();
Test2(); Test2();
pinned (p = ary)
Test3(p);
} }
} }


/* /*
BEGIN-OUTPUT BEGIN-OUTPUT
b
0
a a
a a
b b
Expand All @@ -95,5 +126,17 @@ c
end for end for
42 42
3 3
Test3()
42
42
42
2
3
42
42
2
3
3
42
END-OUTPUT END-OUTPUT
*/ */
1 change: 0 additions & 1 deletion snippets/Nemerle.Unsafe/Nemerle.Unsafe/PinnedMacro.n
Expand Up @@ -81,7 +81,6 @@ namespace Nemerle.Unsafe


| _ => Message.FatalError(args.Location, "Expected 'name = expr'."); | _ => Message.FatalError(args.Location, "Expected 'name = expr'.");
} }
// TODO: Add implementation here.
} }
} }
} }
43 changes: 36 additions & 7 deletions snippets/Nemerle.Unsafe/Test/Main.n
Expand Up @@ -8,21 +8,23 @@ using Nemerle.Unsafe;


module Program module Program
{ {
mutable i = 0;

ary = array[42, 2, 3];
str = "abc";
mutable _ptr : char*;

Test1() : void Test1() : void
{ {
pinned (p1 = str) pinned (p1 = str)
{ {
WriteLine(p1[3].ToString());
WriteLine((p1[3] : int).ToString());
WriteLine(p1[0]); WriteLine(p1[0]);
UnsafeMethod(p1); UnsafeMethod(p1);
} }
} }


mutable i = 0;

ary = array[42, 2, 3];
str = "abc";
mutable _ptr : char*;

TupleTest1(_tup : int * string) : void TupleTest1(_tup : int * string) : void
{ {
} }
Expand Down Expand Up @@ -70,9 +72,36 @@ module Program
} }
} }


Test3(ptrIn : int*) : void
{
WriteLine("Test3()");
WriteLine(*ptrIn);
mutable ptr = ptrIn;
ptr += 10000;
WriteLine(ptr[-10000]);
ptr = ptrIn + 100;
WriteLine(ptr[-100]);
ptr = ptrIn + 3;
WriteLine(ptr[-2]);
ptr = ptrIn + 3;
WriteLine(ptr[-1]);
ptr = ptrIn;
WriteLine(ptr[1 - 1]);
WriteLine(ptr[0]);
WriteLine(ptr[1]);
WriteLine(ptr[2]);
ptr = ptrIn + -6;
WriteLine(ptr[8]);
ptr = ptrIn + -10000;
WriteLine(ptr[10000]);
}


Main() : void Main() : void
{ {
Test1(); Test1();
Test2(); Test2();
pinned (p = ary)
Test3(p);
} }
} }
16 changes: 16 additions & 0 deletions snippets/Nemerle.Unsafe/UnsafeTest/Program.cs
Expand Up @@ -14,8 +14,24 @@ unsafe class Program
static int[] ary = new int[] { 1, 2, 3 }; static int[] ary = new int[] { 1, 2, 3 };
//static int[] ary = new int[0]; //static int[] ary = new int[0];


byte Test3(byte* ptr)
{
return ptr[-3];
}

static void Test4(char* ptr)
{
var c = ptr[3];
Console.WriteLine(c.ToString());
}

static void Main(string[] args) static void Main(string[] args)
{ {
fixed (char* p = "abc")
Test4(p);

return;

var x = 1; var x = 1;
//typeof(int).MakePointerType() //typeof(int).MakePointerType()
//Console.WriteLine(ary[x]); //Console.WriteLine(ary[x]);
Expand Down

0 comments on commit 930184e

Please sign in to comment.