1
0
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:
g012 2017-10-14 22:51:18 +02:00
parent 2f89c9f9c3
commit 3db7a48f48
3 changed files with 16 additions and 8 deletions

View File

@ -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

View File

@ -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.

View File

@ -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)