Add a "colocated" flag to symbol references. (#298)

This adds a "colocated" flag to function and symbolic global variables which
indicates that they are defined along with the current function, so they can
use PC-relative addressing.

This also changes the function decl syntax; the name now always precedes the
signature, and the "function" keyword is no longer included.
This commit is contained in:
Dan Gohman
2018-04-13 15:00:09 -07:00
committed by GitHub
parent 645fa3e858
commit 0e57f3d0ea
46 changed files with 312 additions and 164 deletions

View File

@@ -144,6 +144,7 @@ impl<'a> Context<'a> {
while self.function.global_vars.next_key().index() <= gv.index() {
self.function.create_global_var(GlobalVarData::Sym {
name: ExternalName::testcase(""),
colocated: false,
});
}
self.function.global_vars[gv] = data;
@@ -208,6 +209,7 @@ impl<'a> Context<'a> {
self.function.import_function(ExtFuncData {
name: ExternalName::testcase(""),
signature: SigRef::reserved_value(),
colocated: false,
});
}
self.function.dfg.ext_funcs[fn_] = data;
@@ -760,7 +762,7 @@ impl<'a> Parser<'a> {
// Parse a whole function definition.
//
// function ::= * function-spec "{" preamble function-body "}"
// function ::= * "function" name signature "{" preamble function-body "}"
//
fn parse_function(
&mut self,
@@ -772,10 +774,19 @@ impl<'a> Parser<'a> {
debug_assert!(self.comments.is_empty());
self.start_gathering_comments();
let (location, name, sig) = self.parse_function_spec(unique_isa)?;
self.match_identifier("function", "expected 'function'")?;
let location = self.loc;
// function ::= "function" * name signature "{" preamble function-body "}"
let name = self.parse_external_name()?;
// function ::= "function" name * signature "{" preamble function-body "}"
let sig = self.parse_signature(unique_isa)?;
let mut ctx = Context::new(Function::with_name_signature(name, sig), unique_isa);
// function ::= function-spec * "{" preamble function-body "}"
// function ::= "function" name signature * "{" preamble function-body "}"
self.match_token(
Token::LBrace,
"expected '{' before function body",
@@ -784,11 +795,11 @@ impl<'a> Parser<'a> {
self.token();
self.claim_gathered_comments(AnyEntity::Function);
// function ::= function-spec "{" * preamble function-body "}"
// function ::= "function" name signature "{" * preamble function-body "}"
self.parse_preamble(&mut ctx)?;
// function ::= function-spec "{" preamble * function-body "}"
// function ::= "function" name signature "{" preamble * function-body "}"
self.parse_function_body(&mut ctx)?;
// function ::= function-spec "{" preamble function-body * "}"
// function ::= "function" name signature "{" preamble function-body * "}"
self.match_token(
Token::RBrace,
"expected '}' after function body",
@@ -808,29 +819,9 @@ impl<'a> Parser<'a> {
Ok((ctx.function, details))
}
// Parse a function spec.
//
// function-spec ::= * "function" name signature
//
fn parse_function_spec(
&mut self,
unique_isa: Option<&TargetIsa>,
) -> Result<(Location, ExternalName, Signature)> {
self.match_identifier("function", "expected 'function'")?;
let location = self.loc;
// function-spec ::= "function" * name signature
let name = self.parse_external_name()?;
// function-spec ::= "function" name * signature
let sig = self.parse_signature(unique_isa)?;
Ok((location, name, sig))
}
// Parse an external name.
//
// For example, in a function spec, the parser would be in this state:
// For example, in a function decl, the parser would be in this state:
//
// function ::= "function" * name signature { ... }
//
@@ -1095,7 +1086,7 @@ impl<'a> Parser<'a> {
// global-var-decl ::= * GlobalVar(gv) "=" global-var-desc
// global-var-desc ::= "vmctx" offset32
// | "deref" "(" GlobalVar(base) ")" offset32
// | "globalsym" name
// | globalsym ["colocated"] name
//
fn parse_global_var_decl(&mut self) -> Result<(GlobalVar, GlobalVarData)> {
let gv = self.match_gv("expected global variable number: gv«n»")?;
@@ -1124,8 +1115,9 @@ impl<'a> Parser<'a> {
GlobalVarData::Deref { base, offset }
}
"globalsym" => {
let colocated = self.optional(Token::Identifier("colocated"));
let name = self.parse_external_name()?;
GlobalVarData::Sym { name }
GlobalVarData::Sym { name, colocated }
}
other => return err!(self.loc, "Unknown global variable kind '{}'", other),
};
@@ -1237,8 +1229,8 @@ impl<'a> Parser<'a> {
//
// Two variants:
//
// function-decl ::= FuncRef(fnref) "=" function-spec
// FuncRef(fnref) "=" SigRef(sig) name
// function-decl ::= FuncRef(fnref) "=" ["colocated"]" name function-decl-sig
// function-decl-sig ::= SigRef(sig) | signature
//
// The first variant allocates a new signature reference. The second references an existing
// signature which must be declared first.
@@ -1250,9 +1242,19 @@ impl<'a> Parser<'a> {
"expected '=' in function decl",
)?;
let loc = self.loc;
// function-decl ::= FuncRef(fnref) "=" * ["colocated"] name function-decl-sig
let colocated = self.optional(Token::Identifier("colocated"));
// function-decl ::= FuncRef(fnref) "=" ["colocated"] * name function-decl-sig
let name = self.parse_external_name()?;
// function-decl ::= FuncRef(fnref) "=" ["colocated"] name * function-decl-sig
let data = match self.token() {
Some(Token::Identifier("function")) => {
let (loc, name, sig) = self.parse_function_spec(ctx.unique_isa)?;
Some(Token::LPar) => {
// function-decl ::= FuncRef(fnref) "=" ["colocated"] name * signature
let sig = self.parse_signature(ctx.unique_isa)?;
let sigref = ctx.function.import_signature(sig);
ctx.map.def_entity(sigref.into(), &loc).expect(
"duplicate SigRef entities created",
@@ -1260,6 +1262,7 @@ impl<'a> Parser<'a> {
ExtFuncData {
name,
signature: sigref,
colocated,
}
}
Some(Token::SigRef(sig_src)) => {
@@ -1271,10 +1274,10 @@ impl<'a> Parser<'a> {
};
ctx.check_sig(sig, &self.loc)?;
self.consume();
let name = self.parse_external_name()?;
ExtFuncData {
name,
signature: sig,
colocated,
}
}
_ => return err!(self.loc, "expected 'function' or sig«n» in function decl"),