Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Compiler/Delphi/Code Generation/Optimization    [ Add a report in this area ]  
Report #:  9283   Status: Open
Make BASM Functions Inlineable
Project:  Delphi Build #:  99
Version:    7.0 Submitted By:   Dennis Christensen
Report Type:  New Feature Request Date Reported:  10/8/2004 12:56:39 AM
Severity:    Infrequently encountered problem Last Updated: 3/20/2012 2:24:39 AM
Platform:    All platforms Internal Tracking #:   220062
Resolution: None (Resolution Comments) Resolved in Build: : None
Duplicate of:  None
Voting and Rating
Overall Rating: (20 Total Ratings)
4.85 out of 5
Total Votes: 76
Description
I would like to be able to inline BASM functions.

Regards
Dennis
Steps to Reproduce:
Pierre le Riche adds...

If basm inlining is done, provide a mechanism for telling the compiler about registers the programmer is preserving.

function AddOne(ANumber: integer): integer; inline; preserves(ecx, edx);
asm
  inc eax
end;

This way you can tell the compiler that it need not worry about
pushing/popping ecx and edx around the inlined code. It would be impossible
for the compiler to be able to determine which of the volatile registers
(eax, edx, ecx) are modified and which not in BASM code, and without this
information it  would have to assume that all three are modified and that
would
increase  stack traffic (possibly killing the advantage gained from
inlining).

An example:

procedure MyProc(ANumber: integer);
asm
  cmp eax, 10
  jne @Done
  push offset ADifferentProcedure
@Done:
end;

Which registers are preserved here? ;-)

Perhaps the asm keyword itself should be expanded, e.g.:

function MyProc(AFunnyNumber: integer): integer;
begin
  AFunnyNumber := AFunnyNumber + 12345;
  asm preserves ecx, edx
    mov eax, AFunnyNumber
    bsf eax, eax
    mov AFunnyNumber, eax
  end;
  if AFunnyNumber > 10 then
    Result := 1
  else
    Result := 10;
end;

A totally contrived example, but it should illustrate the point.

Other candidates:
asm(eax, ecx) //eax and ecx are modified
...
end;

asm uses eax, edx
...
end;

asm edx, ecx  //edx and ecx are not changed
...
end;

Workarounds
None
Attachment
None
Comments

Will DeWitt Jr. at 12/16/2004 10:10:01 AM -
Dennis, minor suggestion-- can you update the Version and Build No. fields (Version should be set to "2005" and Build No. should be set to 9.0.1761.24408).

Otherwise, I hope this gets implemented, it'd be really nice.  =)

Pierre le Riche at 6/24/2005 8:12:59 AM -
Perhaps something along the line of:

function AddOne(ANumber: integer): integer; inline; preserves(ecx, edx);
asm
  inc eax
end;

This way you can tell the compiler that it need not worry about pushing/popping ecx and edx around the inlined code. It would be impossible for the compiler to be able to determine which of the volatile registers (eax, edx, ecx) are modified and which not in BASM code, and it is critical for it to know this to be able to effect any speed improvement from inlining BASM code.

An example:

procedure MyProc(ANumber: integer);
asm
  cmp eax, 10
  jne @Done
  push offset ADifferentProcedure
@Done:
end;

Which registers are preserved here? ;-)

Will DeWitt Jr. at 6/25/2005 10:42:13 AM -
That would be a nice optimization, but, unless it was relatively easy for Borland to implement, I still think most people who use BASM would settle for just getting rid of the CALL/RET cost.

Igor Funa at 8/23/2007 11:56:09 PM -
I agree: there should be a possibility to inline asm procedures.
However there are at least two issues to be solved:
1. Loading of parameters to registers
2. Declaring preserved registers

1. Loading of parameters to registers
Of course, when the procedure gets expanded you don't know
where the parameter that is passed to procedure is stored.
Maybe there could be some solution with some "macro" instruction like

Procedure TestProc (Par1: Longword; Var Par2: LongWord);
asm
  MOV  EAX, PARAMETER Par1 { loads value of Par1 }
  MOV  EDX, PARAMETER Par2 { loads address of Par2 }
.......
end;

When expanding the compiler should generate proper code to load parameter to the register. Sometimes this might be complicated since inside expanded code it should not use additional registers.

2. Solutions to this issue are already proposed above.

In general, there SHOULD BE a way to inline asm procedures.
At least a limited one. In worst case you could write code knowing that this procedure will ALWAYS be inlined, e.g. if
there is an asm procedure with inline directive it SHOULD be ALWAYS inlined. In this case there should be some rules where the parameters will be stored and this rules would be used when writing inlined asm procedure.
Maybe a limitation on number/type of parameters (e.g. max 3 parameters to be put in registers) could simplify the problem.

Server Response from: ETNACODE01