1#
2# Create functions - start
3#
4
5function(create_system)
6  cmake_parse_arguments(OBJECT "" "ENTRY;FORMAT;NAME;OBJECT" "" ${ARGN})
7
8  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}          TRUE)
9  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_OBJ_TYPE SYSTEM)
10  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_NAME     ${OBJECT_NAME})
11  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_FORMAT   ${OBJECT_FORMAT})
12  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_ENTRY    ${OBJECT_ENTRY})
13
14  set(${OBJECT_OBJECT} SYSTEM_${OBJECT_NAME} PARENT_SCOPE)
15endfunction()
16
17function(create_region)
18  cmake_parse_arguments(OBJECT "" "NAME;OBJECT;SIZE;START;FLAGS" "" ${ARGN})
19
20  if(DEFINED OBJECT_SIZE)
21    if(${OBJECT_SIZE} MATCHES "^([0-9]*)[kK]$")
22      math(EXPR OBJECT_SIZE "1024 * ${CMAKE_MATCH_1}" OUTPUT_FORMAT HEXADECIMAL)
23    elseif(${OBJECT_SIZE} MATCHES "^([0-9]*)[mM]$")
24      math(EXPR OBJECT_SIZE "1024 * 1024 * ${CMAKE_MATCH_1}" OUTPUT_FORMAT HEXADECIMAL)
25    elseif(NOT (${OBJECT_SIZE} MATCHES "^([0-9]*)$" OR ${OBJECT_SIZE} MATCHES "^0x([0-9a-fA-F]*)$"))
26      message(FATAL_ERROR "SIZE format is unknown.")
27    endif()
28  endif()
29
30  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}          TRUE)
31  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_OBJ_TYPE REGION)
32  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_NAME     ${OBJECT_NAME})
33  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_ADDRESS  ${OBJECT_START})
34  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_FLAGS    ${OBJECT_FLAGS})
35  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_SIZE     ${OBJECT_SIZE})
36
37  set(${OBJECT_OBJECT} REGION_${OBJECT_NAME} PARENT_SCOPE)
38endfunction()
39
40function(get_parent)
41  cmake_parse_arguments(GET_PARENT "" "OBJECT;PARENT;TYPE" "" ${ARGN})
42
43  get_property(type GLOBAL PROPERTY ${GET_PARENT_OBJECT}_OBJ_TYPE)
44  if(${type} STREQUAL ${GET_PARENT_TYPE})
45    # Already the right type, so just set and return.
46    set(${GET_PARENT_PARENT} ${GET_PARENT_OBJECT} PARENT_SCOPE)
47    return()
48  endif()
49
50  get_property(parent GLOBAL PROPERTY ${GET_PARENT_OBJECT}_PARENT)
51  get_property(type   GLOBAL PROPERTY ${parent}_OBJ_TYPE)
52  while(NOT ${type} STREQUAL ${GET_PARENT_TYPE})
53    get_property(parent GLOBAL PROPERTY ${parent}_PARENT)
54    get_property(type   GLOBAL PROPERTY ${parent}_OBJ_TYPE)
55  endwhile()
56
57  set(${GET_PARENT_PARENT} ${parent} PARENT_SCOPE)
58endfunction()
59
60function(create_group)
61  cmake_parse_arguments(OBJECT "" "GROUP;LMA;NAME;OBJECT;SYMBOL;VMA" "" ${ARGN})
62
63  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}          TRUE)
64  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_OBJ_TYPE GROUP)
65  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_NAME     ${OBJECT_NAME})
66  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_SYMBOL   ${OBJECT_SYMBOL})
67
68  if(DEFINED OBJECT_GROUP)
69    find_object(OBJECT parent NAME ${OBJECT_GROUP})
70  else()
71    if(DEFINED OBJECT_VMA)
72      find_object(OBJECT obj NAME ${OBJECT_VMA})
73      get_parent(OBJECT ${obj} PARENT parent TYPE REGION)
74
75      get_property(vma GLOBAL PROPERTY ${parent}_NAME)
76      set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_VMA ${vma})
77    endif()
78
79    if(DEFINED OBJECT_LMA)
80      find_object(OBJECT obj NAME ${OBJECT_LMA})
81      get_parent(OBJECT ${obj} PARENT parent TYPE REGION)
82
83      get_property(lma GLOBAL PROPERTY ${parent}_NAME)
84      set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_LMA ${lma})
85    endif()
86  endif()
87
88  get_property(GROUP_FLAGS_INHERITED GLOBAL PROPERTY ${parent}_FLAGS)
89  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_FLAGS  ${GROUP_FLAGS_INHERITED})
90  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_PARENT ${parent})
91
92  add_group(OBJECT ${parent} GROUP GROUP_${OBJECT_NAME})
93
94  set(${OBJECT_OBJECT} GROUP_${OBJECT_NAME} PARENT_SCOPE)
95endfunction()
96
97function(create_section)
98  set(single_args "NAME;ADDRESS;ALIGN_WITH_INPUT;TYPE;ALIGN;ENDALIGN;SUBALIGN;VMA;LMA;NOINPUT;NOINIT;NOSYMBOLS;GROUP;SYSTEM")
99  set(multi_args  "PASS")
100
101  cmake_parse_arguments(SECTION "" "${single_args}" "${multi_args}" ${ARGN})
102
103  if(DEFINED SECTION_PASS AND NOT "${PASS}" IN_LIST SECTION_PASS)
104    # This section is not active in this pass, ignore.
105    return()
106  endif()
107
108  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME} TRUE)
109  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_OBJ_TYPE         SECTION)
110  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NAME             ${SECTION_NAME})
111  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ADDRESS          ${SECTION_ADDRESS})
112  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_TYPE             ${SECTION_TYPE})
113  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ALIGN            ${SECTION_ALIGN})
114  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ALIGN_WITH_INPUT ${SECTION_ALIGN_WITH_INPUT})
115  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_SUBALIGN         ${SECTION_SUBALIGN})
116  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ENDALIGN         ${SECTION_ENDALIGN})
117  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOINPUT          ${SECTION_NOINPUT})
118  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOINIT           ${SECTION_NOINIT})
119  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOSYMBOLS        ${SECTION_NOSYMBOLS})
120
121  string(REGEX REPLACE "^[\.]" "" name_clean "${SECTION_NAME}")
122  string(REPLACE "." "_" name_clean "${name_clean}")
123  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NAME_CLEAN ${name_clean})
124
125  set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_start      ${name_clean})
126  set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_size       ${name_clean})
127  set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_load_start ${name_clean})
128  set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end        ${name_clean})
129
130  set(INDEX 100)
131  set(settings_single "ALIGN;ANY;FIRST;KEEP;OFFSET;PASS;PRIO;SECTION;SORT")
132  set(settings_multi  "FLAGS;INPUT;SYMBOLS")
133  foreach(settings ${SECTION_SETTINGS})
134    if("${settings}" MATCHES "^{(.*)}$")
135      cmake_parse_arguments(SETTINGS "" "${settings_single}" "${settings_multi}" ${CMAKE_MATCH_1})
136
137      if(NOT ("${SETTINGS_SECTION}" STREQUAL "${SECTION_NAME}"))
138        continue()
139      endif()
140
141      if(DEFINED SETTINGS_PASS AND NOT "${PASS}" IN_LIST SETTINGS_PASS)
142        # This section setting is not active in this pass, ignore.
143        continue()
144      endif()
145
146      if(DEFINED SETTINGS_PRIO)
147        set(idx ${SETTINGS_PRIO})
148      else()
149        set(idx ${INDEX})
150        math(EXPR INDEX "${INDEX} + 1")
151      endif()
152
153      foreach(setting ${settings_single} ${settings_multi})
154        set_property(GLOBAL PROPERTY
155          SECTION_${SECTION_NAME}_SETTING_${idx}_${setting}
156          ${SETTINGS_${setting}}
157        )
158        if(DEFINED SETTINGS_SORT)
159          set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end ${name_clean}_end)
160        endif()
161      endforeach()
162
163      set_property(GLOBAL APPEND PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES ${idx})
164
165    endif()
166  endforeach()
167
168  get_property(indicies GLOBAL PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES)
169  if(DEFINED indicies)
170    list(SORT indicies COMPARE NATURAL)
171    set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES ${indicies})
172  endif()
173
174  if(DEFINED SECTION_GROUP)
175    find_object(OBJECT parent NAME ${SECTION_GROUP})
176  elseif(DEFINED SECTION_VMA OR DEFINED SECTION_LMA)
177    if(DEFINED SECTION_VMA)
178      find_object(OBJECT object NAME ${SECTION_VMA})
179      get_parent(OBJECT ${object} PARENT parent TYPE REGION)
180
181      get_property(vma GLOBAL PROPERTY ${parent}_NAME)
182      set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_VMA ${vma})
183      set(SECTION_VMA ${vma})
184    endif()
185
186    if(DEFINED SECTION_LMA)
187      find_object(OBJECT object NAME ${SECTION_LMA})
188      get_parent(OBJECT ${object} PARENT parent TYPE REGION)
189
190      get_property(lma GLOBAL PROPERTY ${parent}_NAME)
191      set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_LMA ${lma})
192      set(SECTION_LMA ${lma})
193    endif()
194  else()
195    set(parent ${SECTION_SYSTEM})
196  endif()
197
198  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_PARENT ${parent})
199  add_section(OBJECT ${parent} SECTION ${SECTION_NAME} ADDRESS ${SECTION_ADDRESS} VMA ${SECTION_VMA})
200endfunction()
201
202function(create_symbol)
203  cmake_parse_arguments(SYM "" "OBJECT;EXPR;SIZE;SUBALIGN;SYMBOL" "" ${ARGN})
204
205  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL} TRUE)
206  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_OBJ_TYPE SYMBOL)
207  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_NAME     ${SYM_SYMBOL})
208  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_EXPR     ${SYM_EXPR})
209  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_SIZE     ${SYM_SIZE})
210  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_SYMBOL   ${SYM_SYMBOL})
211
212  set_property(GLOBAL PROPERTY SYMBOL_TABLE_${SYM_SYMBOL} ${SYM_SYMBOL})
213
214  add_symbol(OBJECT ${SYM_OBJECT} SYMBOL SYMBOL_${SYM_SYMBOL})
215endfunction()
216
217#
218# Create functions - end
219#
220
221#
222# Add functions - start
223#
224function(add_region)
225  cmake_parse_arguments(ADD_REGION "" "OBJECT;REGION" "" ${ARGN})
226
227  get_property(exists GLOBAL PROPERTY ${ADD_REGION_OBJECT})
228  if(NOT exists)
229    message(FATAL_ERROR
230      "Adding region ${ADD_REGION_REGION} to none-existing object: "
231      "${ADD_REGION_OBJECT}"
232    )
233  endif()
234
235  set_property(GLOBAL PROPERTY ${ADD_REGION_REGION}_PARENT ${ADD_REGION_OBJECT})
236  set_property(GLOBAL APPEND PROPERTY ${ADD_REGION_OBJECT}_REGIONS ${ADD_REGION_REGION})
237endfunction()
238
239function(add_group)
240  cmake_parse_arguments(ADD_GROUP "" "OBJECT;GROUP" "" ${ARGN})
241
242  get_property(exists GLOBAL PROPERTY ${ADD_GROUP_OBJECT})
243  if(NOT exists)
244    message(FATAL_ERROR
245      "Adding group ${ADD_GROUP_GROUP} to none-existing object: "
246      "${ADD_GROUP_OBJECT}"
247    )
248  endif()
249
250  get_property(vma GLOBAL PROPERTY ${ADD_GROUP_GROUP}_VMA)
251  get_property(object_name GLOBAL PROPERTY ${ADD_GROUP_OBJECT}_NAME)
252
253  if((NOT DEFINED vma) OR ("${vma}" STREQUAL ${object_name}))
254    set_property(GLOBAL APPEND PROPERTY ${ADD_GROUP_OBJECT}_GROUPS ${ADD_GROUP_GROUP})
255  else()
256    set_property(GLOBAL APPEND PROPERTY ${ADD_GROUP_OBJECT}_${vma}_GROUPS ${ADD_GROUP_GROUP})
257  endif()
258endfunction()
259
260function(add_section)
261  cmake_parse_arguments(ADD_SECTION "" "OBJECT;SECTION;ADDRESS;VMA" "" ${ARGN})
262
263  if(DEFINED ADD_SECTION_OBJECT)
264    get_property(type GLOBAL PROPERTY ${ADD_SECTION_OBJECT}_OBJ_TYPE)
265    get_property(object_name GLOBAL PROPERTY ${ADD_SECTION_OBJECT}_NAME)
266
267    if(NOT DEFINED type)
268      message(FATAL_ERROR
269              "Adding section ${ADD_SECTION_SECTION} to "
270              "none-existing object: ${ADD_SECTION_OBJECT}"
271      )
272    endif()
273  else()
274    set(ADD_SECTION_OBJECT RELOCATEABLE)
275  endif()
276
277  if("${ADD_SECTION_VMA}" STREQUAL "${object_name}" AND DEFINED ADD_SECTION_ADDRESS)
278    set_property(GLOBAL APPEND PROPERTY
279      ${ADD_SECTION_OBJECT}_SECTIONS_FIXED
280      SECTION_${ADD_SECTION_SECTION}
281    )
282  elseif(NOT DEFINED ADD_SECTION_VMA AND DEFINED SECTION_ADDRESS)
283    set_property(GLOBAL APPEND PROPERTY
284      ${ADD_SECTION_OBJECT}_SECTIONS_FIXED
285      SECTION_${ADD_SECTION_SECTION}
286    )
287  elseif("${ADD_SECTION_VMA}" STREQUAL "${object_name}")
288    set_property(GLOBAL APPEND PROPERTY
289      ${ADD_SECTION_OBJECT}_SECTIONS
290      SECTION_${ADD_SECTION_SECTION}
291    )
292  elseif(NOT DEFINED ADD_SECTION_VMA)
293    set_property(GLOBAL APPEND PROPERTY
294      ${ADD_SECTION_OBJECT}_SECTIONS
295      SECTION_${ADD_SECTION_SECTION}
296    )
297  elseif(DEFINED SECTION_ADDRESS)
298    set_property(GLOBAL APPEND PROPERTY
299      ${ADD_SECTION_OBJECT}_${ADD_SECTION_VMA}_SECTIONS_FIXED
300      SECTION_${ADD_SECTION_SECTION}
301    )
302  else()
303    set_property(GLOBAL APPEND PROPERTY
304      ${ADD_SECTION_OBJECT}_${ADD_SECTION_VMA}_SECTIONS
305      SECTION_${ADD_SECTION_SECTION}
306    )
307  endif()
308endfunction()
309
310function(add_symbol)
311  cmake_parse_arguments(ADD_SYMBOL "" "OBJECT;SYMBOL" "" ${ARGN})
312
313  # Section can be fixed address or not, VMA == LMA, .
314  #
315  get_property(exists GLOBAL PROPERTY ${ADD_SYMBOL_OBJECT})
316  if(NOT exists)
317    message(FATAL_ERROR
318      "Adding symbol ${ADD_SYMBOL_SYMBOL} to none-existing object: "
319      "${ADD_SYMBOL_OBJECT}"
320    )
321  endif()
322
323  set_property(GLOBAL APPEND PROPERTY ${ADD_SYMBOL_OBJECT}_SYMBOLS ${ADD_SYMBOL_SYMBOL})
324endfunction()
325
326#
327# Add functions - end
328#
329
330#
331# Retrieval functions - start
332#
333function(find_object)
334  cmake_parse_arguments(FIND "" "OBJECT;NAME" "" ${ARGN})
335
336  get_property(REGION  GLOBAL PROPERTY REGION_${FIND_NAME})
337  get_property(GROUP   GLOBAL PROPERTY GROUP_${FIND_NAME})
338  get_property(SECTION GLOBAL PROPERTY SECTION_${FIND_NAME})
339
340  if(REGION)
341    set(${FIND_OBJECT} REGION_${FIND_NAME} PARENT_SCOPE)
342  elseif(GROUP)
343    set(${FIND_OBJECT} GROUP_${FIND_NAME} PARENT_SCOPE)
344  elseif(SECTION)
345    set(${FIND_OBJECT} SECTION_${FIND_NAME} PARENT_SCOPE)
346  else()
347    message(WARNING "No object with name ${FIND_NAME} could be found.")
348  endif()
349endfunction()
350
351function(get_objects)
352  cmake_parse_arguments(GET "" "LIST;OBJECT;TYPE" "" ${ARGN})
353
354  get_property(type GLOBAL PROPERTY ${GET_OBJECT}_OBJ_TYPE)
355
356  if(${type} STREQUAL SECTION)
357    # A section doesn't have sub-items.
358    return()
359  endif()
360
361  if(NOT (${GET_TYPE} STREQUAL SECTION
362     OR   ${GET_TYPE} STREQUAL GROUP)
363  )
364    message(WARNING "Only retrieval of SECTION GROUP objects are supported.")
365    return()
366  endif()
367
368  set(out)
369
370  get_parent(OBJECT ${GET_OBJECT} PARENT parent TYPE SYSTEM)
371  get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
372  list(REMOVE_ITEM regions ${GET_OBJECT})
373
374  if(${GET_TYPE} STREQUAL SECTION)
375    get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_SECTIONS_FIXED)
376    list(APPEND out ${sections})
377
378    get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_GROUPS)
379    foreach(group ${groups})
380      get_objects(LIST sections OBJECT ${group} TYPE ${GET_TYPE})
381      list(APPEND out ${sections})
382    endforeach()
383
384    get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_SECTIONS)
385    list(APPEND out ${sections})
386
387    foreach(region ${regions})
388      get_property(vma GLOBAL PROPERTY ${region}_NAME)
389
390      get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_${vma}_SECTIONS_FIXED)
391      list(APPEND out ${sections})
392
393      get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_${vma}_GROUPS)
394      foreach(group ${groups})
395        get_objects(LIST sections OBJECT ${group} TYPE ${GET_TYPE})
396        list(APPEND out ${sections})
397      endforeach()
398
399      get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_${vma}_SECTIONS)
400      list(APPEND out ${sections})
401    endforeach()
402  endif()
403
404  if(${GET_TYPE} STREQUAL GROUP)
405    get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_GROUPS)
406    list(APPEND out ${groups})
407
408    foreach(group ${groups})
409      get_objects(LIST subgroups OBJECT ${group} TYPE ${GET_TYPE})
410      list(APPEND out ${subgroups})
411    endforeach()
412
413    foreach(region ${regions})
414      get_property(vma GLOBAL PROPERTY ${region}_NAME)
415
416      get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_${vma}_GROUPS)
417      list(APPEND out ${groups})
418
419      foreach(group ${groups})
420        get_objects(LIST subgroups OBJECT ${group} TYPE ${GET_TYPE})
421        list(APPEND out ${subgroups})
422      endforeach()
423    endforeach()
424  endif()
425
426  set(${GET_LIST} ${out} PARENT_SCOPE)
427endfunction()
428
429#
430# Retrieval functions - end
431#
432
433function(is_empty)
434  cmake_parse_arguments(IS_EMPTY "" "OBJECT" "" ${ARGN})
435
436  get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_SECTIONS_FIXED)
437  if(DEFINED sections)
438    set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
439    return()
440  endif()
441
442  get_property(groups GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_GROUPS)
443  if(DEFINED groups)
444    set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
445    return()
446  endif()
447
448
449  get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_SECTIONS)
450  if(DEFINED sections)
451    set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
452    return()
453  endif()
454
455  get_parent(OBJECT ${IS_EMPTY_OBJECT} PARENT parent TYPE SYSTEM)
456  get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
457  list(REMOVE_ITEM regions ${IS_EMPTY_OBJECT})
458  foreach(region ${regions})
459    get_property(vma GLOBAL PROPERTY ${region}_NAME)
460    get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_SECTIONS_FIXED)
461    if(DEFINED sections)
462      set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
463      return()
464    endif()
465
466    get_property(groups GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_GROUPS)
467    if(DEFINED groups)
468      set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
469      return()
470    endif()
471
472    get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_SECTIONS)
473    if(DEFINED sections)
474      set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
475      return()
476    endif()
477  endforeach()
478  set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY TRUE)
479endfunction()
480
481# This function post process the region for easier use.
482#
483# This is common post processing.
484# If the calling <linker>_script.cmake generator implements its own
485# process_region(), then the process_region_common() must be called explicitly
486# from the process_region() from the <linker>_script.cmake generator.
487#
488# This allows a custom <linker>_script.cmake generator to completely disable
489# the common post processing of regions.
490#
491# Tasks:
492# - Apply missing settings, such as initial address for first section in a region.
493# - Symbol names on sections
494# - Ordered list of all sections for easier retrival on printing and configuration.
495function(process_region_common)
496  cmake_parse_arguments(REGION_COMMON "" "OBJECT" "" ${ARGN})
497
498  is_empty(OBJECT ${REGION_COMMON_OBJECT})
499
500  set(sections)
501  get_objects(LIST sections OBJECT ${REGION_COMMON_OBJECT} TYPE SECTION)
502  set_property(GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_SECTION_LIST_ORDERED ${sections})
503
504  set(groups)
505  get_objects(LIST groups OBJECT ${REGION_COMMON_OBJECT} TYPE GROUP)
506  set_property(GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_GROUP_LIST_ORDERED ${groups})
507
508  list(LENGTH sections section_count)
509  if(section_count GREATER 0)
510    list(GET sections 0 section)
511    get_property(address GLOBAL PROPERTY ${section}_ADDRESS)
512    if(NOT DEFINED address)
513      get_parent(OBJECT ${REGION_COMMON_OBJECT} PARENT parent TYPE REGION)
514      get_property(address GLOBAL PROPERTY ${parent}_ADDRESS)
515      set_property(GLOBAL PROPERTY ${section}_ADDRESS ${address})
516    endif()
517  endif()
518
519  get_parent(OBJECT ${REGION_COMMON_OBJECT} PARENT parent TYPE SYSTEM)
520  get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
521  list(REMOVE_ITEM regions ${REGION_COMMON_OBJECT})
522  foreach(region ${regions})
523    get_property(vma GLOBAL PROPERTY ${region}_NAME)
524    set(sections_${vma})
525    get_property(sections GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_SECTIONS_FIXED)
526    list(APPEND sections_${vma} ${sections})
527
528    get_property(groups GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_GROUPS)
529    foreach(group ${groups})
530      get_objects(LIST sections OBJECT ${group} TYPE SECTION)
531      list(APPEND sections_${vma} ${sections})
532    endforeach()
533
534    get_property(sections GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_SECTIONS)
535    list(APPEND sections_${vma} ${sections})
536
537    list(LENGTH sections_${vma} section_count)
538    if(section_count GREATER 0)
539      list(GET sections_${vma} 0 section)
540      get_property(address GLOBAL PROPERTY ${section}_ADDRESS)
541      if(NOT DEFINED address)
542        get_property(address GLOBAL PROPERTY ${region}_ADDRESS)
543        set_property(GLOBAL PROPERTY ${section}_ADDRESS ${address})
544      endif()
545    endif()
546  endforeach()
547endfunction()
548
549if(NOT COMMAND process_region)
550  function(process_region)
551    process_region_common(${ARGN})
552  endfunction()
553endif()
554
555
556#
557# String functions - start
558#
559# Each linker must implement their own <type>_to_string() functions to
560# generate a correct linker script.
561#
562if(NOT COMMAND system_to_string)
563  function(system_to_string)
564    message(WARNING "No linker defined function found. Please implement a "
565                    "system_to_string() function for this linker."
566    )
567  endfunction()
568endif()
569
570if(NOT COMMAND group_to_string)
571  function(group_to_string)
572    message(WARNING "No linker defined function found. Please implement a "
573                    "group_to_string() function for this linker."
574    )
575  endfunction()
576endif()
577
578if(NOT COMMAND section_to_string)
579  function(section_to_string)
580    message(WARNING "No linker defined function found. Please implement a "
581                    "section_to_string() function for this linker."
582    )
583  endfunction()
584endif()
585
586if(NOT COMMAND symbol_to_string)
587  function(symbol_to_string)
588    message(WARNING "No linker defined function found. Please implement a "
589                    "symbol_to_string() function for this linker."
590    )
591  endfunction()
592endif()
593
594function(to_string)
595  cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
596
597  get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE)
598
599  if("${type}" STREQUAL SYSTEM)
600    system_to_string(OBJECT ${STRING_OBJECT} STRING ${STRING_STRING})
601  elseif(("${type}" STREQUAL REGION) OR ("${type}" STREQUAL GROUP))
602    group_to_string(OBJECT ${STRING_OBJECT} STRING ${STRING_STRING})
603  elseif("${type}" STREQUAL SECTION)
604    section_to_string(SECTION ${STRING_OBJECT} STRING ${STRING_STRING})
605  elseif("${type}" STREQUAL SYMBOL)
606    symbol_to_string(SYMBOL ${STRING_OBJECT} STRING ${STRING_STRING})
607  endif()
608
609  set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
610endfunction()
611
612#
613# String functions - end
614#
615
616create_system(OBJECT new_system NAME ZEPHYR_LINKER_v1 FORMAT ${FORMAT} ENTRY ${ENTRY})
617
618# Sorting the memory sections in ascending order.
619foreach(region ${MEMORY_REGIONS})
620  if("${region}" MATCHES "^{(.*)}$")
621    cmake_parse_arguments(REGION "" "NAME;START" "" ${CMAKE_MATCH_1})
622    math(EXPR start_dec "${REGION_START}" OUTPUT_FORMAT DECIMAL)
623    set(region_id ${start_dec}_${REGION_NAME})
624    set(region_${region_id} ${region})
625    string(REPLACE ";" "\;" region_${region_id} "${region_${region_id}}")
626    list(APPEND region_sort ${region_id})
627  endif()
628endforeach()
629
630list(SORT region_sort COMPARE NATURAL)
631set(MEMORY_REGIONS_SORTED)
632foreach(region_start ${region_sort})
633  list(APPEND MEMORY_REGIONS_SORTED "${region_${region_start}}")
634endforeach()
635# sorting complete.
636
637foreach(region ${MEMORY_REGIONS_SORTED})
638  if("${region}" MATCHES "^{(.*)}$")
639    create_region(OBJECT new_region ${CMAKE_MATCH_1})
640
641    add_region(OBJECT ${new_system} REGION ${new_region})
642  endif()
643endforeach()
644
645foreach(group ${GROUPS})
646  if("${group}" MATCHES "^{(.*)}$")
647    create_group(OBJECT new_group ${CMAKE_MATCH_1})
648  endif()
649endforeach()
650
651foreach(section ${SECTIONS})
652  if("${section}" MATCHES "^{(.*)}$")
653    create_section(${CMAKE_MATCH_1} SYSTEM ${new_system})
654  endif()
655endforeach()
656
657foreach(symbol ${SYMBOLS})
658  if("${symbol}" MATCHES "^{(.*)}$")
659    create_symbol(OBJECT ${new_system} ${CMAKE_MATCH_1})
660  endif()
661endforeach()
662
663get_property(regions GLOBAL PROPERTY ${new_system}_REGIONS)
664foreach(region ${regions})
665  process_region(OBJECT ${region})
666endforeach()
667
668set(OUT)
669to_string(OBJECT ${new_system} STRING OUT)
670
671if(OUT_FILE)
672  file(WRITE ${OUT_FILE} "${OUT}")
673endif()
674