2019-07-15 12:21:50 +00:00
[< back to index ](../doc_index.md )
2018-04-02 22:21:26 +00:00
2018-02-01 21:39:38 +00:00
# Macros and inlining
2018-01-04 00:15:04 +00:00
2018-02-01 21:39:38 +00:00
## Macros
2018-01-04 00:15:04 +00:00
2020-01-03 22:56:37 +00:00
Functions defined with the `macro` keyword are not actual functions, but they are used as syntax replacements.
It implies the following:
* macros must return `void`
* cannot be `inline` , `noinline` or `extern`
* can be `asm` - in this case, they should **not** end with a return instruction
* do not have an address
* their invocations cannot be used as expressions
* in case of `asm` macros, the parameters must be defined as either `const` (compile-time constants) or `ref` (variables)
2020-02-02 22:19:17 +00:00
* in case of non-`asm` macros, the parameters must be variables; exceptionally, their type may be declared as `void`
2020-01-03 22:56:37 +00:00
* macros do not have their own scope (they reuse the scope from their invocations) – exceptions: the parameters and the local labels defined in assembly
* control-flow statements (`break`, `continue` , `return` , `goto` , `label` ) are run as if places in the caller function
When invoking a macro, you need to pass variables as arguments to parameters annotated with `ref` and constants as arguments annotated with `const` .
2020-02-02 22:19:17 +00:00
Invoking a non-`asm` macro requires the types of passed variables to match precisely. No type conversions are performed.
Exception: parameters of type `void` can accept a variable of any type.
2020-01-03 22:56:37 +00:00
You can invoke a macro from assembly, by preceding the invocation with `+`
Examples:
macro void inc_x() {
x += 1
}
byte add_two_1(byte x) {
inc_x()
inc_x()
return x
}
macro void inc(byte b) {
b += 1
}
byte add_two_2(byte x) {
inc(x)
inc(x)
return x
}
macro void add(byte b, byte v) {
b += v
}
macro void retu(byte result) {
return result
}
byte add_two_3(byte x) {
add(x, 2)
retu(x)
}
macro asm byte add_asm(byte ref b, byte const v) {
LDA b
CLC
ADC #v
// no RTS!
}
byte add_two_4(byte x) {
add_asm(x, 2)
return x
}
2018-01-04 00:15:04 +00:00
## Automatic inlining
2019-06-11 22:20:24 +00:00
You can control inlining behavior in several ways:
* functions declared with the `inline` keyword will be inlined if possible
* functions declared with the `noinline` keyword will never be inlined
* the remaining functions may be inlined only if the `-finline` command-line option is enabled
and the compiler decides the function is worth doing
2018-02-01 21:39:38 +00:00
2019-12-01 02:16:09 +00:00
## Automatic subroutine extraction
Subroutine extraction is the opposite of inlining.
When given the `-fsubroutine-extraction` , the compiler will attempt to extract common code fragments to new subroutines.
The code will get smaller and slower.
Generally, when using `-fsubroutine-extraction` , it's recommended to also use `-finline` .
This allows the compiler to first inline and optimize code and then extract it back when appropriate.