Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion compiler/backends/JIT_x64.pas
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ TJitEmitter = record
procedure MOVZX_Reg_Mem_i16(Reg: EReg; BaseReg: EReg; Offset: Int64);
procedure MOV_Reg_Mem_i32(Reg: EReg; BaseReg: EReg; Offset: Int64);
procedure MOV_Reg_Mem_i64(Reg: EReg; BaseReg: EReg; Offset: Int64);
procedure MOVSXD_Reg_Mem_i32(Reg: EReg; BaseReg: EReg; Offset: Int64);
procedure MOV_Mem_Reg_i8(BaseReg: EReg; Offset: Int64; Reg: EReg);
procedure MOV_Mem_Reg_i16(BaseReg: EReg; Offset: Int64; Reg: EReg);
procedure MOV_Mem_Reg_i32(BaseReg: EReg; Offset: Int64; Reg: EReg);
Expand Down Expand Up @@ -533,6 +534,13 @@ procedure TJitEmitter.MOV_Reg_Mem_i64(Reg: EReg; BaseReg: EReg; Offset: Int64);
WriteBytes(@Offset, 4);
end;

procedure TJitEmitter.MOVSXD_Reg_Mem_i32(Reg: EReg; BaseReg: EReg; Offset: Int64);
begin
// MOVSXD r64, r/m32 — opcode: 48 63 /r (REX.W + 63)
WriteBytes([$48, $63, $80 + (Ord(Reg) * 8) + Ord(BaseReg)]);
WriteBytes(@Offset, 4);
end;

procedure TJitEmitter.MOV_Mem_Reg_i8(BaseReg: EReg; Offset: Int64; Reg: EReg);
begin
WriteBytes([$88, $80 + (Ord(Reg) * 8) + Ord(BaseReg)]);
Expand Down Expand Up @@ -977,7 +985,7 @@ procedure TJitEmitter.Load_Int_Operand(const arg: TOperand; Reg: EReg);
case BaseJITType(arg.BaseType) of
xtInt8: MOVZX_Reg_Mem_i8(Reg, rbx, arg.Data.Addr);
xtInt16: MOVZX_Reg_Mem_i16(Reg, rbx, arg.Data.Addr);
xtInt32: MOV_Reg_Mem_i32(Reg, rbx, arg.Data.Addr);
xtInt32: MOVSXD_Reg_Mem_i32(Reg, rbx, arg.Data.Addr);
xtInt64: MOV_Reg_Mem_i64(Reg, rbx, arg.Data.Addr);
end
else
Expand Down
4 changes: 2 additions & 2 deletions compiler/includes/interpreter.jitcode.inc
Original file line number Diff line number Diff line change
Expand Up @@ -739,13 +739,13 @@ begin
while i <= BC.Code.High do
begin
// Check if current opcode is eligible for fusion
if CanJITSuper(BC.Code.Data[i]) and (BC.Settings.Data[i].JIT in [1,3]) then
if CanJITSuper(BC.Code.Data[i]) and (BC.Settings.Data[i].JIT in [1,{$IFNDEF CPUX86_64}2,{$ENDIF}3]) then
begin
n := i;

// Find how many eligible opcodes follow
while (i <= BC.Code.High) and CanJITSuper(BC.Code.Data[i]) and
(BC.Settings.Data[i].JIT in [1,3]) do
(BC.Settings.Data[i].JIT in [1,{$IFNDEF CPUX86_64}2,{$ENDIF}3]) do
Inc(i);

