Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
GHC
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
4,253
Issues
4,253
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
395
Merge Requests
395
Requirements
Requirements
List
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Code Review
Insights
Issue
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Glasgow Haskell Compiler
GHC
Commits
d02a50ee
Commit
d02a50ee
authored
Sep 04, 2013
by
Jan Stolarek
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix definition of DefinerOfRegs for CmmForeignCall
And update comments
parent
e30c84cb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
78 additions
and
8 deletions
+78
-8
compiler/cmm/CmmNode.hs
compiler/cmm/CmmNode.hs
+74
-5
compiler/cmm/CmmSink.hs
compiler/cmm/CmmSink.hs
+4
-3
No files found.
compiler/cmm/CmmNode.hs
View file @
d02a50ee
...
...
@@ -52,7 +52,7 @@ data CmmNode e x where
[
CmmActual
]
->
-- zero or more arguments
CmmNode
O
O
-- Semantics: clobbers any GlobalRegs for which callerSaves r == True
-- See Note [
foreign calls clobber GlobalReg
s]
-- See Note [
Unsafe foreign calls clobber caller-save register
s]
--
-- Invariant: the arguments and the ForeignTarget must not
-- mention any registers for which CodeGen.Platform.callerSaves
...
...
@@ -158,8 +158,8 @@ made manifest in CmmLayoutStack, where they are lowered into the above
sequence.
-}
{- Note [
foreign calls clobber GlobalReg
s]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{- Note [
Unsafe foreign calls clobber caller-save register
s]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~
A foreign call is defined to clobber any GlobalRegs that are mapped to
caller-saves machine registers (according to the prevailing C ABI).
...
...
@@ -329,8 +329,9 @@ instance DefinerOfRegs GlobalReg (CmmNode e x) where
foldRegsDefd
dflags
f
z
n
=
case
n
of
CmmAssign
lhs
_
->
fold
f
z
lhs
CmmUnsafeForeignCall
tgt
_
_
->
fold
f
z
(
foreignTargetRegs
tgt
)
CmmCall
{}
->
fold
f
z
activeRegs
CmmForeignCall
{
tgt
=
tgt
}
->
fold
f
z
(
foreignTargetRegs
tgt
)
CmmCall
{}
->
fold
f
z
activeRegs
CmmForeignCall
{}
->
fold
f
z
activeRegs
-- See Note [Safe foreign calls clobber STG registers]
_
->
z
where
fold
::
forall
a
b
.
DefinerOfRegs
GlobalReg
a
=>
...
...
@@ -344,6 +345,74 @@ instance DefinerOfRegs GlobalReg (CmmNode e x) where
foreignTargetRegs
(
ForeignTarget
_
(
ForeignConvention
_
_
_
CmmNeverReturns
))
=
[]
foreignTargetRegs
_
=
activeCallerSavesRegs
-- Note [Safe foreign calls clobber STG registers]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
-- During stack layout phase every safe foreign call is expanded into a block
-- that contains unsafe foreign call (instead of safe foreign call) and ends
-- with a normal call (See Note [Foreign calls]). This means that we must
-- treat safe foreign call as if it was a normal call (because eventually it
-- will be). This is important if we try to run sinking pass before stack
-- layout phase. Consider this example of what might go wrong (this is cmm
-- code from stablename001 test). Here is code after common block elimination
-- (before stack layout):
--
-- c1q6:
-- _s1pf::P64 = R1;
-- _c1q8::I64 = performMajorGC;
-- I64[(young<c1q9> + 8)] = c1q9;
-- foreign call "ccall" arg hints: [] result hints: [] (_c1q8::I64)(...)
-- returns to c1q9 args: ([]) ress: ([])ret_args: 8ret_off: 8;
-- c1q9:
-- I64[(young<c1qb> + 8)] = c1qb;
-- R1 = _s1pc::P64;
-- call stg_makeStableName#(R1) returns to c1qb, args: 8, res: 8, upd: 8;
--
-- If we run sinking pass now (still before stack layout) we will get this:
--
-- c1q6:
-- I64[(young<c1q9> + 8)] = c1q9;
-- foreign call "ccall" arg hints: [] result hints: [] performMajorGC(...)
-- returns to c1q9 args: ([]) ress: ([])ret_args: 8ret_off: 8;
-- c1q9:
-- I64[(young<c1qb> + 8)] = c1qb;
-- _s1pf::P64 = R1; <------ _s1pf sunk past safe foreign call
-- R1 = _s1pc::P64;
-- call stg_makeStableName#(R1) returns to c1qb, args: 8, res: 8, upd: 8;
--
-- Notice that _s1pf was sunk past a foreign call. When we run stack layout
-- safe call to performMajorGC will be turned into:
--
-- c1q6:
-- _s1pc::P64 = P64[Sp + 8];
-- I64[Sp - 8] = c1q9;
-- Sp = Sp - 8;
-- I64[I64[CurrentTSO + 24] + 16] = Sp;
-- P64[CurrentNursery + 8] = Hp + 8;
-- (_u1qI::I64) = call "ccall" arg hints: [PtrHint,]
-- result hints: [PtrHint] suspendThread(BaseReg, 0);
-- call "ccall" arg hints: [] result hints: [] performMajorGC();
-- (_u1qJ::I64) = call "ccall" arg hints: [PtrHint]
-- result hints: [PtrHint] resumeThread(_u1qI::I64);
-- BaseReg = _u1qJ::I64;
-- _u1qK::P64 = CurrentTSO;
-- _u1qL::P64 = I64[_u1qK::P64 + 24];
-- Sp = I64[_u1qL::P64 + 16];
-- SpLim = _u1qL::P64 + 192;
-- HpAlloc = 0;
-- Hp = I64[CurrentNursery + 8] - 8;
-- HpLim = I64[CurrentNursery] + (%MO_SS_Conv_W32_W64(I32[CurrentNursery + 48]) * 4096 - 1);
-- call (I64[Sp])() returns to c1q9, args: 8, res: 8, upd: 8;
-- c1q9:
-- I64[(young<c1qb> + 8)] = c1qb;
-- _s1pf::P64 = R1; <------ INCORRECT!
-- R1 = _s1pc::P64;
-- call stg_makeStableName#(R1) returns to c1qb, args: 8, res: 8, upd: 8;
--
-- Notice that c1q6 now ends with a call. Sinking _s1pf::P64 = R1 past that
-- call is clearly incorrect. This is what would happen if we assumed that
-- safe foreign call has the same semantics as unsafe foreign call. To prevent
-- this we need to treat safe foreign call as if was normal call.
-----------------------------------
-- mapping Expr in CmmNode
...
...
compiler/cmm/CmmSink.hs
View file @
d02a50ee
...
...
@@ -501,10 +501,10 @@ conflicts dflags (r, rhs, addr) node
|
SpMem
{}
<-
addr
,
CmmAssign
(
CmmGlobal
Sp
)
_
<-
node
=
True
-- (4) assignments that read caller-saves GlobalRegs conflict with a
-- foreign call. See Note [
foreign calls clobber GlobalRegs].
-- foreign call. See Note [
Unsafe foreign calls clobber caller-save registers]
|
CmmUnsafeForeignCall
{}
<-
node
,
anyCallerSavesRegs
dflags
rhs
=
True
-- (5) foreign calls clobber heap: see Note [
f
oreign calls clobber heap]
-- (5) foreign calls clobber heap: see Note [
F
oreign calls clobber heap]
|
CmmUnsafeForeignCall
{}
<-
node
,
memConflicts
addr
AnyMem
=
True
-- (6) native calls clobber any memory
...
...
@@ -563,7 +563,8 @@ data AbsMem
-- that was written in the same basic block. To take advantage of
-- non-aliasing of heap memory we will have to be more clever.
-- Note [foreign calls clobber]
-- Note [Foreign calls clobber heap]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
-- It is tempting to say that foreign calls clobber only
-- non-heap/stack memory, but unfortunately we break this invariant in
...
...
parcs
@trac-parcs
mentioned in issue
#8235 (closed)
·
Sep 05, 2013
mentioned in issue
#8235 (closed)
mentioned in issue #8235
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment