Custom legalization for global_addr.

The code to compute the address of a global variable depends on the kind
of variable, so custom legalization is required.

- Add a legalizer::globalvar module which exposes an
  expand_global_addr() function. This module is likely to grow as we add
  more types of global variables.
- Add a ArgumentPurpose::VMContext enumerator. This is used to represent
  special 'vmctx' arguments that are used as base pointers for vmctx
  globals.
This commit is contained in:
Jakob Stoklund Olesen
2017-08-18 09:08:41 -07:00
parent 5dba00b761
commit f2ebabaf5f
7 changed files with 127 additions and 12 deletions

View File

@@ -56,6 +56,7 @@ pub fn legalize_signatures(func: &mut Function, isa: &TargetIsa) {
fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
let mut has_sret = false;
let mut has_link = false;
let mut has_vmctx = false;
// Insert position for argument conversion code.
// We want to insert instructions before the first instruction in the entry block.
@@ -86,6 +87,10 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
assert!(!has_sret, "Multiple sret arguments found");
has_sret = true;
}
ArgumentPurpose::VMContext => {
assert!(!has_vmctx, "Multiple vmctx arguments found");
has_vmctx = true;
}
_ => panic!("Unexpected special-purpose arg {}", abi_types[abi_arg]),
}
abi_arg += 1;
@@ -134,7 +139,12 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
assert!(!has_sret, "Multiple sret arguments found");
has_sret = true;
}
ArgumentPurpose::VMContext => {
assert!(!has_vmctx, "Multiple vmctx arguments found");
has_vmctx = true;
}
}
// Just create entry block values to match here. We will use them in `handle_return_abi()`
// below.
func.dfg.append_ebb_arg(entry, arg.value_type);
@@ -503,14 +513,15 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
return false;
}
// Count the special-purpose return values (`link` and `sret`) that were appended to the
// legalized signature.
// Count the special-purpose return values (`link`, `sret`, and `vmctx`) that were appended to
// the legalized signature.
let special_args = sig.return_types
.iter()
.rev()
.take_while(|&rt| {
rt.purpose == ArgumentPurpose::Link ||
rt.purpose == ArgumentPurpose::StructReturn
rt.purpose == ArgumentPurpose::StructReturn ||
rt.purpose == ArgumentPurpose::VMContext
})
.count();
@@ -522,8 +533,8 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
|_, abi_arg| sig.return_types[abi_arg]);
assert_eq!(dfg.inst_variable_args(inst).len(), abi_args);
// Append special return arguments for any `sret` and `link` return values added to the
// legalized signature. These values should simply be propagated from the entry block
// Append special return arguments for any `sret`, `link`, and `vmctx` return values added to
// the legalized signature. These values should simply be propagated from the entry block
// arguments.
if special_args > 0 {
dbg!("Adding {} special-purpose arguments to {}",
@@ -533,13 +544,14 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
for arg in &sig.return_types[abi_args..] {
match arg.purpose {
ArgumentPurpose::Link |
ArgumentPurpose::StructReturn => {}
ArgumentPurpose::StructReturn |
ArgumentPurpose::VMContext => {}
ArgumentPurpose::Normal => panic!("unexpected return value {}", arg),
_ => panic!("Unsupported special purpose return value {}", arg),
}
// A `link` or `sret` return value can only appear in a signature that has a unique
// matching argument. They are appended at the end, so search the signature from the
// end.
// A `link`/`sret`/`vmctx` return value can only appear in a signature that has a
// unique matching argument. They are appended at the end, so search the signature from
// the end.
let idx = sig.argument_types
.iter()
.rposition(|t| t.purpose == arg.purpose)