// control flow, so what comes before is likely cmp operation
Expand Down
51 changes: 38 additions & 13 deletions compiler/xpr.compilercontext.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1698,26 +1698,51 @@ function TCompilerContext.GenerateIntrinsics(Name: string; Arguments: array of X
Result := nil;
TTypeIntrinsics(TypeIntrinsics).FContext := Self;
case Lowercase(Name) of
'_refcnt': Result := (TypeIntrinsics as TTypeIntrinsics).GenerateRefcount(SelfType, Arguments);
'high' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateHigh(SelfType, Arguments);
'len' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateLen(SelfType, Arguments);
'setlen' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateSetLen(SelfType, Arguments);
'collect': Result := (TypeIntrinsics as TTypeIntrinsics).GenerateCollect(SelfType, Arguments);
'tostr' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateToStr(SelfType, Arguments);
'default': Result := (TypeIntrinsics as TTypeIntrinsics).GenerateDefault(SelfType, Arguments);

'__passign__' : Result := (TypeIntrinsics as TTypeIntrinsics).GeneratePtrAssign(SelfType, Arguments, CompileAs);
'__pdispose__': Result := (TypeIntrinsics as TTypeIntrinsics).GeneratePtrDispose(SelfType, Arguments, CompileAs);
// Core
'_refcnt' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateRefcount(SelfType, Arguments);
'high' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateHigh(SelfType, Arguments);
'len' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateLen(SelfType, Arguments);
'setlen' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateSetLen(SelfType, Arguments);
'collect' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateCollect(SelfType, Arguments);
'tostr' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateToStr(SelfType, Arguments);
'default' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateDefault(SelfType, Arguments);
'__passign__' : Result := (TypeIntrinsics as TTypeIntrinsics).GeneratePtrAssign(SelfType, Arguments, CompileAs);
'__pdispose__' : Result := (TypeIntrinsics as TTypeIntrinsics).GeneratePtrDispose(SelfType, Arguments, CompileAs);
'__eq__' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateEq(SelfType, Arguments);
'__neq__' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateNeq(SelfType, Arguments);

// Tier 1
'push' : Result := (TypeIntrinsics as TTypeIntrinsics).GeneratePush(SelfType, Arguments);
'pop' : Result := (TypeIntrinsics as TTypeIntrinsics).GeneratePop(SelfType, Arguments);
'slice' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateSlice(SelfType, Arguments);
'copy' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateCopy(SelfType, Arguments);
'contains' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateContains(SelfType, Arguments);
'indexof' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateIndexOf(SelfType, Arguments);
'delete' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateDelete(SelfType, Arguments);
'insert' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateInsert(SelfType, Arguments);
'remove' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateRemove(SelfType, Arguments);
// Tier 2
'reverse' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateReverse(SelfType, Arguments);
'sort' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateSort(SelfType, Arguments);
'concat' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateConcat(SelfType, Arguments);
// Tier 3 — numeric
'sum' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateSum(SelfType, Arguments);
'min' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateMin(SelfType, Arguments);
'max' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateMax(SelfType, Arguments);
'mean' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateMean(SelfType, Arguments);
'variance' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateVariance(SelfType, Arguments);
'stddev' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateStdDev(SelfType, Arguments);
'median' : Result := (TypeIntrinsics as TTypeIntrinsics).GenerateMedian(SelfType, Arguments);
end;

if (Result <> nil) then
begin
CURRENT_SCOPE := Result.FContext.Scope;
Result.FContext.Scope:=GLOBAL_SCOPE;
CURRENT_SCOPE := Result.FContext.Scope;
Result.FContext.Scope := GLOBAL_SCOPE;
Self.DelayedNodes += Result;
Result.Compile(NullResVar, []);
XTree_Function(Result).PreCompiled := True;
Result.FContext.Scope:=CURRENT_SCOPE;
Result.FContext.Scope := CURRENT_SCOPE;
end;
end;

Expand Down
34 changes: 25 additions & 9 deletions compiler/xpr.parser.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1475,11 +1475,11 @@ function TParser.ParseTypeDecl(): XTree_Node;
Consume(tkEQ, PostInc);

if Current.Token = tkKW_CLASS then
Result := ParseClassDecl(Name, declIndent)
Result := ParseClassDecl(Name, myIndent)
else
begin
SetInsesitive();
Typ := ParseAddType('', True, False, declIndent);
Typ := ParseAddType('', True, False, myIndent);
ResetInsesitive();
Result := XTree_TypeDecl.Create(Name, Typ, FContext, DocPos);
end;
Expand Down Expand Up @@ -1762,8 +1762,19 @@ function TParser.RHSExpr(Left: XTree_Node; leftPrecedence: Int8=0): XTree_Node;

if AsOperator(op.Token) = op_Invoke then
begin
Result := XTree_Invoke.Create(
Left, ParseExpressionList(True, True), FContext, Left.FDocPos);
if Left is XTree_Field then
begin
// a.Method() or a.Len().ToStr() - extract SelfExpr from the field node
// so the object side goes through PushArgsToStack's temp-spill path
Result := XTree_Invoke.Create(
XTree_Field(Left).Right, // method name identifier
ParseExpressionList(True, True), FContext, Left.FDocPos);
XTree_Invoke(Result).SelfExpr := XTree_Field(Left).Left; // the object
end
else
Result := XTree_Invoke.Create(
Left, ParseExpressionList(True, True), FContext, Left.FDocPos);

Consume(tkRPARENTHESES);
if NextIf(tkCOLON) then
begin
Expand All @@ -1778,11 +1789,16 @@ function TParser.RHSExpr(Left: XTree_Node; leftPrecedence: Int8=0): XTree_Node;
Right := ParsePrimary();
if Right = nil then FContext.RaiseException(eInvalidExpression, DocPos);

nextPrecedence := OperatorPrecedence();
if precedence < nextPrecedence then
Right := RHSExpr(Right, precedence + 1)
else if precedence = nextPrecedence then
Right := RHSExpr(Right, precedence + OperatorAssoc());
// Dot operator never recurses right - each segment is just one identifier.
// The outer loop handles a.B().C() by converting Field+Invoke repeatedly.
if AsOperator(op.Token) <> op_Dot then
begin
nextPrecedence := OperatorPrecedence();
if precedence < nextPrecedence then
Right := RHSExpr(Right, precedence + 1)
else if precedence = nextPrecedence then
Right := RHSExpr(Right, precedence + OperatorAssoc());
end;

Left := Merge(AsOperator(op.Token), Left, Right);
end;
Expand Down
5 changes: 1 addition & 4 deletions compiler/xpr.tokenizer.pas
Original file line number Diff line number Diff line change
Expand Up @@ -497,10 +497,7 @@ procedure TTokenizer.AddString();
Inc(pos);
while (Current <> data[i]) and (Current <> #0) do Next_CheckNewline;
str := Copy(data, i+1, pos-i-1);
if Length(str) <= 1 then
Self.Append(tkCHAR, str)
else
Self.Append(tkSTRING, str);
Self.Append(tkSTRING, str);
Inc(pos);
end;

Expand Down
Loading
Loading