mirror of
https://github.com/g012/l65.git
synced 2024-06-11 10:29:27 +00:00
Added strip_empty option and weak sections, and empty sections are no more removed by default.
Allowed to pass section references to VCS far calls.
This commit is contained in:
parent
2f89c9f9c3
commit
3db7a48f48
19
6502.lua
19
6502.lua
|
@ -9,6 +9,7 @@ local stats={} M.stats=stats setmetatable(stats, stats)
|
||||||
local before_link={} M.before_link=before_link
|
local before_link={} M.before_link=before_link
|
||||||
|
|
||||||
M.strip = true -- set to false to disable dead stripping of relocatable sections
|
M.strip = true -- set to false to disable dead stripping of relocatable sections
|
||||||
|
M.strip_empty = false -- set to true to strip empty sections: their label will then not resolve
|
||||||
M.pcall = pcall -- set to empty function returning false to disable eval during compute_size()
|
M.pcall = pcall -- set to empty function returning false to disable eval during compute_size()
|
||||||
-- set to pcall directly if you want to keep ldazab/x/y eval during compute_size() even if
|
-- set to pcall directly if you want to keep ldazab/x/y eval during compute_size() even if
|
||||||
-- disabled for other parts (required to distinguish automatically between zp/abs addressing)
|
-- disabled for other parts (required to distinguish automatically between zp/abs addressing)
|
||||||
|
@ -124,7 +125,7 @@ M.link = function()
|
||||||
local position_section = function(section, constrain)
|
local position_section = function(section, constrain)
|
||||||
local location = section.location
|
local location = section.location
|
||||||
local chunks,rorg = location.chunks,location.rorg
|
local chunks,rorg = location.chunks,location.rorg
|
||||||
table.sort(chunks, function(a,b) return a.size==b.size and a.id<b.id or a.size<b.size end)
|
table.sort(chunks, function(a,b) if a.size==b.size then return a.id<b.id end return a.size<b.size end)
|
||||||
for chunk_ix,chunk in ipairs(chunks) do if chunk.size >= section.size then
|
for chunk_ix,chunk in ipairs(chunks) do if chunk.size >= section.size then
|
||||||
local waste,cross,lsb,position = math.maxinteger,math.maxinteger,math.maxinteger
|
local waste,cross,lsb,position = math.maxinteger,math.maxinteger,math.maxinteger
|
||||||
local usage_lowest = function(start, finish)
|
local usage_lowest = function(start, finish)
|
||||||
|
@ -190,8 +191,12 @@ M.link = function()
|
||||||
location.cycles = location.cycles + section.cycles
|
location.cycles = location.cycles + section.cycles
|
||||||
location.used = location.used + section.size
|
location.used = location.used + section.size
|
||||||
if section.size == 0 then
|
if section.size == 0 then
|
||||||
sections[ix]=nil
|
if M.strip_empty or section.weak then
|
||||||
if not section.org then table.insert(symbols_to_remove, section.label) end
|
sections[ix]=nil
|
||||||
|
if not section.org then table.insert(symbols_to_remove, section.label) end
|
||||||
|
else
|
||||||
|
section.org = location.start
|
||||||
|
end
|
||||||
elseif not section.org then
|
elseif not section.org then
|
||||||
if M.strip and not section.refcount and not section.strong then
|
if M.strip and not section.refcount and not section.strong then
|
||||||
sections[ix]=nil
|
sections[ix]=nil
|
||||||
|
@ -228,7 +233,7 @@ M.link = function()
|
||||||
end end
|
end end
|
||||||
end
|
end
|
||||||
|
|
||||||
table.sort(related_sections, function(a,b) return a.size==b.size and a.id<b.id or a.size>b.size end)
|
table.sort(related_sections, function(a,b) if a.size==b.size then return a.id<b.id end return a.size>b.size end)
|
||||||
for _,section in ipairs(related_sections) do if not section.org then
|
for _,section in ipairs(related_sections) do if not section.org then
|
||||||
local related,ins = {},table.insert
|
local related,ins = {},table.insert
|
||||||
local function collect(section_parent, offset)
|
local function collect(section_parent, offset)
|
||||||
|
@ -268,7 +273,7 @@ M.link = function()
|
||||||
|
|
||||||
for _,location in ipairs(locations) do
|
for _,location in ipairs(locations) do
|
||||||
local position_independent_sections = location.position_independent_sections
|
local position_independent_sections = location.position_independent_sections
|
||||||
table.sort(position_independent_sections, function(a,b) return a.size==b.size and a.label>b.label or a.size>b.size end)
|
table.sort(position_independent_sections, function(a,b) if a.size==b.size then return a.label>b.label end return a.size>b.size end)
|
||||||
for _,section in ipairs(position_independent_sections) do
|
for _,section in ipairs(position_independent_sections) do
|
||||||
if not position_section(section) then
|
if not position_section(section) then
|
||||||
error("unable to find space for section " .. section.label)
|
error("unable to find space for section " .. section.label)
|
||||||
|
@ -369,7 +374,7 @@ M.writesym = function(filename)
|
||||||
local ins,fmt,rep = table.insert,string.format,string.rep
|
local ins,fmt,rep = table.insert,string.format,string.rep
|
||||||
local s,sym_rev = {'--- Symbol List'},{}
|
local s,sym_rev = {'--- Symbol List'},{}
|
||||||
for k,v in pairs(symbols) do if type(v) == 'number' then ins(sym_rev,k) end end
|
for k,v in pairs(symbols) do if type(v) == 'number' then ins(sym_rev,k) end end
|
||||||
table.sort(sym_rev, function(a,b) local x,y=symbols[a],symbols[b] return x==y and a<b or x<y end)
|
table.sort(sym_rev, function(a,b) local x,y=symbols[a],symbols[b] if x==y then return a<b end return x<y end)
|
||||||
for _,v in ipairs(sym_rev) do
|
for _,v in ipairs(sym_rev) do
|
||||||
local k=symbols[v]
|
local k=symbols[v]
|
||||||
local u=v:match'.*()_' if u then -- change _ to . in local labels
|
local u=v:match'.*()_' if u then -- change _ to . in local labels
|
||||||
|
@ -437,7 +442,7 @@ end
|
||||||
M.section = function(t)
|
M.section = function(t)
|
||||||
local section = {}
|
local section = {}
|
||||||
local name = t or 'S'..id()
|
local name = t or 'S'..id()
|
||||||
if (type(name) ~= 'string') then
|
if type(name) ~= 'string' then
|
||||||
assert(type(t) == 'table', "invalid arguments for section")
|
assert(type(t) == 'table', "invalid arguments for section")
|
||||||
if t.type == 'section' then
|
if t.type == 'section' then
|
||||||
for _,v in ipairs(sections) do if v == t then
|
for _,v in ipairs(sections) do if v == t then
|
||||||
|
|
|
@ -308,6 +308,8 @@ Check if `v` is within long range, call `error` if it is not, or convert negativ
|
||||||
|
|
||||||
`strip`: defaults to `true`. Set to `false` to disable dead stripping of relocatable sections.
|
`strip`: defaults to `true`. Set to `false` to disable dead stripping of relocatable sections.
|
||||||
|
|
||||||
|
`strip_empty`: defaults to `false`. Set to `true` to enable stripping of empty sections; otherwise, they are positioned at the start of the container location.
|
||||||
|
|
||||||
`pcall`: defaults to system's `pcall`. Set to an empty function returning `false` to disable early evaluation of expressions during link phase for computing the size of each section. This will force all opcodes without an explicit size to default to the largest possible size...
|
`pcall`: defaults to system's `pcall`. Set to an empty function returning `false` to disable early evaluation of expressions during link phase for computing the size of each section. This will force all opcodes without an explicit size to default to the largest possible size...
|
||||||
|
|
||||||
`pcall_za`: ...unless this field is set to system's `pcall`. Defaults to module's `pcall`. This field is used only by the `za*` (`zab`, `zax`, `zay`) virtual addressing modes, to discriminate between zeropage and absolute addressing.
|
`pcall_za`: ...unless this field is set to system's `pcall`. Defaults to module's `pcall`. This field is used only by the `za*` (`zab`, `zax`, `zay`) virtual addressing modes, to discriminate between zeropage and absolute addressing.
|
||||||
|
@ -373,7 +375,7 @@ If `opt.org` is set, the section is fixed and must start at this address in ROM;
|
||||||
|
|
||||||
`opt.align` requests the section starts on an address multiple of `opt.align`. If `opt.offset` is specified, then it is the reference point from the start of the section which must be aligned, instead of the start of the section itself.
|
`opt.align` requests the section starts on an address multiple of `opt.align`. If `opt.offset` is specified, then it is the reference point from the start of the section which must be aligned, instead of the start of the section itself.
|
||||||
|
|
||||||
If `opt.strong` resolves to `true`, the section will not be stripped even if it has no reference and stripping is active.
|
If `opt.strong` resolves to `true`, the section will not be stripped even if it has no reference and stripping is active. If `opt.weak` resolves to `true`, the section is stripped if its size is 0, and the references to it will fail to resolve.
|
||||||
|
|
||||||
When using the `opt` version, `opt` is first set as the actual section table, so custom properties are preserved.
|
When using the `opt` version, `opt` is first set as the actual section table, so custom properties are preserved.
|
||||||
|
|
||||||
|
|
1
vcs.l65
1
vcs.l65
|
@ -193,6 +193,7 @@ farcall = function(dst)
|
||||||
local loc_src = location_current
|
local loc_src = location_current
|
||||||
local create_stubs = function()
|
local create_stubs = function()
|
||||||
if type(dst) == 'function' then dst = dst() end
|
if type(dst) == 'function' then dst = dst() end
|
||||||
|
if type(dst) == 'table' and dst.type == 'section' then dst = dst.instructions[1] end -- put labels only
|
||||||
local stub,loc_dst = far_stubs[dst],dst.section.location
|
local stub,loc_dst = far_stubs[dst],dst.section.location
|
||||||
if not (stub and stub[loc_src]) then
|
if not (stub and stub[loc_src]) then
|
||||||
location(loc_src)
|
location(loc_src)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user